refactor: split downloader into modules
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { API, DOWNLOAD_DIR } = require('./config');
|
||||
const { fetchJSON } = require('./network');
|
||||
|
||||
async function fetchLyric(songId) {
|
||||
try {
|
||||
const res = await fetchJSON(`${API.lyric}?id=${songId}`);
|
||||
if (res.code !== 200) return null;
|
||||
return res.data;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function mergeLrc(lrc, tlyric) {
|
||||
if (!lrc) return '';
|
||||
if (!tlyric) return lrc;
|
||||
|
||||
const transMap = new Map();
|
||||
for (const line of tlyric.split('\n')) {
|
||||
const match = line.match(/^\[(\d+:\d+[\.:]\d+)\](.*)/);
|
||||
if (match && match[2].trim()) transMap.set(match[1], match[2].trim());
|
||||
}
|
||||
|
||||
const result = [];
|
||||
for (const line of lrc.split('\n')) {
|
||||
result.push(line);
|
||||
const match = line.match(/^\[(\d+:\d+[\.:]\d+)\]/);
|
||||
if (match && transMap.has(match[1])) result.push(`[${match[1]}]${transMap.get(match[1])}`);
|
||||
}
|
||||
return result.join('\n');
|
||||
}
|
||||
|
||||
function parseCredits(lrcText) {
|
||||
const credits = {};
|
||||
if (!lrcText) return credits;
|
||||
const labels = {
|
||||
lyricist: /^(作词|作詞|词|填词|Lyricist|Lyrics? by|Written by)$/i,
|
||||
composer: /^(作曲|曲|Composer|Composed by|Music by)$/i,
|
||||
arranger: /^(编曲|編曲|Arranger|Arranged by)$/i,
|
||||
producer: /^(制作人|製作人|出品人|监制|Producer|Produced by)$/i,
|
||||
mixer: /^(混音|Mix(ing)?|Mixed by)$/i,
|
||||
};
|
||||
for (const raw of lrcText.split('\n')) {
|
||||
const line = raw.replace(/^(\s*\[[^\]]*\]\s*)+/, '').trim();
|
||||
const match = line.match(/^([^::]{1,12})\s*[::]\s*(.+)$/);
|
||||
if (!match) continue;
|
||||
const label = match[1].trim();
|
||||
const value = match[2].trim().replace(/\s*\/\s*/g, '/');
|
||||
if (!value) continue;
|
||||
for (const [key, pattern] of Object.entries(labels)) {
|
||||
if (pattern.test(label) && !credits[key]) {
|
||||
credits[key] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return credits;
|
||||
}
|
||||
|
||||
async function saveLyric(songId, fileName) {
|
||||
const data = await fetchLyric(songId);
|
||||
if (!data?.lrc) {
|
||||
console.log(' ⚠️ 未获取到歌词');
|
||||
return;
|
||||
}
|
||||
|
||||
const lrcPath = path.join(DOWNLOAD_DIR, fileName + '.lrc');
|
||||
fs.writeFileSync(lrcPath, data.lrc, 'utf-8');
|
||||
console.log(` 📄 歌词已保存: ${path.basename(lrcPath)}`);
|
||||
if (data.tlyric?.trim()) {
|
||||
const mergedPath = path.join(DOWNLOAD_DIR, fileName + '.合并翻译.lrc');
|
||||
fs.writeFileSync(mergedPath, mergeLrc(data.lrc, data.tlyric), 'utf-8');
|
||||
console.log(` 📄 翻译歌词已保存: ${path.basename(mergedPath)}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { fetchLyric, mergeLrc, parseCredits, saveLyric };
|
||||
Reference in New Issue
Block a user