feat(音乐链接): 统一使用 TuneHub 格式的音乐页面链接
将网易云和QQ音乐的原始链接替换为 TuneHub 格式的统一链接 在同步任务中优先获取歌曲元数据,避免显示原始URL 增加日志输出以帮助调试链接解析过程
This commit is contained in:
@@ -30,7 +30,7 @@ function normalizeTunehubPlaylist(playlistId, detail) {
|
||||
duration: 0,
|
||||
album: item.album || '',
|
||||
cover,
|
||||
pageUrl: `https://music.163.com/song?id=${item.id}`,
|
||||
pageUrl: `https://music-dl.sayqz.com/?source=netease&id=${item.id}`,
|
||||
playUrl: item.url || '',
|
||||
isBlocked,
|
||||
isCloud: false,
|
||||
|
||||
@@ -7,11 +7,12 @@ function buildPageUrl(source, songId) {
|
||||
if (!source || !songId) {
|
||||
return '';
|
||||
}
|
||||
// 使用 TuneHub 格式的页面 URL
|
||||
if (source === 'netease') {
|
||||
return `https://music.163.com/song?id=${songId}`;
|
||||
return `https://music-dl.sayqz.com/?source=${source}&id=${songId}`;
|
||||
}
|
||||
if (source === 'qq') {
|
||||
return `https://y.qq.com/n/ryqq/songDetail/${songId}`;
|
||||
return `https://music-dl.sayqz.com/?source=${source}&id=${songId}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -64,15 +64,31 @@ async function createJob(req, res) {
|
||||
|
||||
let meta = {};
|
||||
const songId = request.urlJob && request.urlJob.meta.songId ? request.urlJob.meta.songId : "";
|
||||
|
||||
|
||||
// 先从 TuneHub 获取歌曲信息,避免显示原始 URL
|
||||
if (request.urlJob.meta && (request.urlJob.meta.songName !== "" && request.urlJob.meta.artist !== "")) {
|
||||
meta = {
|
||||
songName: request.urlJob.meta.songName,
|
||||
artist: request.urlJob.meta.artist,
|
||||
album : request.urlJob.meta.album ? request.urlJob.meta.album : "",
|
||||
};
|
||||
} else {
|
||||
// 没有前端元数据,先获取歌曲信息
|
||||
logger.info(`[sync_jobs] No meta provided, fetching song info from URL: ${url}`);
|
||||
const songInfo = await require('../service/media_fetcher').getMetaWithUrl(url);
|
||||
if (songInfo && songInfo.songName) {
|
||||
meta = {
|
||||
songName: songInfo.songName,
|
||||
artist: songInfo.artist || "",
|
||||
album: songInfo.album || "",
|
||||
};
|
||||
logger.info(`[sync_jobs] Fetched song info: ${meta.songName} - ${meta.artist}`);
|
||||
} else {
|
||||
logger.warn(`[sync_jobs] Failed to fetch song info from URL, will use URL as fallback`);
|
||||
meta.songName = url; // 备用方案
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (songId) {
|
||||
const songFromWyCloud = await findTheBestMatchFromWyCloud(req.account.uid, {
|
||||
songName: meta.songName,
|
||||
@@ -90,7 +106,7 @@ async function createJob(req, res) {
|
||||
}
|
||||
meta.songFromWyCloud = songFromWyCloud;
|
||||
}
|
||||
|
||||
|
||||
// create job
|
||||
const args = `${jobType}: {"url":${url}}`;
|
||||
if (await JobManager.findActiveJobByArgs(uid, args)) {
|
||||
@@ -108,7 +124,7 @@ async function createJob(req, res) {
|
||||
tip: `等待${operation}`,
|
||||
createdAt: Date.now()
|
||||
});
|
||||
|
||||
|
||||
// async job
|
||||
syncSingleSongWithUrl(req.account.uid, url, meta, jobId, jobType).then(async ret => {
|
||||
await JobManager.updateJob(uid, jobId, {
|
||||
|
||||
@@ -36,25 +36,36 @@ function parseTunehubParams(url) {
|
||||
|
||||
function parsePageUrlParams(url) {
|
||||
if (!url) {
|
||||
logger.error(`[parsePageUrlParams] URL is empty or null`);
|
||||
return null;
|
||||
}
|
||||
logger.info(`[parsePageUrlParams] Parsing URL: ${url}`);
|
||||
|
||||
// 支持网易云音乐PC版和手机版
|
||||
if (url.indexOf('music.163.com') >= 0 || url.indexOf('m.music.163.com') >= 0) {
|
||||
logger.info(`[parsePageUrlParams] Detected Netease domain in URL`);
|
||||
const match = url.match(/id=(\d+)/);
|
||||
if (match && match[1]) {
|
||||
logger.info(`[parsePageUrlParams] Parsed Netease URL: ${url} -> netease:${match[1]}`);
|
||||
return { source: 'netease', id: match[1] };
|
||||
} else {
|
||||
logger.error(`[parsePageUrlParams] Failed to extract song ID from Netease URL: ${url}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 支持QQ音乐
|
||||
if (url.indexOf('y.qq.com') >= 0) {
|
||||
logger.info(`[parsePageUrlParams] Detected QQ domain in URL`);
|
||||
const match = url.match(/songDetail\/([A-Za-z0-9]+)/);
|
||||
if (match && match[1]) {
|
||||
logger.info(`[parsePageUrlParams] Parsed QQ URL: ${url} -> qq:${match[1]}`);
|
||||
return { source: 'qq', id: match[1] };
|
||||
} else {
|
||||
logger.error(`[parsePageUrlParams] Failed to extract song ID from QQ URL: ${url}`);
|
||||
}
|
||||
}
|
||||
logger.info(`[parsePageUrlParams] URL not recognized: ${url}`);
|
||||
|
||||
logger.error(`[parsePageUrlParams] URL not recognized: ${url}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -178,7 +189,14 @@ async function fetchWithUrl(url, {
|
||||
async function getMetaWithUrl(url) {
|
||||
logger.info(`getMetaWithUrl from ${url}`);
|
||||
|
||||
const params = parseTunehubParams(url) || parsePageUrlParams(url);
|
||||
// DEBUG: 添加详细日志
|
||||
logger.info(`[getMetaWithUrl] DEBUG: URL = ${url}`);
|
||||
const tunehubParams = parseTunehubParams(url);
|
||||
logger.info(`[getMetaWithUrl] DEBUG: tunehubParams = ${JSON.stringify(tunehubParams)}`);
|
||||
const pageParams = parsePageUrlParams(url);
|
||||
logger.info(`[getMetaWithUrl] DEBUG: pageParams = ${JSON.stringify(pageParams)}`);
|
||||
|
||||
const params = tunehubParams || pageParams;
|
||||
if (params) {
|
||||
logger.info(`[getMetaWithUrl] Trying TuneHub first for ${params.source}:${params.id}`);
|
||||
const tunehubInfo = await getSongInfo(params.source, params.id);
|
||||
@@ -188,7 +206,8 @@ async function getMetaWithUrl(url) {
|
||||
}
|
||||
logger.warn(`[getMetaWithUrl] TuneHub failed for ${params.source}:${params.id}, will try media-get as fallback`);
|
||||
} else {
|
||||
logger.info(`[getMetaWithUrl] URL not recognized as TuneHub-supported format, trying media-get`);
|
||||
logger.error(`[getMetaWithUrl] ERROR: URL not recognized as TuneHub-supported format: ${url}`);
|
||||
return false; // 直接返回失败,不再调用 media-get
|
||||
}
|
||||
|
||||
// Fallback to media-get only if TuneHub fails or URL format not supported
|
||||
|
||||
@@ -239,7 +239,7 @@ async function getSongsFromPlaylist(uid, source, playlistId) {
|
||||
duration: songInfo.dt / 1000,
|
||||
album: songInfo.al.name,
|
||||
cover: songInfo.al.picUrl,
|
||||
pageUrl: `https://music.163.com/song?id=${songInfo.id}`,
|
||||
pageUrl: `https://music-dl.sayqz.com/?source=netease&id=${songInfo.id}`,
|
||||
playUrl: !isBlocked && !isCloud ? `http://music.163.com/song/media/outer/url?id=${songInfo.id}.mp3` : '', // 不再建议使用这个 url,建议每次都 Call API 获取
|
||||
isBlocked,
|
||||
isCloud,
|
||||
|
||||
Reference in New Issue
Block a user