From dcfd9cc5be90fb64aa2235aacbf787e39a00d4b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8F=B2=E6=82=A6?= Date: Wed, 7 Jan 2026 18:36:15 +0800 Subject: [PATCH] =?UTF-8?q?=20=20-=20=E6=AD=8C=E5=8D=95=E5=88=97=E8=A1=A8/?= =?UTF-8?q?=E6=AD=8C=E6=9B=B2=E8=AF=A6=E6=83=85=E4=BB=8D=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E7=BD=91=E6=98=93=E4=BA=91=E6=8E=A5=E5=8F=A3=EF=BC=88TuneHub?= =?UTF-8?q?=20=E6=B2=A1=E6=9C=89=E6=9D=83=E9=99=90=E4=BF=A1=E6=81=AF/?= =?UTF-8?q?=E8=A2=AB=E5=B0=81=E7=8A=B6=E6=80=81=E7=AD=89=EF=BC=89=EF=BC=8C?= =?UTF-8?q?=E4=B8=8D=E8=83=BD=E7=9B=B4=E6=8E=A5=E6=9B=BF=E6=8D=A2=E3=80=82?= =?UTF-8?q?=20=20=20-=20=E6=92=AD=E6=94=BE/=E4=B8=8B=E8=BD=BD=20URL=20?= =?UTF-8?q?=E5=B7=B2=E4=BC=98=E5=85=88=20TuneHub=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/service/media_fetcher/index.js | 69 +++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/backend/src/service/media_fetcher/index.js b/backend/src/service/media_fetcher/index.js index afa4cff..455f6c5 100644 --- a/backend/src/service/media_fetcher/index.js +++ b/backend/src/service/media_fetcher/index.js @@ -6,6 +6,7 @@ const cmd = require('../../utils/cmd'); const fs = require('fs'); const configManager = require('../config_manager') const downloadFile = require('../../utils/download'); +const { getSongInfo, buildSongUrl } = require('../music_platform/tunehub'); const { getBinPath } = require('./media_get'); @@ -16,6 +17,64 @@ if (!fs.existsSync(basePath)) { } logger.info(`[tmp path] use ${basePath}`) +function parseTunehubParams(url) { + try { + const parsed = new URL(url); + if (!parsed.hostname.includes('music-dl.sayqz.com')) { + return null; + } + const source = parsed.searchParams.get('source'); + const id = parsed.searchParams.get('id'); + if (!source || !id) { + return null; + } + return { source, id }; + } catch (err) { + return null; + } +} + +function parsePageUrlParams(url) { + if (!url) { + return null; + } + if (url.indexOf('music.163.com') >= 0 || url.indexOf('m.music.163.com') >= 0) { + const match = url.match(/id=(\d+)/); + if (match && match[1]) { + return { source: 'netease', id: match[1] }; + } + } + if (url.indexOf('y.qq.com') >= 0) { + const match = url.match(/songDetail\/([A-Za-z0-9]+)/); + if (match && match[1]) { + return { source: 'qq', id: match[1] }; + } + } + return null; +} + +function buildMetaFromTunehub(source, info, url, songId) { + return { + songName: info.name || '', + artist: info.artist || '', + album: info.album || '', + duration: 0, + coverUrl: info.pic || '', + publicTime: '', + isTrial: false, + resourceType: '', + audios: [ + { + url: info.url || buildSongUrl(source, songId), + } + ], + fromMusicPlatform: true, + resourceForbidden: false, + source, + pageUrl: url, + }; +} + async function downloadViaSourceUrl(url) { logger.info(`downloadViaSourceUrl params: url: ${url}`); @@ -82,6 +141,14 @@ async function fetchWithUrl(url, { async function getMetaWithUrl(url) { logger.info(`getMetaWithUrl from ${url}`); + const params = parseTunehubParams(url) || parsePageUrlParams(url); + if (params) { + const tunehubInfo = await getSongInfo(params.source, params.id); + if (tunehubInfo) { + return buildMetaFromTunehub(params.source, tunehubInfo, url, params.id); + } + } + let args = ['-u', `"${url}"`, '-m', '--infoFormat=json', '-l=silence']; const {code, message} = await cmd(getBinPath(), args); @@ -177,4 +244,4 @@ module.exports = { fetchWithUrl: fetchWithUrl, getMetaWithUrl: getMetaWithUrl, searchSongFromAllPlatform: searchSongFromAllPlatform, -} \ No newline at end of file +}