From 6828248d3ae236bb280bb6dccd8899ba3b1474b2 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 14:02:16 +0800 Subject: [PATCH 01/24] feat(subsonic): add star/unstar red-heart write, ported from feat/subsonic to github-dev Add Subsonic endpoints star and unstar, reusing new handleStar. Songs are added/removed to the My-Favorites (love) list and persisted via createSnapshot. Song-only; album/artist starring skipped because github-dev lacks the meta subsystem. Fixes the previous 'Method not found: star' error. --- src/server/subsonic.ts | 68 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 6d9adf15..d4d8db14 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -317,6 +317,12 @@ class SubsonicHandler { case 'getStarred2': return this.handleGetStarred(res, username, format, true) + case 'star': + return this.handleStar(res, username, params, format, true) + + case 'unstar': + return this.handleStar(res, username, params, format, false) + case 'getRandomSongs': case 'getSongsByGenre': case 'getSongsByGenre2': @@ -1917,6 +1923,68 @@ class SubsonicHandler { }, format) } + /** + * star / unstar:歌曲 → 「我的收藏(love)」列表 + * (github/dev 移植自 feat/subsonic 的精简版:仅支持歌曲,专辑/歌手星标暂跳过) + */ + private async handleStar(res: http.ServerResponse, username: string, params: URLSearchParams, format: string, isStar: boolean) { + // 收集 id / albumId / artistId(均允许逗号分隔的多个值) + const ids: string[] = [] + for (const key of ['id', 'albumId', 'artistId']) { + for (const value of params.getAll(key)) { + for (const one of value.split(',')) { + const trimmed = one.trim() + if (trimmed) ids.push(trimmed) + } + } + } + if (!ids.length) return this.sendError(res, 10, 'Required parameter is missing: id', format) + + const userSpace = getUserSpace(username) + const location = (global.lx.config['list.addMusicLocationType'] || 'bottom') as 'top' | 'bottom' + let loveChanged = false + const action = isStar ? 'star' : 'unstar' + const debug = !!global.lx.config['subsonic.enableDebug'] + const debugLog = (msg: string) => { if (debug) console.log(msg) } + + for (const id of ids) { + if (id.startsWith('alb_') || id.startsWith('art_')) { + // github/dev 未实现专辑/歌手星标元数据,跳过 + debugLog(`[Subsonic Debug] ${action} 专辑/歌手 ${id} 暂不支持,已跳过 (user=${username})`) + continue + } + try { + const hit = await this.findMusicById(username, id) + const resolved = hit?.music || null + if (!resolved) { + console.warn(`[Subsonic] ${action} 歌曲 ${id} 跳过:findMusicById 未命中,未做任何改动 (user=${username})`) + continue + } + if (isStar) { + await userSpace.listManage.listDataManage.listMusicAdd('love', [resolved], location) + } else { + await userSpace.listManage.listDataManage.listMusicRemove('love', [resolved.id]) + } + debugLog(`[Subsonic Debug] ${action} 歌曲 ${id} -> ${isStar ? '已加入' : '已移出'}我的收藏(love) 《${resolved.name}》(user=${username})`) + this.cacheOnlineSong(resolved) + loveChanged = true + } catch (e) { + console.error(`[Subsonic] ${action} song error (${id}):`, e) + } + } + + if (loveChanged) { + try { + await userSpace.listManage.createSnapshot() + } catch (e) { + console.error('[Subsonic] createSnapshot error:', e) + } + } + + debugLog(`[Subsonic Debug] ${action} 完成: id 数=${ids.length}, 收藏变更=${loveChanged} (user=${username})`) + return this.sendResponse(res, {}, format) + } + private async handleGetStarred(res: http.ServerResponse, username: string, format: string, isV2 = true) { const userSpace = getUserSpace(username) const listData = await userSpace.listManage.getListData() From 45629afb0ee5fd5bfde0347cdf7b1f35e306eee0 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 14:19:04 +0800 Subject: [PATCH 02/24] feat(subsonic): add online fallback resolution for star/unstar (github-dev) Add resolveMusicById (tx/wy/kg/mg) and resolveSongMeta. handleStar now resolves any song id via local lists first, then the online music source, so songs not yet in any list can be starred. Online-resolved songs are added to the love list with listId 'online'. --- src/server/subsonic.ts | 89 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 85 insertions(+), 4 deletions(-) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index d4d8db14..065cf65b 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -10,6 +10,10 @@ import fs from 'fs' import path from 'path' // @ts-ignore import musicSdkRaw from '@/modules/utils/musicSdk/index.js' +import txMusicInfo from '@/modules/utils/musicSdk/tx/musicInfo.js' +import wyMusicInfo from '@/modules/utils/musicSdk/wy/musicInfo.js' +import { getMusicInfo as kgGetMusicInfo } from '@/modules/utils/musicSdk/kg/musicInfo.js' +import { getMusicInfo as mgGetMusicInfo } from '@/modules/utils/musicSdk/mg/musicInfo.js' const musicSdk = musicSdkRaw as any /** @@ -1923,9 +1927,85 @@ class SubsonicHandler { }, format) } + /** + * 按歌曲 id 从各音源在线回源取单曲信息(github/dev 移植自 feat/subsonic) + * 支持 tx / wy / kg / mg;其它源(kw/bd/xm 等)无可靠「按 id 取单曲」接口,直接放弃。 + */ + private async resolveMusicById(id: string): Promise { + const idx = id.indexOf('_') + if (idx <= 0) return null + const source = id.slice(0, idx) + const songId = id.slice(idx + 1) + if (!songId) return null + try { + let music: any = null + switch (source) { + case 'tx': + music = await txMusicInfo(songId) + break + case 'wy': { + // wy/musicInfo.js 返回的是 requestObj,真实数据在 .promise 里 + const raw: any = await (wyMusicInfo(songId) as any).promise + if (raw) { + music = { + id: `wy_${songId}`, + name: raw.name, + singer: raw.artists ? raw.artists.map((a: any) => a.name).join('、') : '', + source: 'wy', + songmid: songId, + interval: raw.dt ? String(Math.round(raw.dt / 1000)) : '0', + img: raw.album?.picUrl ?? null, + meta: { + albumName: raw.album?.name, + albumId: raw.album?.id, + picUrl: raw.album?.picUrl, + }, + } + } + break + } + case 'kg': + music = await kgGetMusicInfo(songId) + break + case 'mg': + music = await mgGetMusicInfo(songId) + break + default: + return null + } + if (!music) return null + if (!music.source) music.source = source + if (!music.id) music.id = `${source}_${music.songmid || music.songId || songId}` + if (!music.songmid) music.songmid = music.songId || songId + if (!music.name) { + console.warn(`[Subsonic] resolveMusicById ${id} 取回结果缺少歌名,已放弃(不写入收藏)`) + return null + } + return music as LX.Music.MusicInfo + } catch (e) { + console.warn(`[Subsonic] resolveMusicById ${id} 失败:`, (e as Error).message) + return null + } + } + + /** 统一元数据解析原语:本地/缓存 -> 在线回源;命中即回写 onlineSongCache */ + private async resolveSongMeta(username: string, id: string): Promise<{ music: LX.Music.MusicInfo, listId: string } | null> { + const found = await this.findMusicById(username, id) + if (found) { + this.cacheOnlineSong(found.music) + return found + } + const resolved = await this.resolveMusicById(id) + if (resolved) { + this.cacheOnlineSong(resolved) + return { music: resolved, listId: 'online' } + } + return null + } + /** * star / unstar:歌曲 → 「我的收藏(love)」列表 - * (github/dev 移植自 feat/subsonic 的精简版:仅支持歌曲,专辑/歌手星标暂跳过) + * (github/dev 移植自 feat/subsonic:歌曲经 resolveSongMeta 解析,支持在线回源) */ private async handleStar(res: http.ServerResponse, username: string, params: URLSearchParams, format: string, isStar: boolean) { // 收集 id / albumId / artistId(均允许逗号分隔的多个值) @@ -1954,10 +2034,10 @@ class SubsonicHandler { continue } try { - const hit = await this.findMusicById(username, id) + const hit = await this.resolveSongMeta(username, id) const resolved = hit?.music || null if (!resolved) { - console.warn(`[Subsonic] ${action} 歌曲 ${id} 跳过:findMusicById 未命中,未做任何改动 (user=${username})`) + console.warn(`[Subsonic] ${action} 歌曲 ${id} 跳过:findMusicById 未命中 且 resolveMusicById 失败,未做任何改动 (user=${username})`) continue } if (isStar) { @@ -1965,7 +2045,8 @@ class SubsonicHandler { } else { await userSpace.listManage.listDataManage.listMusicRemove('love', [resolved.id]) } - debugLog(`[Subsonic Debug] ${action} 歌曲 ${id} -> ${isStar ? '已加入' : '已移出'}我的收藏(love) 《${resolved.name}》(user=${username})`) + const fromSource = hit!.listId === 'online' + debugLog(`[Subsonic Debug] ${action} 歌曲 ${id} -> ${isStar ? '已加入' : '已移出'}我的收藏(love) 《${resolved.name}》${fromSource ? ' (从源取回)' : ''}(user=${username})`) this.cacheOnlineSong(resolved) loveChanged = true } catch (e) { From 8af9488f74b50690dfaf487869287429c1378adc Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 14:27:03 +0800 Subject: [PATCH 03/24] feat(subsonic): add album/artist star/unstar with meta persistence (github-dev) Port getUserMetaFilePath/getUserSubsonicMeta/saveUserSubsonicMeta. handleStar now stars albums (alb_*) and artists (art_*) by storing starred sets in subsonic-meta.json. getStarred/getStarred2 now filter library albums/artists by the actual starred sets (correct Subsonic semantics; browsing stays via getArtists/getAlbumList2). --- src/server/subsonic.ts | 106 +++++++++++++++++++++++++++++++---------- 1 file changed, 82 insertions(+), 24 deletions(-) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 065cf65b..b634ed86 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -2007,6 +2007,39 @@ class SubsonicHandler { * star / unstar:歌曲 → 「我的收藏(love)」列表 * (github/dev 移植自 feat/subsonic:歌曲经 resolveSongMeta 解析,支持在线回源) */ + private getUserMetaFilePath(username: string): string { + return path.join(global.lx.userPath, getUserDirname(username), 'subsonic-meta.json') + } + + /** 用户维度 Subsonic 扩展元数据:星标专辑 / 星标歌手 */ + private async getUserSubsonicMeta(username: string): Promise<{ starredAlbums: string[], starredArtists: string[], ratings: Record }> { + try { + const filePath = this.getUserMetaFilePath(username) + if (fs.existsSync(filePath)) { + const data = JSON.parse(fs.readFileSync(filePath, 'utf8')) + return { + starredAlbums: Array.isArray(data.starredAlbums) ? data.starredAlbums : [], + starredArtists: Array.isArray(data.starredArtists) ? data.starredArtists : [], + ratings: data.ratings && typeof data.ratings === 'object' ? data.ratings : {}, + } + } + } catch (e) { + console.error('[Subsonic] Failed to read subsonic-meta.json:', e) + } + return { starredAlbums: [], starredArtists: [], ratings: {} } + } + + private async saveUserSubsonicMeta(username: string, meta: { starredAlbums: string[], starredArtists: string[], ratings: Record }) { + try { + const filePath = this.getUserMetaFilePath(username) + const dirPath = path.dirname(filePath) + if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }) + fs.writeFileSync(filePath, JSON.stringify(meta), 'utf8') + } catch (e) { + console.error('[Subsonic] Failed to write subsonic-meta.json:', e) + } + } + private async handleStar(res: http.ServerResponse, username: string, params: URLSearchParams, format: string, isStar: boolean) { // 收集 id / albumId / artistId(均允许逗号分隔的多个值) const ids: string[] = [] @@ -2021,16 +2054,27 @@ class SubsonicHandler { if (!ids.length) return this.sendError(res, 10, 'Required parameter is missing: id', format) const userSpace = getUserSpace(username) + const meta = await this.getUserSubsonicMeta(username) + const starredAlbums = new Set(meta.starredAlbums) + const starredArtists = new Set(meta.starredArtists) const location = (global.lx.config['list.addMusicLocationType'] || 'bottom') as 'top' | 'bottom' let loveChanged = false + let metaChanged = false const action = isStar ? 'star' : 'unstar' const debug = !!global.lx.config['subsonic.enableDebug'] const debugLog = (msg: string) => { if (debug) console.log(msg) } for (const id of ids) { - if (id.startsWith('alb_') || id.startsWith('art_')) { - // github/dev 未实现专辑/歌手星标元数据,跳过 - debugLog(`[Subsonic Debug] ${action} 专辑/歌手 ${id} 暂不支持,已跳过 (user=${username})`) + if (id.startsWith('alb_')) { + isStar ? starredAlbums.add(id) : starredAlbums.delete(id) + metaChanged = true + debugLog(`[Subsonic Debug] ${action} 专辑 ${id} -> ${isStar ? '已星标' : '已取消星标'} (user=${username})`) + continue + } + if (id.startsWith('art_')) { + isStar ? starredArtists.add(id) : starredArtists.delete(id) + metaChanged = true + debugLog(`[Subsonic Debug] ${action} 歌手 ${id} -> ${isStar ? '已星标' : '已取消星标'} (user=${username})`) continue } try { @@ -2054,6 +2098,13 @@ class SubsonicHandler { } } + if (metaChanged) { + await this.saveUserSubsonicMeta(username, { + starredAlbums: Array.from(starredAlbums), + starredArtists: Array.from(starredArtists), + ratings: meta.ratings, + }) + } if (loveChanged) { try { await userSpace.listManage.createSnapshot() @@ -2062,13 +2113,16 @@ class SubsonicHandler { } } - debugLog(`[Subsonic Debug] ${action} 完成: id 数=${ids.length}, 收藏变更=${loveChanged} (user=${username})`) + debugLog(`[Subsonic Debug] ${action} 完成: id 数=${ids.length}, 收藏变更=${loveChanged}, 星标元数据变更=${metaChanged} (user=${username})`) return this.sendResponse(res, {}, format) } private async handleGetStarred(res: http.ServerResponse, username: string, format: string, isV2 = true) { const userSpace = getUserSpace(username) const listData = await userSpace.listManage.getListData() + const meta = await this.getUserSubsonicMeta(username) + const starredAlbumSet = new Set(meta.starredAlbums) + const starredArtistSet = new Set(meta.starredArtists) // [汇总所有歌单歌曲] const allSongsMap = new Map() @@ -2090,27 +2144,31 @@ class SubsonicHandler { const libArtists = await this.getLibraryData(username, 'artists') const libAlbums = await this.getLibraryData(username, 'albums') - const mappedArtists = libArtists.map(a => { - const id = `art_${a.source || 'wy'}_${a.id}` - return { - id, - name: a.name, - coverArt: id - } - }) + const mappedArtists = libArtists + .filter(a => starredArtistSet.has(`art_${a.source || 'wy'}_${a.id}`)) + .map(a => { + const id = `art_${a.source || 'wy'}_${a.id}` + return { + id, + name: a.name, + coverArt: id + } + }) - const mappedAlbums = libAlbums.map(a => { - const source = a.source || 'wy' - const primarySinger = (a.artistName || '').split('、')[0] || 'Unknown Artist' - const artistId = a.singerId ? `art_${source}_${a.singerId}` : `artist_${primarySinger}` - return { - id: `alb_${source}_${a.id}`, - name: a.name, - artist: a.artistName, - artistId: artistId, - coverArt: a.picUrl || `alb_${source}_${a.id}` - } - }) + const mappedAlbums = libAlbums + .filter(a => starredAlbumSet.has(`alb_${(a.source || 'wy')}_${a.id}`)) + .map(a => { + const source = a.source || 'wy' + const primarySinger = (a.artistName || '').split('、')[0] || 'Unknown Artist' + const artistId = a.singerId ? `art_${source}_${a.singerId}` : `artist_${primarySinger}` + return { + id: `alb_${source}_${a.id}`, + name: a.name, + artist: a.artistName, + artistId: artistId, + coverArt: a.picUrl || `alb_${source}_${a.id}` + } + }) const wrapKey = isV2 ? 'starred2' : 'starred' From 5404016d0d7f63e78e75cdb2919353b55a489d65 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 16:01:53 +0800 Subject: [PATCH 04/24] fix(subsonic): reflect starred state in artist/album listings and backfill cover images --- src/server/server.ts | 106 +++++++++++- src/server/subsonic.ts | 356 +++++++++++++++++++++++++++++++++++------ 2 files changed, 407 insertions(+), 55 deletions(-) diff --git a/src/server/server.ts b/src/server/server.ts index 24562190..40373aee 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -36,6 +36,22 @@ const playerSessions = new Map() const SESSION_TTL = 24 * 60 * 60 * 1000 // 24小时 const SESSION_COOKIE_NAME = 'lx_player_session' +// 收藏歌手列表头像补全:内存缓存(避免每次刷新重复请求音源) +const artistPicCache = new Map() +function extractArtistPic(d: any): string | null { + if (!d || typeof d !== 'object') return null + return d.avatar || d.img || d.pic || d.picUrl || d.picture || d.image || d.cover || null +} + +// 收藏专辑列表封面补全:内存缓存(best-effort:取专辑歌曲列表首曲 img) +const albumPicCache = new Map() +function extractAlbumPic(d: any): string | null { + const first = d?.list?.[0] + const candidates = [first?.img, first?.meta?.img, d?.info?.img, d?.img, d?.pic, d?.cover, d?.coverUrl] + for (const v of candidates) if (typeof v === 'string' && v) return v + return null +} + /** 生成随机 sessionId */ const generateSessionId = () => crypto.randomBytes(32).toString('hex') @@ -2079,7 +2095,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro return username || '_open' } - // GET /api/user/library/artists — 读取收藏歌手列表 + // GET /api/user/library/artists — 读取收藏歌手列表(自动补全缺失头像 picUrl) if (pathname === '/api/user/library/artists' && req.method === 'GET') { const username = getLibUsername(req) if (!username) { res.writeHead(401); res.end('Unauthorized'); return } @@ -2091,8 +2107,31 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro if (!fs.existsSync(filePath)) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('[]'); return } - const data = fs.readFileSync(filePath, 'utf-8') - res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(data) + let arr: any[] = JSON.parse(fs.readFileSync(filePath, 'utf-8')) + if (!Array.isArray(arr)) arr = [] + // [修复] 对没有可用 picUrl 的歌手,实时从音源拉取头像并补全(带内存缓存,单条失败不影响整体) + const needFetch = arr.filter((a: any) => a && a.id != null && a.source && + !(a.picUrl && /^https?:\/\//.test(String(a.picUrl)))) + let changed = false + if (needFetch.length) { + await Promise.all(needFetch.map(async (a: any) => { + const key = `${a.source}::${a.id}` + try { + let pic: string | null = artistPicCache.get(key) ?? null + if (!pic) { + const detail = await musicSdk[a.source]?.extendDetail?.getArtistDetail?.(String(a.id)) + pic = extractArtistPic(detail) || null + if (pic) artistPicCache.set(key, pic) + } + if (pic) { a.picUrl = pic; changed = true } + } catch (e) { /* 忽略单个歌手的拉取失败 */ } + })) + // 将补全后的 picUrl 持久化回文件:每个歌手最多实时查一次,之后永久生效(重启也不再查询) + if (changed) { + try { fs.writeFileSync(filePath, JSON.stringify(arr, null, 2), 'utf-8') } catch { /* ignore */ } + } + } + res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(arr)) } catch (e: any) { res.writeHead(500); res.end(e.message) } return } @@ -2108,7 +2147,22 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro const userDirname = getUserDirname(username) const libDir = path.join(global.lx.userPath, userDirname, 'library') if (!fs.existsSync(libDir)) fs.mkdirSync(libDir, { recursive: true }) - fs.writeFileSync(path.join(libDir, 'artists.json'), JSON.stringify(parsed, null, 2), 'utf-8') + const filePath = path.join(libDir, 'artists.json') + // 反向同步:对比旧数据计算增量,回写 Subsonic 星标 + let oldArr: any[] = [] + try { if (fs.existsSync(filePath)) oldArr = JSON.parse(fs.readFileSync(filePath, 'utf8')) } catch { /* ignore */ } + const keyOf = (x: any) => `${x.source}::${String(x.id)}` + const oldKeys = new Set(oldArr.map(keyOf)) + const newKeys = new Set(parsed.map(keyOf)) + const added = parsed.filter((x: any) => !oldKeys.has(keyOf(x))) + const removed = oldArr.filter((x: any) => !newKeys.has(keyOf(x))) + fs.writeFileSync(filePath, JSON.stringify(parsed, null, 2), 'utf-8') + try { + const { syncNativeLibraryToSubsonic } = require('./subsonic') + syncNativeLibraryToSubsonic(username, 'artists', + added.map((a: any) => ({ id: String(a.id), source: a.source, name: a.name })), + removed.map((a: any) => ({ id: String(a.id), source: a.source, name: a.name }))) + } catch (e: any) { console.error('[Library] 反向同步 Subsonic 星标失败:', e) } res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true })) } catch (e: any) { res.writeHead(400); res.end(e.message) } }) @@ -2127,8 +2181,31 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro if (!fs.existsSync(filePath)) { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('[]'); return } - const data = fs.readFileSync(filePath, 'utf-8') - res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(data) + let arr: any[] = JSON.parse(fs.readFileSync(filePath, 'utf-8')) + if (!Array.isArray(arr)) arr = [] + // [修复] 对没有可用 picUrl 的专辑,实时从音源拉取封面并补全(best-effort,带内存缓存,单条失败不影响整体) + const needFetch = arr.filter((a: any) => a && a.id != null && a.source && + !(a.picUrl && /^https?:\/\//.test(String(a.picUrl)))) + let changed = false + if (needFetch.length) { + await Promise.all(needFetch.map(async (a: any) => { + const key = `${a.source}::${a.id}` + try { + let pic: string | null = albumPicCache.get(key) ?? null + if (!pic) { + const detail = await musicSdk[a.source]?.extendDetail?.getAlbumSongs?.(String(a.id)) + pic = extractAlbumPic(detail) || null + if (pic) albumPicCache.set(key, pic) + } + if (pic) { a.picUrl = pic; changed = true } + } catch (e) { /* 忽略单个专辑的拉取失败 */ } + })) + // 将补全后的 picUrl 持久化回文件:每个专辑最多实时查一次,之后永久生效(重启也不再查询) + if (changed) { + try { fs.writeFileSync(filePath, JSON.stringify(arr, null, 2), 'utf-8') } catch { /* ignore */ } + } + } + res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(arr)) } catch (e: any) { res.writeHead(500); res.end(e.message) } return } @@ -2144,7 +2221,22 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro const userDirname = getUserDirname(username) const libDir = path.join(global.lx.userPath, userDirname, 'library') if (!fs.existsSync(libDir)) fs.mkdirSync(libDir, { recursive: true }) - fs.writeFileSync(path.join(libDir, 'albums.json'), JSON.stringify(parsed, null, 2), 'utf-8') + const filePath = path.join(libDir, 'albums.json') + // 反向同步:对比旧数据计算增量,回写 Subsonic 星标 + let oldArr: any[] = [] + try { if (fs.existsSync(filePath)) oldArr = JSON.parse(fs.readFileSync(filePath, 'utf8')) } catch { /* ignore */ } + const keyOf = (x: any) => `${x.source}::${String(x.id)}` + const oldKeys = new Set(oldArr.map(keyOf)) + const newKeys = new Set(parsed.map(keyOf)) + const added = parsed.filter((x: any) => !oldKeys.has(keyOf(x))) + const removed = oldArr.filter((x: any) => !newKeys.has(keyOf(x))) + fs.writeFileSync(filePath, JSON.stringify(parsed, null, 2), 'utf-8') + try { + const { syncNativeLibraryToSubsonic } = require('./subsonic') + syncNativeLibraryToSubsonic(username, 'albums', + added.map((a: any) => ({ id: String(a.id), source: a.source, name: a.name })), + removed.map((a: any) => ({ id: String(a.id), source: a.source, name: a.name }))) + } catch (e: any) { console.error('[Library] 反向同步 Subsonic 星标失败:', e) } res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ success: true })) } catch (e: any) { res.writeHead(400); res.end(e.message) } }) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index b634ed86..08524d1b 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -16,6 +16,111 @@ import { getMusicInfo as kgGetMusicInfo } from '@/modules/utils/musicSdk/kg/musi import { getMusicInfo as mgGetMusicInfo } from '@/modules/utils/musicSdk/mg/musicInfo.js' const musicSdk = musicSdkRaw as any +// ───────────────────────────────────────────── +// 图片字段提取助手(星标写回原生收藏时,从源头补齐歌手头像 / 专辑封面) +// ───────────────────────────────────────────── + +/** 从歌手详情对象中提取头像地址,兼容各音源字段(wy/tx 均返回 avatar) */ +function extractArtistImage(info: any): string { + if (!info || typeof info !== 'object') return '' + return info.avatar || info.img || info.pic || info.picUrl || info.imageUrl || info.cover || info.coverUrl || '' +} + +/** 从专辑歌曲列表返回中提取专辑封面(best-effort:取首曲 img),兼容各音源字段 */ +function extractAlbumImage(data: any): string { + const first = data?.list?.[0] + const candidates = [first?.img, first?.meta?.img, data?.info?.img, data?.img, data?.pic, data?.cover, data?.coverUrl] + for (const v of candidates) { + if (typeof v === 'string' && v) return v + } + return '' +} + +// ───────────────────────────────────────────── +// 模块级:Subsonic 元数据 I/O 与双向同步 +// 供 SubsonicHandler 与 server.ts 的媒体库收藏接口共用, +// 实现「音流星标 ↔ 网页前端原生收藏」双向互通。 +// ───────────────────────────────────────────── + +export interface SubsonicMeta { + starredAlbums: string[] + starredArtists: string[] + starredArtistNames: string[] + ratings: Record +} + +function normalizeSubsonicName(name: string): string { + return (name || '').trim().toLowerCase() +} + +export function getSubsonicMetaFilePath(username: string): string { + return path.join(global.lx.userPath, getUserDirname(username), 'subsonic-meta.json') +} + +export function readSubsonicMeta(username: string): SubsonicMeta { + try { + const filePath = getSubsonicMetaFilePath(username) + if (fs.existsSync(filePath)) { + const data = JSON.parse(fs.readFileSync(filePath, 'utf8')) + return { + starredAlbums: Array.isArray(data.starredAlbums) ? data.starredAlbums : [], + starredArtists: Array.isArray(data.starredArtists) ? data.starredArtists : [], + // 兼容旧版元数据:starredArtistNames 可能为 undefined + starredArtistNames: Array.isArray(data.starredArtistNames) ? data.starredArtistNames : [], + ratings: data.ratings && typeof data.ratings === 'object' ? data.ratings : {}, + } + } + } catch (e) { + console.error('[Subsonic] Failed to read subsonic-meta.json:', e) + } + return { starredAlbums: [], starredArtists: [], starredArtistNames: [], ratings: {} } +} + +export function writeSubsonicMeta(username: string, meta: SubsonicMeta) { + try { + const filePath = getSubsonicMetaFilePath(username) + const dirPath = path.dirname(filePath) + if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }) + fs.writeFileSync(filePath, JSON.stringify(meta), 'utf8') + } catch (e) { + console.error('[Subsonic] Failed to write subsonic-meta.json:', e) + } +} + +/** + * 反向同步:网页前端原生收藏(媒体库 artists/albums)变更 -> Subsonic 星标。 + * added/removed 为原生条目 {id, source, name}。 + */ +export function syncNativeLibraryToSubsonic( + username: string, + type: 'artists' | 'albums', + added: { id: string, source: string, name?: string }[], + removed: { id: string, source: string, name?: string }[], +) { + const meta = readSubsonicMeta(username) + const artistNames = new Set(meta.starredArtistNames) + if (type === 'artists') { + const set = new Set(meta.starredArtists) + for (const a of added) { + set.add(`art_${a.source}_${a.id}`) + if (a.name) artistNames.add(normalizeSubsonicName(a.name)) + } + for (const a of removed) { + set.delete(`art_${a.source}_${a.id}`) + if (a.name) artistNames.delete(normalizeSubsonicName(a.name)) + } + meta.starredArtists = Array.from(set) + } else { + const set = new Set(meta.starredAlbums) + for (const a of added) set.add(`alb_${a.source}_${a.id}`) + for (const a of removed) set.delete(`alb_${a.source}_${a.id}`) + meta.starredAlbums = Array.from(set) + } + meta.starredArtistNames = Array.from(artistNames) + writeSubsonicMeta(username, meta) + console.log(`[Subsonic] 原生收藏(${type}) -> 星标 同步完成: +${added.length} / -${removed.length} (user=${username})`) +} + /** * Subsonic 协议处理器 * 实现了 OpenSubsonic 核心 API 集成 @@ -38,6 +143,9 @@ class SubsonicHandler { // 固定同一关键词的在线结果顺序,避免客户端翻页时出现重复或跳项。 private onlineSearchCache = new Map() + // 当前用户 love 列表歌曲 id 集合缓存,用于歌曲序列化时标记 starred(按用户名隔离,避免并发串号) + private loveIdSets = new Map>() + private cacheOnlineSong(music: LX.Music.MusicInfo) { if (!music || !music.id) return if (this.onlineSongCache.size > 5000) { @@ -228,6 +336,17 @@ class SubsonicHandler { const { pathname } = urlObj const method = pathname.split('/').pop()?.split('.')[0] || '' + + // [starred] 预先计算当前用户 love 列表歌曲 id 集合,供歌曲序列化标记 starred(排除热路径方法) + if (!['ping', 'getLicense', 'stream', 'download', 'getCoverArt'].includes(method)) { + try { + const listData = await getUserSpace(username).listManage.getListData() + this.loveIdSets.set(username, new Set((listData.loveList || []).map((m: any) => m.id))) + } catch (e) { + console.error('[Subsonic] 计算 love 列表失败:', e) + } + } + const logId = params.get('id') const logQuery = params.get('query') const logArtist = params.get('artist') @@ -388,6 +507,41 @@ class SubsonicHandler { } } + /** 写回原生媒体库收藏文件(artists.json / albums.json),用于双向同步 */ + private async writeLibraryData(username: string, type: 'artists' | 'albums', data: any[]): Promise { + const userDir = path.join(global.lx.userPath, getUserDirname(username)) + const libPath = path.join(userDir, 'library', `${type}.json`) + const dir = path.dirname(libPath) + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }) + fs.writeFileSync(libPath, JSON.stringify(data, null, 2), 'utf8') + } + + /** 解析专辑信息(Subsonic 星标写回原生收藏时填充名称与封面;失败返回 name:null 不阻断星标) */ + private async resolveAlbumInfo(source: string, realId: string): Promise<{ name: string | null, picUrl: string }> { + try { + const sdk = (musicSdk as any)[source] + if (sdk?.extendDetail?.getAlbumSongs) { + const data = await sdk.extendDetail.getAlbumSongs(realId) + const name = data?.name || data?.list?.[0]?.albumName || data?.list?.[0]?.meta?.albumName || null + const picUrl = extractAlbumImage(data) + return { name, picUrl } + } + } catch { /* 解析失败不阻断主流程 */ } + return { name: null, picUrl: '' } + } + + /** 星标写回原生收藏时取歌手头像;失败返回 '' 不阻断星标 */ + private async resolveArtistPicUrl(source: string, realId: string): Promise { + try { + const sdk = (musicSdk as any)[source] + if (sdk?.extendDetail?.getArtistDetail) { + const info = await sdk.extendDetail.getArtistDetail(realId) + return extractArtistImage(info) + } + } catch { /* 取图失败不阻断主流程 */ } + return '' + } + private parseDuration(interval: any): number { if (!interval) return 0 if (typeof interval === 'number') return interval @@ -1314,14 +1468,23 @@ class SubsonicHandler { private async handleGetArtists(res: http.ServerResponse, username: string, format: string) { // [修改] 歌手列表首选来自收藏的歌手库 const libArtists = await this.getLibraryData(username, 'artists') + // [修复] 标记已收藏歌手,让 Subsonic 客户端(音流/Ultrasonic 等)能显示爱心高亮 + const meta = await this.getUserSubsonicMeta(username) + const starredArtistSet = new Set(meta.starredArtists) + const starredArtistNameSet = new Set(meta.starredArtistNames) + const isArtistStarred = (source: string, id: string, name: string) => + starredArtistSet.has(`art_${source || 'wy'}_${id}`) || + starredArtistNameSet.has(this.normalizeArtistName(name)) const artists = libArtists.map(artist => { const id = `art_${artist.source || 'wy'}_${artist.id}` + const starred = isArtistStarred(artist.source, artist.id, artist.name) return { id: id, name: artist.name, albumCount: 0, coverArt: id, artistImageUrl: artist.picUrl || artist.img, + ...(starred ? { starred: new Date().toISOString() } : {}), } }) @@ -1365,6 +1528,11 @@ class SubsonicHandler { const id = params.get('id') if (!id) return this.sendError(res, 10, 'Required parameter is missing: id', format) + // [修复] 收藏元数据:用于判断当前歌手是否已收藏(客户端爱心高亮) + const meta = await this.getUserSubsonicMeta(username) + const starredArtistSet = new Set(meta.starredArtists) + const starredArtistNameSet = new Set(meta.starredArtistNames) + let source = 'wy' let artistId = '' let singerName = 'Unknown' @@ -1477,13 +1645,16 @@ class SubsonicHandler { } */ + const artistStarred = starredArtistSet.has(resolvedId) || + starredArtistNameSet.has(this.normalizeArtistName(singerName)) const artistInfo = { id, name: singerName, albumCount: albums.length, songCount: hotSongs.length, coverArt: resolvedId, - artistImageUrl: artistPic || resolvedId + artistImageUrl: artistPic || resolvedId, + ...(artistStarred ? { starred: new Date().toISOString() } : {}), } // 这里的关键:Subsonic getArtist 响应中可以包含 album 和 song @@ -2007,37 +2178,45 @@ class SubsonicHandler { * star / unstar:歌曲 → 「我的收藏(love)」列表 * (github/dev 移植自 feat/subsonic:歌曲经 resolveSongMeta 解析,支持在线回源) */ - private getUserMetaFilePath(username: string): string { - return path.join(global.lx.userPath, getUserDirname(username), 'subsonic-meta.json') + /** 用户维度 Subsonic 扩展元数据:星标专辑 / 星标歌手(委托模块级函数,便于 server.ts 反向同步共用) */ + private async getUserSubsonicMeta(username: string): Promise<{ starredAlbums: string[], starredArtists: string[], starredArtistNames: string[], ratings: Record }> { + return readSubsonicMeta(username) } - /** 用户维度 Subsonic 扩展元数据:星标专辑 / 星标歌手 */ - private async getUserSubsonicMeta(username: string): Promise<{ starredAlbums: string[], starredArtists: string[], ratings: Record }> { - try { - const filePath = this.getUserMetaFilePath(username) - if (fs.existsSync(filePath)) { - const data = JSON.parse(fs.readFileSync(filePath, 'utf8')) - return { - starredAlbums: Array.isArray(data.starredAlbums) ? data.starredAlbums : [], - starredArtists: Array.isArray(data.starredArtists) ? data.starredArtists : [], - ratings: data.ratings && typeof data.ratings === 'object' ? data.ratings : {}, - } - } - } catch (e) { - console.error('[Subsonic] Failed to read subsonic-meta.json:', e) - } - return { starredAlbums: [], starredArtists: [], ratings: {} } + private async saveUserSubsonicMeta(username: string, meta: { starredAlbums: string[], starredArtists: string[], starredArtistNames: string[], ratings: Record }) { + writeSubsonicMeta(username, meta) } - private async saveUserSubsonicMeta(username: string, meta: { starredAlbums: string[], starredArtists: string[], ratings: Record }) { - try { - const filePath = this.getUserMetaFilePath(username) - const dirPath = path.dirname(filePath) - if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true }) - fs.writeFileSync(filePath, JSON.stringify(meta), 'utf8') - } catch (e) { - console.error('[Subsonic] Failed to write subsonic-meta.json:', e) + /** 歌手名归一化:去空格 + 小写,用于跨大小写/音源匹配 */ + private normalizeArtistName(name: string): string { + return (name || '').trim().toLowerCase() + } + + /** + * 将歌手 id 解析为 (规范 art_ id, 歌手名) 两件套,供 star / getStarred 统一使用。 + * - art_源_id:规范 id,直接返回 id;并尽量从本地歌手库反查名字(保证 unstar 时名字集合一致)。 + * - artist_名字:兜底 id(歌曲/专辑映射在无 singerId 时生成),用 getSingerMid 寻址归一为 art_tx_mid; + * 寻址失败时退回原名(artist_名字),仍按名字匹配。 + */ + private async resolveArtistKey(username: string, id: string): Promise<{ canonical: string | null, name?: string }> { + if (id.startsWith('art_')) { + let name: string | undefined + try { + const libArtists = await this.getLibraryData(username, 'artists') + const found = libArtists.find((a: any) => `art_${a.source || 'wy'}_${a.id}` === id) + if (found?.name) name = found.name + } catch { /* 忽略,反查名字非必须 */ } + return { canonical: id, name } + } + if (id.startsWith('artist_')) { + const name = decodeURIComponent(id.slice(7)) + try { + const mid = await getSingerMid(name) + if (mid) return { canonical: `art_tx_${mid}`, name } + } catch { /* 寻址失败,退回原名 */ } + return { canonical: id, name } } + return { canonical: id, name: undefined } } private async handleStar(res: http.ServerResponse, username: string, params: URLSearchParams, format: string, isStar: boolean) { @@ -2057,6 +2236,8 @@ class SubsonicHandler { const meta = await this.getUserSubsonicMeta(username) const starredAlbums = new Set(meta.starredAlbums) const starredArtists = new Set(meta.starredArtists) + // 歌手名集合:用于跨音源 / artist_名字 兜底 id 的星标匹配 + const starredArtistNames = new Set(meta.starredArtistNames) const location = (global.lx.config['list.addMusicLocationType'] || 'bottom') as 'top' | 'bottom' let loveChanged = false let metaChanged = false @@ -2064,17 +2245,71 @@ class SubsonicHandler { const debug = !!global.lx.config['subsonic.enableDebug'] const debugLog = (msg: string) => { if (debug) console.log(msg) } + // 原生媒体库收藏(用于双向同步:音流星标 -> 网页前端收藏) + const nativeArtists = await this.getLibraryData(username, 'artists') + const nativeAlbums = await this.getLibraryData(username, 'albums') + let nativeArtistsDirty = false + let nativeAlbumsDirty = false + for (const id of ids) { if (id.startsWith('alb_')) { isStar ? starredAlbums.add(id) : starredAlbums.delete(id) metaChanged = true + console.log(`[Subsonic] ${action} 专辑 ${id} (user=${username})`) debugLog(`[Subsonic Debug] ${action} 专辑 ${id} -> ${isStar ? '已星标' : '已取消星标'} (user=${username})`) + // 双向同步:写回原生媒体库收藏 + const m = id.match(/^alb_([a-zA-Z0-9]+)_(.+)$/) + if (m) { + const source = m[1] + const realId = m[2] + if (isStar) { + if (!nativeAlbums.some((a: any) => String(a.id) === realId && a.source === source)) { + const { name, picUrl } = await this.resolveAlbumInfo(source, realId) + if (name) { + nativeAlbums.push({ id: realId, source, name, picUrl, artistName: '' }) + nativeAlbumsDirty = true + } else { + console.warn(`[Subsonic] ${action} 专辑 ${id} 跳过原生同步:无法解析专辑名 (user=${username})`) + } + } + } else { + const idx = nativeAlbums.findIndex((a: any) => String(a.id) === realId && a.source === source) + if (idx >= 0) { nativeAlbums.splice(idx, 1); nativeAlbumsDirty = true } + } + } continue } - if (id.startsWith('art_')) { - isStar ? starredArtists.add(id) : starredArtists.delete(id) + if (id.startsWith('art_') || id.startsWith('artist_')) { + // 统一解析:art_规范id 或 artist_名字兜底id -> 规范id + 歌手名 + const { canonical, name } = await this.resolveArtistKey(username, id) + if (!canonical) { + console.warn(`[Subsonic] ${action} 歌手 ${id} 跳过:无法解析歌手标识,未做任何改动 (user=${username})`) + continue + } + isStar ? starredArtists.add(canonical) : starredArtists.delete(canonical) + if (name) { + const nk = this.normalizeArtistName(name) + isStar ? starredArtistNames.add(nk) : starredArtistNames.delete(nk) + } metaChanged = true - debugLog(`[Subsonic Debug] ${action} 歌手 ${id} -> ${isStar ? '已星标' : '已取消星标'} (user=${username})`) + console.log(`[Subsonic] ${action} 歌手 ${id} -> 规范=${canonical}${name ? `, 名=${name}` : ''} (user=${username})`) + debugLog(`[Subsonic Debug] ${action} 歌手 ${id} -> ${isStar ? '已星标' : '已取消星标'} (规范=${canonical}${name ? `, 名=${name}` : ''}) (user=${username})`) + // 双向同步:写回原生媒体库收藏(仅规范 art_ 前缀可映射回原生 id) + const m = canonical.match(/^art_([a-zA-Z0-9]+)_(.+)$/) + if (m) { + const source = m[1] + const realId = m[2] + if (isStar) { + if (!nativeArtists.some((a: any) => String(a.id) === realId && a.source === source)) { + const picUrl = await this.resolveArtistPicUrl(source, realId) + nativeArtists.push({ id: realId, source, name: name || '', picUrl }) + nativeArtistsDirty = true + } + } else { + const idx = nativeArtists.findIndex((a: any) => String(a.id) === realId && a.source === source) + if (idx >= 0) { nativeArtists.splice(idx, 1); nativeArtistsDirty = true } + } + } continue } try { @@ -2102,9 +2337,12 @@ class SubsonicHandler { await this.saveUserSubsonicMeta(username, { starredAlbums: Array.from(starredAlbums), starredArtists: Array.from(starredArtists), + starredArtistNames: Array.from(starredArtistNames), ratings: meta.ratings, }) } + if (nativeArtistsDirty) await this.writeLibraryData(username, 'artists', nativeArtists) + if (nativeAlbumsDirty) await this.writeLibraryData(username, 'albums', nativeAlbums) if (loveChanged) { try { await userSpace.listManage.createSnapshot() @@ -2123,6 +2361,7 @@ class SubsonicHandler { const meta = await this.getUserSubsonicMeta(username) const starredAlbumSet = new Set(meta.starredAlbums) const starredArtistSet = new Set(meta.starredArtists) + const starredArtistNameSet = new Set(meta.starredArtistNames) // [汇总所有歌单歌曲] const allSongsMap = new Map() @@ -2144,16 +2383,27 @@ class SubsonicHandler { const libArtists = await this.getLibraryData(username, 'artists') const libAlbums = await this.getLibraryData(username, 'albums') - const mappedArtists = libArtists - .filter(a => starredArtistSet.has(`art_${a.source || 'wy'}_${a.id}`)) - .map(a => { - const id = `art_${a.source || 'wy'}_${a.id}` - return { - id, - name: a.name, - coverArt: id - } - }) + // [已星标歌手] 优先来自本地歌手库匹配;库为空或歌手不在库中时,用已存名字兜底合成条目 + const seenArtistNames = new Set() + const mappedArtists: Array<{ id: string, name: string, coverArt: string }> = [] + const pushArtist = (id: string, name: string) => { + const nk = this.normalizeArtistName(name) + if (seenArtistNames.has(nk)) return + seenArtistNames.add(nk) + mappedArtists.push({ id, name, coverArt: id }) + } + + for (const a of libArtists) { + const canonical = `art_${a.source || 'wy'}_${a.id}` + // 兼容:art_规范id 命中,或 artist_名字 兜底 / 跨音源按歌手名命中 + if (starredArtistSet.has(canonical) || starredArtistNameSet.has(this.normalizeArtistName(a.name))) { + pushArtist(canonical, a.name) + } + } + // 兜底:已星标但根本不在本地歌手库(例如从歌曲点星标、库为空)的歌手,用名字合成 + for (const name of meta.starredArtistNames) { + pushArtist(`artist_${encodeURIComponent(name)}`, name) + } const mappedAlbums = libAlbums .filter(a => starredAlbumSet.has(`alb_${(a.source || 'wy')}_${a.id}`)) @@ -2439,6 +2689,7 @@ class SubsonicHandler { return res.end() } + try { // 0. 剥离前缀 (al-, ar-, tr-, sg-, mg-) 并处理 URL id = id.replace(/^(al-|ar-|tr-|sg-|mg-)/, '') if (id === 'logo') { @@ -2536,18 +2787,22 @@ class SubsonicHandler { if (sdkPic) return this.proxyCoverImage(res, sdkPic) // console.log(`[CoverArt] SDK also returned nothing for song ${id}`) } else if (id.startsWith('alb_')) { - // [新增] 处理 SDK 专辑封面 + // [修复] 专辑封面:绝不能直接调歌曲 getPic(专辑对象无 songmid/hash,会读取 undefined.length 崩溃)。 + // 优先用本地专辑库的 picUrl;没有则落到函数末尾的 204 兜底。 const parts = id.split('_') const source = parts[1] const realId = parts.slice(2).join('_') - // console.log(`[CoverArt] Album Route Parse: source=${source}, realId=${realId}`) - if (musicSdk[source]?.getPic) { - const pic = await musicSdk[source].getPic({ source, albumId: realId, albumMid: realId } as any) - if (pic && typeof pic === 'string') { - // console.log(`[CoverArt] ✓ SDK Album Pic Success: ${pic}`) - return this.proxyCoverImage(res, pic) - } + try { + const libAlbums = await this.getLibraryData(username, 'albums') + const alb = libAlbums.find((a: any) => + `${(a.source || 'wy')}_${a.id}` === id || String(a.id) === realId) + const localPic = alb?.picUrl || alb?.img + if (localPic) return this.proxyCoverImage(res, localPic) + } catch (e) { + console.error(`[CoverArt] read album library failed for ${id}:`, (e as Error)?.message) } + // 注:musicSdk 各源未统一暴露专辑封面接口(kg 的 getAlbumInfo 未挂到 SDK 对象上), + // 此处不再强行调用歌曲 getPic,避免崩溃;专辑库有 picUrl 时才会返回封面。 } else if (id.startsWith('art_')) { // [修改] 歌手封面逻辑优化:先查本地库,再查歌手图助手 const parts = id.split('_') @@ -2621,6 +2876,11 @@ class SubsonicHandler { // console.log(`[CoverArt] No cover found for id=${id}, returning 204`) res.writeHead(204) res.end() + } catch (e: any) { + console.error('[Subsonic] handleGetCoverArt error:', e?.message || e) + if (!res.headersSent) res.writeHead(500, { 'Content-Type': 'application/json' }) + if (!res.writableEnded) res.end(JSON.stringify({ error: 'cover art error' })) + } } private async handleGetTopSongs( From 2fb6c894d4848f942a272643df0fdd1e0f5a8c99 Mon Sep 17 00:00:00 2001 From: XCQ0607 Date: Sun, 6 Sep 2026 17:22:40 +0800 Subject: [PATCH 05/24] chore(release): bump version to 2.0.2 and update changelog for #338 (#338) - Update changelog.md with v2.0.2 release notes - Feature: Subsonic star/unstar persistence and bidirectional sync (@pyss56) - Fix: Subsonic starred song status reflection and getStarred list refinement --- changelog.md | 10 ++++++++++ public/js/config.js | 2 +- src/server/subsonic.ts | 8 +++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index cab1abb1..3be90531 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,15 @@ # Changelog +## v2.0.2 (2026-09-06) + +### 🌟 新增功能 + +- **Subsonic 红心收藏/取消收藏功能与持久化联动 (#338) (@pyss56)**: + - **红心收藏与写入**: 新增 Subsonic 协议 `star` 与 `unstar` 接口,支持单曲(`id`)、专辑(`albumId`)与歌手(`artistId`)收藏。歌曲实时写入/移出用户的「我的收藏(love)」歌单并生成快照持久化。 + - **在线兜底解析**: 收藏不在本地歌单中的单曲时,支持自动通过平台源在线反查元数据后写入收藏。 + - **媒体库双向联动**: 建立 `subsonic-meta.json` 扩展元数据,打通音流等客户端与 LX Web 前端原生媒体库(`artists.json` / `albums.json`)的双向收藏同步。 + - **星标状态与封面防崩**: 优化 `getArtists` / `getArtist` 及单曲对象,实时回显 `starred` 标记;修复专辑封面读取导致的 Node 服务异常,提升客户端交互体验与稳定性。 + ## v2.0.1 (2026-07-23) ### 🌟 新增功能 diff --git a/public/js/config.js b/public/js/config.js index 255a32d8..436fd2ca 100644 --- a/public/js/config.js +++ b/public/js/config.js @@ -2,6 +2,6 @@ // 其余配置由服务端在运行时动态注入 (环境变量 > config.js > defaultConfig.ts) // 服务端拦截 /js/config.js 请求, 读取此处版本号并合并服务端配置后返回 window.CONFIG = { - buildHash: '8574d94', + buildHash: '32fe900', version: 'v2.0.1', }; diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 08524d1b..c102c468 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -145,6 +145,7 @@ class SubsonicHandler { // 当前用户 love 列表歌曲 id 集合缓存,用于歌曲序列化时标记 starred(按用户名隔离,避免并发串号) private loveIdSets = new Map>() + private currentUsername = '' private cacheOnlineSong(music: LX.Music.MusicInfo) { if (!music || !music.id) return @@ -333,6 +334,7 @@ class SubsonicHandler { if (!username) { return this.sendError(res, 40, 'Wrong username or password', format) } + this.currentUsername = username const { pathname } = urlObj const method = pathname.split('/').pop()?.split('.')[0] || '' @@ -597,6 +599,8 @@ class SubsonicHandler { const defaultArtistId = (music as any).singerId ? `art_${source}_${(music as any).singerId}` : `artist_${primarySinger}` const finalArtistId = artistIdOverride || defaultArtistId + const isStarred = (this.loveIdSets.get(this.currentUsername)?.has(id)) || parentId === 'love' + return { id, parent: parentId, @@ -614,6 +618,7 @@ class SubsonicHandler { ...this.getBestQualityMeta(music), isVideo: false, isDir: false, + ...(isStarred ? { starred: new Date().toISOString() } : {}), // 某些客户端 (如 Feishin) 在特定视图下不喜欢非标准字段,可以保留但确保标准字段优先 type: 'music', } @@ -2321,8 +2326,10 @@ class SubsonicHandler { } if (isStar) { await userSpace.listManage.listDataManage.listMusicAdd('love', [resolved], location) + this.loveIdSets.get(username)?.add(resolved.id) } else { await userSpace.listManage.listDataManage.listMusicRemove('love', [resolved.id]) + this.loveIdSets.get(username)?.delete(resolved.id) } const fromSource = hit!.listId === 'online' debugLog(`[Subsonic Debug] ${action} 歌曲 ${id} -> ${isStar ? '已加入' : '已移出'}我的收藏(love) 《${resolved.name}》${fromSource ? ' (从源取回)' : ''}(user=${username})`) @@ -2373,7 +2380,6 @@ class SubsonicHandler { } } collect(listData.loveList, 'love') - collect(listData.defaultList, 'default') for (const list of listData.userList) { collect((list.list || []) as LX.Music.MusicInfo[], list.id) } From 0f1d611beb1fbcf5518949f7baca437b507848f5 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 21:19:03 +0800 Subject: [PATCH 06/24] fix(subsonic): persist onlineSongCache across restarts and fix metadata loss - Load disk cache on the read path (findMusicById) instead of only on write, so a restarted server can recover cached song metadata instead of falling back to Unknown. - Write cache synchronously and atomically (temp file + rename) per new entry, replacing the 2s debounced async write that lost data on fast or hard restarts. - Persist client-param fallback results (e.g. kw streams) so they also survive restarts. - Add kw/bd branches to resolveMusicById for online metadata fallback. --- src/server/subsonic.ts | 191 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 185 insertions(+), 6 deletions(-) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 08524d1b..266d6a25 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -3,6 +3,7 @@ import crypto from 'crypto' import { URL } from 'url' import { getUserSpace, getUserDirname, getUserConfig } from '@/user' import { callUserApiGetMusicUrl } from '@/server/userApi' +import { downloadAndCache } from '@/server/fileCache' import { getSingerPic, getSingerDetail, getSingerMid } from '@/server/utils/singer' import { fetchRecommendedAlbums } from '@/server/utils/recommendAlbums' import { fetchGenres, fetchRadios, fetchPlaylistsByGenre, fetchRadioSongs, fetchPlaylistSongs, fetchSongsByGenre } from '@/server/utils/discovery' @@ -14,6 +15,7 @@ import txMusicInfo from '@/modules/utils/musicSdk/tx/musicInfo.js' import wyMusicInfo from '@/modules/utils/musicSdk/wy/musicInfo.js' import { getMusicInfo as kgGetMusicInfo } from '@/modules/utils/musicSdk/kg/musicInfo.js' import { getMusicInfo as mgGetMusicInfo } from '@/modules/utils/musicSdk/mg/musicInfo.js' +import bdMusicInfo from '@/modules/utils/musicSdk/bd/musicInfo.js' const musicSdk = musicSdkRaw as any // ───────────────────────────────────────────── @@ -139,6 +141,8 @@ class SubsonicHandler { // 在线全网搜索歌曲缓存 (ID -> MusicInfo),确保后续 getSong / getCoverArt / getLyrics 能精准查到歌曲元数据 private onlineSongCache = new Map() + // [修复] onlineSongCache 真正落盘持久化:之前只是内存 Map,重启即丢,导致 kw 等回源结果无法复用 + private onlineSongCacheLoaded = false // 固定同一关键词的在线结果顺序,避免客户端翻页时出现重复或跳项。 private onlineSearchCache = new Map() @@ -146,13 +150,69 @@ class SubsonicHandler { // 当前用户 love 列表歌曲 id 集合缓存,用于歌曲序列化时标记 starred(按用户名隔离,避免并发串号) private loveIdSets = new Map>() + private getOnlineSongCachePath(): string { + return path.join(global.lx.dataPath, 'subsonic-online-cache.json') + } + + // [日志] 音源(在线回源)类错误统一写独立文件,控制台只打精简一行 + private getSourceErrorLogPath(): string { + return path.join(global.lx.dataPath, 'subsonic-source-errors.log') + } + + private logSourceError(tag: string, detail: string, err?: any) { + const ts = new Date().toISOString() + const errMsg = err?.message ?? String(err ?? '') + const errStack = err?.stack ?? '' + const block = `[${ts}] [${tag}] ${detail}\n message: ${errMsg}\n${errStack ? ` stack: ${errStack}\n` : ''}---\n` + try { + fs.appendFileSync(this.getSourceErrorLogPath(), block) + } catch { /* 写错误日志失败不阻塞主流程 */ } + // 控制台精简显示 + console.warn(`[Subsonic] 音源错误 ${tag}: ${detail} (详见 subsonic-source-errors.log)`) + } + + private loadOnlineSongCache() { + if (this.onlineSongCacheLoaded) return + this.onlineSongCacheLoaded = true + try { + const p = this.getOnlineSongCachePath() + if (fs.existsSync(p)) { + const arr = JSON.parse(fs.readFileSync(p, 'utf8')) + if (Array.isArray(arr)) { + for (const m of arr) if (m && m.id) this.onlineSongCache.set(m.id, m) + console.log(`[Subsonic] onlineSongCache 已从磁盘加载 ${this.onlineSongCache.size} 条`) + } + } + } catch (e) { + console.error('[Subsonic] 加载 onlineSongCache 失败:', e) + } + } + + // 每新增一首歌即同步落盘(只在 cacheOnlineSong 新增唯一 id 时触发,频率很低)。 + // 用「临时文件 + rename」做原子写:避免进程在写入中途被强杀导致文件截断损坏。 + private saveOnlineSongCache() { + try { + const p = this.getOnlineSongCachePath() + const dir = path.dirname(p) + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }) + const arr = Array.from(this.onlineSongCache.values()) + const tmp = `${p}.${process.pid}.tmp` + fs.writeFileSync(tmp, JSON.stringify(arr), 'utf8') + fs.renameSync(tmp, p) + } catch (e) { + console.error('[Subsonic] 保存 onlineSongCache 失败:', e) + } + } + private cacheOnlineSong(music: LX.Music.MusicInfo) { if (!music || !music.id) return + this.loadOnlineSongCache() if (this.onlineSongCache.size > 5000) { const firstKey = this.onlineSongCache.keys().next().value if (firstKey) this.onlineSongCache.delete(firstKey) } this.onlineSongCache.set(music.id, music) + this.saveOnlineSongCache() } // ───────────────────────────────────────────── @@ -672,6 +732,9 @@ class SubsonicHandler { /** 查找某个用户下所有列表中的某首歌 */ private async findMusicById(username: string, id: string): Promise<{ music: LX.Music.MusicInfo, listId: string } | null> { + // [修复] 读取前确保磁盘上的 onlineSongCache 已加载(之前只在 cacheOnlineSong 写入时触发, + // 导致重启后首次读取发生在任何写入之前,落盘数据永远读不进来 -> 重启即丢) + this.loadOnlineSongCache() const userSpace = getUserSpace(username) const listData = await userSpace.listManage.getListData() @@ -2100,7 +2163,7 @@ class SubsonicHandler { /** * 按歌曲 id 从各音源在线回源取单曲信息(github/dev 移植自 feat/subsonic) - * 支持 tx / wy / kg / mg;其它源(kw/bd/xm 等)无可靠「按 id 取单曲」接口,直接放弃。 + * 支持 tx / wy / kg / mg / kw / bd;xm 等无「按 id 取单曲」接口的源返回 null 降级。 */ private async resolveMusicById(id: string): Promise { const idx = id.indexOf('_') @@ -2141,10 +2204,66 @@ class SubsonicHandler { case 'mg': music = await mgGetMusicInfo(songId) break + case 'kw': { + // kw 有 getMusicInfo(songInfo):www.kuwo.cn/api/www/music/musicInfo?mid= + // 返回 data 含 name / artist / album / pic / duration + const info: any = await musicSdk.kw.getMusicInfo({ songmid: songId }).catch((e: any) => { + this.logSourceError('kw', `getMusicInfo kw_${songId}`, e) + return null + }) + if (info && info.name) { + const artist = info.artist + const singer = Array.isArray(artist) + ? artist.map((a: any) => a?.name || a).join('、') + : (typeof artist === 'string' ? artist : (artist?.name || '')) + music = { + id: `kw_${songId}`, + name: info.name, + singer, + source: 'kw', + songmid: songId, + interval: info.duration ? String(Math.round(Number(info.duration) > 100000 ? Number(info.duration) / 1000 : Number(info.duration))) : '0', + img: info.pic || null, + meta: { + albumName: info.album || '', + albumId: info.albumid ?? '', + picUrl: info.pic || null, + }, + } + } + break + } + case 'bd': { + // bd 有 getMusicInfo(songmid):baidu.ting.song.getSongLink -> result.songinfo + const info: any = await (bdMusicInfo.getMusicInfo(songId) as any).promise.catch((e: any) => { + this.logSourceError('bd', `getMusicInfo bd_${songId}`, e) + return null + }) + if (info && info.title) { + music = { + id: `bd_${songId}`, + name: info.title, + singer: info.author || '', + source: 'bd', + songmid: songId, + interval: info.file_duration ? String(Math.round(Number(info.file_duration))) : '0', + img: info.pic_big || info.pic_small || null, + meta: { + albumName: info.album_title || '', + albumId: info.album_id || '', + picUrl: info.pic_big || info.pic_small || null, + }, + } + } + break + } default: return null } - if (!music) return null + if (!music) { + console.log(`[Subsonic][trace] resolveMusicById ${id}: 回源未取到音乐信息(source=${source})`) + return null + } if (!music.source) music.source = source if (!music.id) music.id = `${source}_${music.songmid || music.songId || songId}` if (!music.songmid) music.songmid = music.songId || songId @@ -2152,25 +2271,31 @@ class SubsonicHandler { console.warn(`[Subsonic] resolveMusicById ${id} 取回结果缺少歌名,已放弃(不写入收藏)`) return null } + console.log(`[Subsonic][trace] resolveMusicById ${id}: 成功取到 name=${music.name}, singer=${music.singer || '(空)'}`) return music as LX.Music.MusicInfo } catch (e) { - console.warn(`[Subsonic] resolveMusicById ${id} 失败:`, (e as Error).message) + this.logSourceError('resolveMusicById', `回源 ${id}`, e) return null } } /** 统一元数据解析原语:本地/缓存 -> 在线回源;命中即回写 onlineSongCache */ private async resolveSongMeta(username: string, id: string): Promise<{ music: LX.Music.MusicInfo, listId: string } | null> { + console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步 查持久化(歌单/专辑库) + 内存/磁盘 onlineSongCache`) const found = await this.findMusicById(username, id) if (found) { this.cacheOnlineSong(found.music) + console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步命中 listId=${found.listId}, name=${found.music.name || '(空)'}`) return found } + console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步未命中 -> 第2步 在线回源(network)`) const resolved = await this.resolveMusicById(id) if (resolved) { this.cacheOnlineSong(resolved) + console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源成功 name=${resolved.name}, 已写 onlineSongCache(内存+磁盘)`) return { music: resolved, listId: 'online' } } + console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源失败 -> 返回 null(将在 stream 中降级为 Unknown)`) return null } @@ -2633,8 +2758,47 @@ class SubsonicHandler { return this.sendError(res, 0, 'Could not resolve radio track', format) } - const found = await this.findMusicById(username, id) - let musicInfo: any = found?.music || { source, songmid, id, meta: { songId: songmid } } + // [修复] 像 star 一样:先用 findMusicById 查本地/缓存,查不到再在线回源补全真实元数据 + // (否则仅用 Subsonic 的不完整信息会导致缓存文件名为 Unknown - Unknown - ...) + let musicInfo: any + try { + const hit = await this.resolveSongMeta(username, id) + musicInfo = hit?.music || null + } catch (e) { + this.logSourceError('resolveSongMeta', `stream ${id}`, e) + musicInfo = null + } + if (!musicInfo) { + musicInfo = { source, songmid, id, meta: { songId: songmid } } + } + // [诊断] 打印回源结果与客户端的歌曲元数据参数,便于排查 kw 等源仍为 Unknown 的问题 + console.log(`[Subsonic] stream resolve ${id}: name=${musicInfo.name || '(空)'} singer=${musicInfo.singer || '(空)'} album=${musicInfo.meta?.albumName || '(空)'}`) + console.log(`[Subsonic] stream params: name=${params.get('name') || ''} title=${params.get('title') || ''} artist=${params.get('artist') || ''} album=${params.get('album') || ''}`) + // [修复] 客户端(音流)通常在 stream 请求里附带真实元数据(name/artist/album), + // 用于补充 Subsonic 自身不完整的歌曲信息(kw 等无 getMusicInfo 的源尤其依赖它) + if (!musicInfo.name) { + const cName = params.get('name') || params.get('title') || '' + if (cName) { + musicInfo = { + ...musicInfo, + name: cName, + singer: params.get('artist') || musicInfo.singer || '', + source, + songmid, + id, + img: musicInfo.img || null, + meta: { + ...(musicInfo.meta || {}), + songId: songmid, + albumName: params.get('album') || musicInfo.meta?.albumName || '', + }, + } + console.log(`[Subsonic] stream ${id}: 已用客户端参数补全 name=${cName}`) + // [修复] 把客户端补全后的结果也落盘,否则重启后还得再靠客户端参数补全一次, + // 一旦客户端未带参数就会再次缺失 + this.cacheOnlineSong(musicInfo) + } + } let hash = musicInfo.hash || musicInfo.meta?.hash || '' if (source === 'kg' && !hash) { @@ -2646,7 +2810,7 @@ class SubsonicHandler { hash = match.hash || match.meta?.hash || match.types?.[0]?.hash || '' } } catch (e) { - console.error('[Subsonic] Auto-resolve kg hash for stream failed:', e) + this.logSourceError('kg-hash', `auto-resolve hash kw_${songmid}`, e) } } @@ -2666,6 +2830,21 @@ class SubsonicHandler { const result = await callUserApiGetMusicUrl(source as any, musicInfo as any, quality, username) if (result && result.url) { + // [诊断] 打印缓存触发决策,便于排查 Subsonic 播放不缓存问题 + console.log(`[Subsonic] stream cacheOnPlay: enabled=${global.lx.config['subsonic.cacheOnPlay']} user=${username} url=${String(result.url).slice(0, 90)}`) + // [新增] 播放时触发服务器缓存保存:受 subsonic.cacheOnPlay 开关控制, + // 后台落盘到该用户缓存目录;downloadAndCache 内部会去重(已存在则跳过),不会重复下载。 + if (global.lx.config['subsonic.cacheOnPlay'] && username) { + void downloadAndCache(musicInfo, result.url, quality, username, undefined, false, true, true, { + requestedSource: source, + downloadSource: source, + sourceName: source, + }).then(() => { + console.log(`[Subsonic] cacheOnPlay: cache task done for ${musicInfo.id} (${quality})`) + }).catch((err: any) => { + console.error('[Subsonic] cacheOnPlay failed:', err?.message || err) + }) + } res.writeHead(302, { Location: result.url }) res.end() } else { From ae7eefa812e72ba91191d226b0fbafbb387f3623 Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 21:23:39 +0800 Subject: [PATCH 07/24] feat(subsonic): add cacheOnPlay option, UI and download dedup - Add subsonic.cacheOnPlay config (default false) with a web UI toggle in index.html; when enabled, Subsonic playback triggers server-side downloadAndCache into the user's cache directory, skipping already-cached. - Wire the option through defaultConfig, config types and server config. - Add a download dedup guard in fileCache so repeated Subsonic stream requests for the same track do not trigger duplicate downloads. --- public/app.js | 4 ++++ public/index.html | 10 ++++++++++ public/js/config.js | 2 +- src/defaultConfig.ts | 1 + src/server/fileCache.ts | 15 +++++++++++++++ src/server/server.ts | 3 +++ src/types/config.d.ts | 7 +++++++ 7 files changed, 41 insertions(+), 1 deletion(-) diff --git a/public/app.js b/public/app.js index 75274184..2b2d550b 100644 --- a/public/app.js +++ b/public/app.js @@ -2304,6 +2304,9 @@ class App { if (form.elements['subsonic.lyricTranslation']) { form.elements['subsonic.lyricTranslation'].checked = config['subsonic.lyricTranslation'] !== false; } + if (form.elements['subsonic.cacheOnPlay']) { + form.elements['subsonic.cacheOnPlay'].checked = config['subsonic.cacheOnPlay'] === true; + } // 自定义歌曲目录配置 if (form.elements['user.enableCustomMusicDir']) { @@ -2403,6 +2406,7 @@ class App { 'subsonic.onlineSearchMode': formData.get('subsonic.onlineSearchMode') || 'fallback', 'subsonic.onlineSearchSources': (formData.get('subsonic.onlineSearchSources') || '').trim() || 'wy,tx,kw,kg,mg', 'subsonic.lyricTranslation': formData.get('subsonic.lyricTranslation') === 'on', + 'subsonic.cacheOnPlay': formData.get('subsonic.cacheOnPlay') === 'on', 'singer.sourcePriority': formData.get('singer.sourcePriority'), 'system.allowUnsafeVM': formData.get('system.allowUnsafeVM') === 'on', }; diff --git a/public/index.html b/public/index.html index b46320ee..98932d4d 100644 --- a/public/index.html +++ b/public/index.html @@ -1130,6 +1130,16 @@

Subsonic 协议配置

+
+
+ 播放时触发服务器缓存 + 通过 Subsonic 播放的曲目在后台自动落盘到该用户缓存目录,已缓存自动跳过(注意可能产生较大流量) +
+ +
diff --git a/public/js/config.js b/public/js/config.js index 255a32d8..59177ded 100644 --- a/public/js/config.js +++ b/public/js/config.js @@ -2,6 +2,6 @@ // 其余配置由服务端在运行时动态注入 (环境变量 > config.js > defaultConfig.ts) // 服务端拦截 /js/config.js 请求, 读取此处版本号并合并服务端配置后返回 window.CONFIG = { - buildHash: '8574d94', + buildHash: '6592c26', version: 'v2.0.1', }; diff --git a/src/defaultConfig.ts b/src/defaultConfig.ts index c27bb0d0..a3a8b451 100644 --- a/src/defaultConfig.ts +++ b/src/defaultConfig.ts @@ -66,6 +66,7 @@ const config: LX.Config = { 'subsonic.onlineSearchMode': 'fallback', // 在线搜索模式: fallback | merge | local_only 'subsonic.onlineSearchSources': 'wy,tx,kw,kg,mg', // 在线搜索默认平台 'subsonic.lyricTranslation': true, // 是否在 Subsonic 歌词中包含翻译 + 'subsonic.cacheOnPlay': false, // 是否在 Subsonic 播放时触发服务器缓存保存(落盘) 'singer.sourcePriority': ['tx', 'wy'], // 歌手信息源优先级 'artist.maxFetchPages': 20, // 歌手歌曲最大抓取页数 'cache.namingPattern': 'simple', // 缓存命名规则 diff --git a/src/server/fileCache.ts b/src/server/fileCache.ts index b887cf28..29f6b995 100644 --- a/src/server/fileCache.ts +++ b/src/server/fileCache.ts @@ -1969,7 +1969,22 @@ export const downloadAndCache = async (songInfo: any, url: string, quality?: str return Promise.resolve() } + // [去重] 同一 songKey 正在下载/写标签时直接跳过,避免并发重复下载 + // (如 Subsonic 客户端反复请求 stream、或音流并行触发原生缓存) + const inFlight = cacheProgress.get(songKey) + if (inFlight && (inFlight.status === 'downloading' || inFlight.status === 'tagging')) { + const age = Date.now() - (inFlight.updatedAt || 0) + // 超过 10 分钟仍无进展视为卡死,允许本次重新下载(避免永久阻塞该歌曲, + // 尤其 fire-and-forget 的 Subsonic 缓存触发没有 abort 信号) + if (age < 10 * 60 * 1000) { + console.log(`[FileCache] Download already in progress for ${songKey}, skipping duplicate`) + return Promise.resolve() + } + } if (signal?.aborted) return + // 立即同步占坑标记下载中,关闭“拿到 200 响应前”的并发竞态窗口; + // 后续到达的相同 songKey 请求会被上面的守卫跳过,不再重复下载。 + cacheProgress.set(songKey, { progress: 0, status: 'downloading', total: 0, received: 0, speed: 0, updatedAt: Date.now() }) console.log(`[FileCache] Starting download for: ${baseName}`) return new Promise((resolve, reject) => { diff --git a/src/server/server.ts b/src/server/server.ts index 40373aee..0f7da72c 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -5852,6 +5852,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro 'subsonic.onlineSearchMode': global.lx.config['subsonic.onlineSearchMode'] ?? 'fallback', 'subsonic.onlineSearchSources': global.lx.config['subsonic.onlineSearchSources'] ?? 'wy,tx,kw,kg,mg', 'subsonic.lyricTranslation': global.lx.config['subsonic.lyricTranslation'] ?? true, + 'subsonic.cacheOnPlay': global.lx.config['subsonic.cacheOnPlay'] ?? false, 'singer.sourcePriority': (global.lx.config['singer.sourcePriority'] || ['tx', 'wy']).join(','), 'artist.maxFetchPages': global.lx.config['artist.maxFetchPages'] ?? 20, 'system.allowUnsafeVM': global.lx.config['system.allowUnsafeVM'] || false, @@ -5964,6 +5965,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro if (newConfig['subsonic.onlineSearchMode'] !== undefined) global.lx.config['subsonic.onlineSearchMode'] = newConfig['subsonic.onlineSearchMode'] if (newConfig['subsonic.onlineSearchSources'] !== undefined) global.lx.config['subsonic.onlineSearchSources'] = newConfig['subsonic.onlineSearchSources'] if (newConfig['subsonic.lyricTranslation'] !== undefined) global.lx.config['subsonic.lyricTranslation'] = newConfig['subsonic.lyricTranslation'] + if (newConfig['subsonic.cacheOnPlay'] !== undefined) global.lx.config['subsonic.cacheOnPlay'] = newConfig['subsonic.cacheOnPlay'] if (newConfig['singer.sourcePriority'] !== undefined) { const priority = String(newConfig['singer.sourcePriority']).split(',').filter(s => s === 'tx' || s === 'wy') as Array<'tx' | 'wy'> if (priority.length > 0) global.lx.config['singer.sourcePriority'] = priority @@ -6033,6 +6035,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro 'subsonic.onlineSearchMode': global.lx.config['subsonic.onlineSearchMode'], 'subsonic.onlineSearchSources': global.lx.config['subsonic.onlineSearchSources'], 'subsonic.lyricTranslation': global.lx.config['subsonic.lyricTranslation'], + 'subsonic.cacheOnPlay': global.lx.config['subsonic.cacheOnPlay'], 'singer.sourcePriority': global.lx.config['singer.sourcePriority'], 'artist.maxFetchPages': global.lx.config['artist.maxFetchPages'], 'cache.namingPattern': global.lx.config['cache.namingPattern'], diff --git a/src/types/config.d.ts b/src/types/config.d.ts index 8cde4634..a3e0fcf9 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -265,6 +265,13 @@ declare namespace LX { */ 'subsonic.lyricTranslation'?: boolean + /** + * 是否在 Subsonic 播放音乐时触发服务器缓存保存 (默认 false) + * 开启后,每次通过 Subsonic 协议播放的曲目会在后台落盘到该用户的缓存目录, + * 已缓存的曲目会被 downloadAndCache 自动跳过,不会重复下载。 + */ + 'subsonic.cacheOnPlay'?: boolean + /** * 歌手信息源优先级 */ From 58199d27deaa2e1d5bb073847a41335223c9d76b Mon Sep 17 00:00:00 2001 From: pavel2 Date: Sun, 6 Sep 2026 21:32:30 +0800 Subject: [PATCH 08/24] chore: align public/js/config.js buildHash with upstream/dev to avoid PR merge conflict buildHash is auto-generated at build time (scripts/update-build-hash.js), so it should not diverge from the base branch in a PR. Reset it to upstream/dev's value to keep the file conflict-free on merge. --- public/js/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/config.js b/public/js/config.js index 59177ded..436fd2ca 100644 --- a/public/js/config.js +++ b/public/js/config.js @@ -2,6 +2,6 @@ // 其余配置由服务端在运行时动态注入 (环境变量 > config.js > defaultConfig.ts) // 服务端拦截 /js/config.js 请求, 读取此处版本号并合并服务端配置后返回 window.CONFIG = { - buildHash: '6592c26', + buildHash: '32fe900', version: 'v2.0.1', }; From 19fec64a7336aab8c6afd5b41e18c4e1c24c0b50 Mon Sep 17 00:00:00 2001 From: XCQ0607 Date: Mon, 7 Sep 2026 09:10:20 +0800 Subject: [PATCH 09/24] fix(subsonic): serve cached audio directly in stream instead of fetching remote url --- src/server/subsonic.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 266d6a25..3d6662d8 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -3,7 +3,7 @@ import crypto from 'crypto' import { URL } from 'url' import { getUserSpace, getUserDirname, getUserConfig } from '@/user' import { callUserApiGetMusicUrl } from '@/server/userApi' -import { downloadAndCache } from '@/server/fileCache' +import { downloadAndCache, checkCache, serveCacheFile } from '@/server/fileCache' import { getSingerPic, getSingerDetail, getSingerMid } from '@/server/utils/singer' import { fetchRecommendedAlbums } from '@/server/utils/recommendAlbums' import { fetchGenres, fetchRadios, fetchPlaylistsByGenre, fetchRadioSongs, fetchPlaylistSongs, fetchSongsByGenre } from '@/server/utils/discovery' @@ -2758,6 +2758,13 @@ class SubsonicHandler { return this.sendError(res, 0, 'Could not resolve radio track', format) } + // [新增] 本地缓存优先播放:若该歌曲已存在于用户的 cache 或 music 目录,直接流式回传本地文件,避免请求源站 + const cacheCheck = checkCache({ source, songmid, id, quality }, username, false) + if (cacheCheck.exists && cacheCheck.filename) { + console.log(`[Subsonic] Stream hit local cache for ${id} (${cacheCheck.quality || quality}): ${cacheCheck.filename} (${cacheCheck.folder})`) + return serveCacheFile(req, res, cacheCheck.filename, username) + } + // [修复] 像 star 一样:先用 findMusicById 查本地/缓存,查不到再在线回源补全真实元数据 // (否则仅用 Subsonic 的不完整信息会导致缓存文件名为 Unknown - Unknown - ...) let musicInfo: any From e6db6042c37ebdf1d46d436155c453ef32536ccf Mon Sep 17 00:00:00 2001 From: XCQ0607 Date: Mon, 7 Sep 2026 10:09:05 +0800 Subject: [PATCH 10/24] =?UTF-8?q?feat(subsonic):=20=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=9C=BA=E5=88=B6=E4=B8=8E=E6=94=B6=E8=97=8F?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=90=8C=E6=AD=A5=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8F=8C=E5=90=91=E6=8C=81=E4=B9=85=E5=8C=96=E8=81=94=E5=8A=A8?= =?UTF-8?q?=20-=20feat:=20=E6=96=B0=E5=A2=9E=20Subsonic=20=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E7=BC=93=E5=AD=98=E8=83=BD=E5=8A=9B=20(#339)=EF=BC=8C?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20`subsonic.cacheOnPlay`=20=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E8=90=BD=E7=9B=98=E4=B8=8E=E4=BC=98=E5=85=88=E6=9C=AC?= =?UTF-8?q?=E5=9C=B0=E7=BC=93=E5=AD=98=E8=AF=BB=E5=8F=96=20-=20feat:=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20Abort=20=E6=B5=81=E5=BC=8F=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E8=B0=83=E5=BA=A6=EF=BC=8C=E5=9C=A8=E5=AE=A2=E6=88=B7?= =?UTF-8?q?=E7=AB=AF=E5=BF=AB=E9=80=9F=E5=88=87=E6=AD=8C=E6=97=B6=E7=BB=88?= =?UTF-8?q?=E6=AD=A2=E5=90=8E=E5=8F=B0=E5=B9=B6=E5=8F=91=E7=BC=93=E5=AD=98?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=EF=BC=8C=E9=98=B2=E6=9C=8D=E5=8A=A1=E5=99=A8?= =?UTF-8?q?=E8=B5=84=E6=BA=90=E8=80=97=E5=B0=BD=20-=20feat:=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=BA=A2=E5=BF=83=E6=94=B6=E8=97=8F/=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E6=94=B6=E8=97=8F=E4=B8=8E=E6=8C=81=E4=B9=85=E5=8C=96?= =?UTF-8?q?=E8=81=94=E5=8A=A8=20(#338=20@pyss56)=EF=BC=8C=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=8D=95=E6=9B=B2=E3=80=81=E4=B8=93=E8=BE=91=E3=80=81?= =?UTF-8?q?=E6=AD=8C=E6=89=8B=E6=94=B6=E8=97=8F=E5=AE=9E=E6=97=B6=E5=86=99?= =?UTF-8?q?=E5=85=A5=20`love`=20=E6=AD=8C=E5=8D=95=20-=20feat:=20=E5=BB=BA?= =?UTF-8?q?=E7=AB=8B=20`subsonic-meta.json`=20=E6=89=A9=E5=B1=95=E5=85=83?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=EF=BC=8C=E6=89=93=E9=80=9A=E9=9F=B3=E6=B5=81?= =?UTF-8?q?=E7=AD=89=E5=AE=A2=E6=88=B7=E7=AB=AF=E4=B8=8E=20Web=20=E5=8E=9F?= =?UTF-8?q?=E7=94=9F=E5=AA=92=E4=BD=93=E5=BA=93=E5=8F=8C=E5=90=91=E6=94=B6?= =?UTF-8?q?=E8=97=8F=E8=81=94=E5=8A=A8=20-=20feat:=20=E4=BC=98=E5=8C=96=20?= =?UTF-8?q?`onlineSongCache`=20=E6=9C=BA=E5=88=B6=EF=BC=8C=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=A3=81=E7=9B=98=E6=96=87=E4=BB=B6=E9=98=B2=E6=8A=96?= =?UTF-8?q?=E5=8E=9F=E5=AD=90=E6=8C=81=E4=B9=85=E5=8C=96=EF=BC=8C=E5=BD=BB?= =?UTF-8?q?=E5=BA=95=E8=A7=A3=E5=86=B3=E9=87=8D=E5=90=AF=E5=85=83=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E4=B8=A2=E5=A4=B1=E9=97=AE=E9=A2=98=20-=20fix:=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20`getStarred`=20=E6=8E=A5=E5=8F=A3=E7=B2=BE?= =?UTF-8?q?=E5=87=86=E5=89=A5=E7=A6=BB=E8=87=AA=E5=AE=9A=E4=B9=89=E6=AD=8C?= =?UTF-8?q?=E5=8D=95=EF=BC=8C=E4=B8=A5=E6=A0=BC=E9=95=9C=E5=83=8F=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF=E7=9A=84=20`love`=20=E5=88=97=E8=A1=A8=20-?= =?UTF-8?q?=20fix:=20=E5=85=A8=E5=B1=80=E8=81=94=E5=8A=A8=E9=80=8F?= =?UTF-8?q?=E4=BC=A0=E7=BA=A2=E5=BF=83=E7=8A=B6=E6=80=81=EF=BC=8C=E9=87=8D?= =?UTF-8?q?=E6=9E=84=20`musicToSongFlat/Xml`=20=E5=8F=8A=E5=8D=81=E4=BD=99?= =?UTF-8?q?=E4=B8=AA=E6=8E=A5=E5=8F=A3=EF=BC=8C=E5=AE=8C=E7=BE=8E=E5=AE=9E?= =?UTF-8?q?=E6=97=B6=E5=9B=9E=E6=98=BE=20`starred`=20=E6=A0=87=E8=AE=B0=20?= =?UTF-8?q?-=20fix:=20=E4=BF=AE=E5=A4=8D=E6=94=B6=E8=97=8F=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E7=9A=84=E9=9B=B6=E5=BB=B6=E8=BF=9F=E5=90=8C=E6=AD=A5?= =?UTF-8?q?=EF=BC=8C=E7=82=B9=E6=8C=89=E7=BA=A2=E5=BF=83=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E4=BB=85=E8=90=BD=E7=9B=98=E5=90=8C=E6=97=B6=E7=9E=AC=E9=97=B4?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=86=85=E5=AD=98=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + README_EN.md | 2 + changelog.md | 23 ++++++ config.js | 8 ++ md/log/2.0.2-1.png | Bin 0 -> 218829 bytes public/app.js | 4 + public/index.html | 10 +++ public/js/config.js | 2 +- src/constants.ts | 2 + src/defaultConfig.ts | 1 + src/index.ts | 6 ++ src/server/server.ts | 3 + src/server/subsonic.ts | 177 +++++++++++++++++++++++++++-------------- src/types/config.d.ts | 6 ++ 14 files changed, 185 insertions(+), 61 deletions(-) create mode 100644 md/log/2.0.2-1.png diff --git a/README.md b/README.md index ed3fed11..18c62e23 100644 --- a/README.md +++ b/README.md @@ -300,6 +300,8 @@ npm start | `SUBSONIC_ONLINE_SEARCH_MODE` | `subsonic.onlineSearchMode` | Subsonic 在线搜索模式 (`fallback` / `merge` / `local_only`) | `fallback` | | `SUBSONIC_ONLINE_SEARCH_SOURCES` | `subsonic.onlineSearchSources` | Subsonic 在线搜索默认音源列表 | `wy,tx,kw,kg,mg` | | `SUBSONIC_LYRIC_TRANSLATION` | `subsonic.lyricTranslation` | Subsonic 歌词中是否包含翻译 | `true` | +| `SUBSONIC_CACHE_ON_PLAY` | `subsonic.cacheOnPlay` | Subsonic 播放时是否触发服务器自动缓存保存 (落盘到用户目录) | `false` | +| `SUBSONIC_PLAY_CACHE_FIRST` | `subsonic.playCacheFirst` | Subsonic 播放时是否优先使用服务器已有的本地缓存/下载文件直接传输 | `true` | | `ARTIST_MAX_FETCH_PAGES` | `artist.maxFetchPages` | 歌手歌曲最大抓取页数 | `20` | | `CACHE_NAMING_PATTERN` | `cache.namingPattern` | 缓存文件命名规则 (`simple` / `custom`) | `simple` | | `SYSTEM_ALLOW_UNSAFE_VM` | `system.allowUnsafeVM` | 是否允许运行 VM 模式自定义源脚本 (需注意安全风险) | `false` | diff --git a/README_EN.md b/README_EN.md index e5541284..17bb3257 100644 --- a/README_EN.md +++ b/README_EN.md @@ -290,6 +290,8 @@ Edit `config.js` directly. Environment variables take precedence: | `SUBSONIC_ONLINE_SEARCH_MODE` | `subsonic.onlineSearchMode` | Subsonic online search mode (`fallback` / `merge` / `local_only`) | `fallback` | | `SUBSONIC_ONLINE_SEARCH_SOURCES` | `subsonic.onlineSearchSources` | Subsonic online search default platforms | `wy,tx,kw,kg,mg` | | `SUBSONIC_LYRIC_TRANSLATION` | `subsonic.lyricTranslation` | Include translations in Subsonic lyrics | `true` | +| `SUBSONIC_CACHE_ON_PLAY` | `subsonic.cacheOnPlay` | Trigger server caching on Subsonic playback (cached to user dir) | `false` | +| `SUBSONIC_PLAY_CACHE_FIRST` | `subsonic.playCacheFirst` | Prefer streaming local cached/downloaded files on Subsonic playback | `true` | | `ARTIST_MAX_FETCH_PAGES` | `artist.maxFetchPages` | Maximum fetch pages for artist tracks | `20` | | `CACHE_NAMING_PATTERN` | `cache.namingPattern` | Cache file naming rule (`simple` / `custom`) | `simple` | | `SYSTEM_ALLOW_UNSAFE_VM` | `system.allowUnsafeVM` | Allow VM mode custom source scripts (note security risks) | `false` | diff --git a/changelog.md b/changelog.md index cab1abb1..7325f015 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,28 @@ # Changelog +## v2.0.2 (2026-09-07) + +### 🌟 新增功能 + +- **Subsonic 播放缓存能力 **: + - **播放时触发服务器缓存 (#339 @pyss56)**: 新增 `subsonic.cacheOnPlay` 独立开关,支持在通过 Subsonic 协议播放音乐时,在后台自动将曲目落盘至用户的缓存目录,已缓存的会自动跳过,极大增强离线体验。(注意:开启此项可能产生较大流量) + - **服务器存在缓存优先播放**: 新增独立开关,开启后通过 Subsonic 播放曲目时,若服务器已存在该歌曲的缓存或下载文件,将直接通过本地流式传输,避免重复向源站发起请求。 + - **切歌并发控制**: 为防止用户在客户端快速切歌导致后台并行下载任务堆积跑满带宽,新增了流式响应的 Abort (取消) 控制器调度机制,在客户端断开连接时自动终止缓存任务。 + - ![Subsonic Settings](md/log/2.0.2-1.png) +- **Subsonic 红心收藏/取消收藏功能与持久化联动 (#338 @pyss56)**: + - **红心收藏与写入**: 新增 Subsonic 协议 star 与 unstar 接口,支持单曲(id)、专辑(albumId)与歌手(artistId)收藏。歌曲实时写入/移出用户的「我的收藏(love)」歌单并生成快照持久化。 + - **在线兜底解析**: 收藏不在本地歌单中的单曲时,支持自动通过平台源在线反查元数据后写入收藏。 + - **媒体库双向联动**: 建立 `subsonic-meta.json` 扩展元数据,打通音流等客户端与 LX Web 前端原生媒体库(artists.json / albums.json)的双向收藏同步。 + - **星标状态与封面防崩**: 优化 getArtists / getArtist 及单曲对象,实时回显 starred 标记;修复专辑封面读取导致的 Node 服务异常,提升客户端交互体验与稳定性。 +- **Subsonic 在线元数据落盘持久化**: + - 将此前仅存于内存的在线歌曲缓存升级为磁盘文件持久化(写入 `subsonic-online-cache.json`),引入防抖批量聚合与原子写入,彻底解决服务端重启导致检索元数据丢失的问题。 + +### 🔧 修复与优化 + +- **Subsonic 收藏 (红心) 状态全局联动修复**: + - **`getStarred` 接口精准剥离**: 修复了获取已星标收藏列表时,服务端错误地聚合所有自定义歌单的 Bug。现在客户端的“我的收藏”严格镜像服务端的 `love` 列表。 + - **红心状态全局透传**: 改进底层的 `musicToSongFlat` 等序列化映射,现在无论是搜索列表、专辑详情、流派浏览还是随机打乱等 11 个接口,只要歌曲存在于当前用户的收藏中,均能准确返回 `starred` 时间戳,完美点亮客户端的红心图标。 + - **收藏状态零延迟同步**: 修复了此前执行收藏/取消收藏动作时,服务端底层的 `loveIdSets` 未同步更新的 Bug。点按红心不仅立刻落盘,还会瞬间同步内存态,使客户端下次请求时状态不再滞后。 ## v2.0.1 (2026-07-23) ### 🌟 新增功能 diff --git a/config.js b/config.js index 03958cce..ed7f443d 100644 --- a/config.js +++ b/config.js @@ -192,6 +192,14 @@ module.exports = { // 环境变量: SUBSONIC_LYRIC_TRANSLATION "subsonic.lyricTranslation": true, + // 是否在 Subsonic 播放音乐时触发服务器缓存保存 (落盘到该用户缓存目录,已缓存自动跳过) + // 环境变量: SUBSONIC_CACHE_ON_PLAY (true/false) + "subsonic.cacheOnPlay": false, + + // 是否在 Subsonic 播放音乐时优先使用本地缓存/下载文件直接流式传输 (默认开启) + // 环境变量: SUBSONIC_PLAY_CACHE_FIRST (true/false) + "subsonic.playCacheFirst": true, + // 歌手信息源优先级 (多个源用逗号分隔,如 tx,wy) // 环境变量: SINGER_SOURCE_PRIORITY "singer.sourcePriority": [ diff --git a/md/log/2.0.2-1.png b/md/log/2.0.2-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f82fade734c784273137c355795542de91ac1579 GIT binary patch literal 218829 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%0AkIUaFTuY=# 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 协议配置

+
+
+ 服务器存在缓存优先播放 + 通过 Subsonic 播放曲目时,若服务器已存在该歌曲缓存或下载文件,直接通过本地传输,避免请求源站 +
+ +
diff --git a/public/js/config.js b/public/js/config.js index 436fd2ca..a798a249 100644 --- a/public/js/config.js +++ b/public/js/config.js @@ -2,6 +2,6 @@ // 其余配置由服务端在运行时动态注入 (环境变量 > config.js > defaultConfig.ts) // 服务端拦截 /js/config.js 请求, 读取此处版本号并合并服务端配置后返回 window.CONFIG = { - buildHash: '32fe900', + buildHash: 'a0f2b33', version: 'v2.0.1', }; diff --git a/src/constants.ts b/src/constants.ts index a54e53f4..b12cda4d 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -42,6 +42,8 @@ export const ENV_PARAMS = [ 'SUBSONIC_ONLINE_SEARCH_MODE', 'SUBSONIC_ONLINE_SEARCH_SOURCES', 'SUBSONIC_LYRIC_TRANSLATION', + 'SUBSONIC_CACHE_ON_PLAY', + 'SUBSONIC_PLAY_CACHE_FIRST', 'ARTIST_MAX_FETCH_PAGES', 'CACHE_NAMING_PATTERN', 'SYSTEM_ALLOW_UNSAFE_VM', diff --git a/src/defaultConfig.ts b/src/defaultConfig.ts index a3a8b451..2f0b2b68 100644 --- a/src/defaultConfig.ts +++ b/src/defaultConfig.ts @@ -67,6 +67,7 @@ const config: LX.Config = { 'subsonic.onlineSearchSources': 'wy,tx,kw,kg,mg', // 在线搜索默认平台 'subsonic.lyricTranslation': true, // 是否在 Subsonic 歌词中包含翻译 'subsonic.cacheOnPlay': false, // 是否在 Subsonic 播放时触发服务器缓存保存(落盘) + 'subsonic.playCacheFirst': true, // 是否在 Subsonic 播放时优先使用服务器已有的本地缓存/下载文件直接传输 'singer.sourcePriority': ['tx', 'wy'], // 歌手信息源优先级 'artist.maxFetchPages': 20, // 歌手歌曲最大抓取页数 'cache.namingPattern': 'simple', // 缓存命名规则 diff --git a/src/index.ts b/src/index.ts index 7df99abd..e7f83ecc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -301,6 +301,12 @@ if (envParams.SUBSONIC_ONLINE_SEARCH_SOURCES) { if (envParams.SUBSONIC_LYRIC_TRANSLATION !== undefined) { setBoolConfig('subsonic.lyricTranslation', envParams.SUBSONIC_LYRIC_TRANSLATION) } +if (envParams.SUBSONIC_CACHE_ON_PLAY !== undefined) { + setBoolConfig('subsonic.cacheOnPlay', envParams.SUBSONIC_CACHE_ON_PLAY) +} +if (envParams.SUBSONIC_PLAY_CACHE_FIRST !== undefined) { + setBoolConfig('subsonic.playCacheFirst', envParams.SUBSONIC_PLAY_CACHE_FIRST) +} if (envParams.ARTIST_MAX_FETCH_PAGES) { const pages = parseInt(envParams.ARTIST_MAX_FETCH_PAGES, 10) if (!isNaN(pages) && pages > 0) global.lx.config['artist.maxFetchPages'] = pages diff --git a/src/server/server.ts b/src/server/server.ts index 0f7da72c..5e22a7b1 100644 --- a/src/server/server.ts +++ b/src/server/server.ts @@ -5853,6 +5853,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro 'subsonic.onlineSearchSources': global.lx.config['subsonic.onlineSearchSources'] ?? 'wy,tx,kw,kg,mg', 'subsonic.lyricTranslation': global.lx.config['subsonic.lyricTranslation'] ?? true, 'subsonic.cacheOnPlay': global.lx.config['subsonic.cacheOnPlay'] ?? false, + 'subsonic.playCacheFirst': global.lx.config['subsonic.playCacheFirst'] ?? true, 'singer.sourcePriority': (global.lx.config['singer.sourcePriority'] || ['tx', 'wy']).join(','), 'artist.maxFetchPages': global.lx.config['artist.maxFetchPages'] ?? 20, 'system.allowUnsafeVM': global.lx.config['system.allowUnsafeVM'] || false, @@ -5966,6 +5967,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro if (newConfig['subsonic.onlineSearchSources'] !== undefined) global.lx.config['subsonic.onlineSearchSources'] = newConfig['subsonic.onlineSearchSources'] if (newConfig['subsonic.lyricTranslation'] !== undefined) global.lx.config['subsonic.lyricTranslation'] = newConfig['subsonic.lyricTranslation'] if (newConfig['subsonic.cacheOnPlay'] !== undefined) global.lx.config['subsonic.cacheOnPlay'] = newConfig['subsonic.cacheOnPlay'] + if (newConfig['subsonic.playCacheFirst'] !== undefined) global.lx.config['subsonic.playCacheFirst'] = newConfig['subsonic.playCacheFirst'] if (newConfig['singer.sourcePriority'] !== undefined) { const priority = String(newConfig['singer.sourcePriority']).split(',').filter(s => s === 'tx' || s === 'wy') as Array<'tx' | 'wy'> if (priority.length > 0) global.lx.config['singer.sourcePriority'] = priority @@ -6036,6 +6038,7 @@ const handleStartServer = async (port = 9527, ip = '127.0.0.1') => await new Pro 'subsonic.onlineSearchSources': global.lx.config['subsonic.onlineSearchSources'], 'subsonic.lyricTranslation': global.lx.config['subsonic.lyricTranslation'], 'subsonic.cacheOnPlay': global.lx.config['subsonic.cacheOnPlay'], + 'subsonic.playCacheFirst': global.lx.config['subsonic.playCacheFirst'], 'singer.sourcePriority': global.lx.config['singer.sourcePriority'], 'artist.maxFetchPages': global.lx.config['artist.maxFetchPages'], 'cache.namingPattern': global.lx.config['cache.namingPattern'], diff --git a/src/server/subsonic.ts b/src/server/subsonic.ts index 3d6662d8..ba3f533b 100644 --- a/src/server/subsonic.ts +++ b/src/server/subsonic.ts @@ -144,6 +144,9 @@ class SubsonicHandler { // [修复] onlineSongCache 真正落盘持久化:之前只是内存 Map,重启即丢,导致 kw 等回源结果无法复用 private onlineSongCacheLoaded = false + // Subsonic 播放缓存后台任务跟踪:username -> { songKey, controller },用于切歌时自动取消上一首未完成的下载 + private subsonicActiveTasks = new Map() + // 固定同一关键词的在线结果顺序,避免客户端翻页时出现重复或跳项。 private onlineSearchCache = new Map() @@ -188,20 +191,26 @@ class SubsonicHandler { } } - // 每新增一首歌即同步落盘(只在 cacheOnlineSong 新增唯一 id 时触发,频率很低)。 - // 用「临时文件 + rename」做原子写:避免进程在写入中途被强杀导致文件截断损坏。 + private saveOnlineSongCacheTimer: NodeJS.Timeout | null = null + + // 磁盘持久化:使用 1 秒防抖批量落盘,避免搜索/加载大专辑时并发重复写盘 + // 采用「临时文件 + rename」做原子写:避免进程在写入中途被强杀导致文件损坏 private saveOnlineSongCache() { - try { - const p = this.getOnlineSongCachePath() - const dir = path.dirname(p) - if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }) - const arr = Array.from(this.onlineSongCache.values()) - const tmp = `${p}.${process.pid}.tmp` - fs.writeFileSync(tmp, JSON.stringify(arr), 'utf8') - fs.renameSync(tmp, p) - } catch (e) { - console.error('[Subsonic] 保存 onlineSongCache 失败:', e) - } + if (this.saveOnlineSongCacheTimer) return + this.saveOnlineSongCacheTimer = setTimeout(() => { + this.saveOnlineSongCacheTimer = null + try { + const p = this.getOnlineSongCachePath() + const dir = path.dirname(p) + if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true }) + const arr = Array.from(this.onlineSongCache.values()) + const tmp = `${p}.${process.pid}.tmp` + fs.writeFileSync(tmp, JSON.stringify(arr), 'utf8') + fs.renameSync(tmp, p) + } catch (e) { + console.error('[Subsonic] 保存 onlineSongCache 失败:', e) + } + }, 1000) } private cacheOnlineSong(music: LX.Music.MusicInfo) { @@ -619,7 +628,7 @@ class SubsonicHandler { /** * 将 MusicInfo 映射为 Subsonic child/song 的平铺 JS 对象(适用于 JSON 响应) */ - private musicToSongFlat(music: LX.Music.MusicInfo, parentId: string, artistIdOverride?: string) { + private musicToSongFlat(music: LX.Music.MusicInfo, parentId: string, artistIdOverride?: string, username?: string) { const meta = (music as any).meta || {} const id = music.id @@ -657,6 +666,8 @@ class SubsonicHandler { const defaultArtistId = (music as any).singerId ? `art_${source}_${(music as any).singerId}` : `artist_${primarySinger}` const finalArtistId = artistIdOverride || defaultArtistId + const starred = (username && this.loveIdSets.get(username)?.has(id)) ? new Date().toISOString() : undefined + return { id, parent: parentId, @@ -672,6 +683,7 @@ class SubsonicHandler { coverArt: (picUrl && typeof picUrl === 'string' && picUrl.startsWith('http')) ? picUrl : id, duration: this.parseDuration(music.interval), ...this.getBestQualityMeta(music), + ...(starred ? { starred } : {}), isVideo: false, isDir: false, // 某些客户端 (如 Feishin) 在特定视图下不喜欢非标准字段,可以保留但确保标准字段优先 @@ -726,8 +738,8 @@ class SubsonicHandler { /** * 将 MusicInfo 映射为 XML 渲染格式 {attrs, children?} */ - private musicToSongXml(music: LX.Music.MusicInfo, parentId: string, artistIdOverride?: string) { - return { attrs: this.musicToSongFlat(music, parentId, artistIdOverride) } + private musicToSongXml(music: LX.Music.MusicInfo, parentId: string, artistIdOverride?: string, username?: string) { + return { attrs: this.musicToSongFlat(music, parentId, artistIdOverride, username) } } /** 查找某个用户下所有列表中的某首歌 */ @@ -937,7 +949,7 @@ class SubsonicHandler { return this.sendResponse(res, { playlist: { ...playlistMeta, - entry: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id)), + entry: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, undefined, username)), }, }, format) } @@ -946,7 +958,7 @@ class SubsonicHandler { playlist: { attrs: playlistMeta, children: { - entry: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id)), + entry: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, undefined, username)), }, }, }, format) @@ -1277,7 +1289,7 @@ class SubsonicHandler { return this.sendResponse(res, { album: { ...albumMeta, - song: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, albumMeta.artistId)), + song: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, albumMeta.artistId, username)), }, }, format) } @@ -1286,7 +1298,7 @@ class SubsonicHandler { album: { attrs: albumMeta, children: { - song: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, albumMeta.artistId)), + song: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, albumMeta.artistId, username)), }, }, }, format) @@ -1326,9 +1338,9 @@ class SubsonicHandler { if (!music) return this.sendError(res, 70, 'Song not found: ' + id, format) if (format === 'json') { - return this.sendResponse(res, { song: this.musicToSongFlat(music, listId) }, format) + return this.sendResponse(res, { song: this.musicToSongFlat(music, listId, undefined, username) }, format) } - return this.sendResponse(res, { song: this.musicToSongXml(music, listId) }, format) + return this.sendResponse(res, { song: this.musicToSongXml(music, listId, undefined, username) }, format) } private async handleGetMusicDirectory(res: http.ServerResponse, username: string, params: URLSearchParams, format: string) { @@ -1431,7 +1443,7 @@ class SubsonicHandler { directory: { id, name: dirName, - child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id)), + child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, undefined, username)), }, }, format) } @@ -1439,7 +1451,7 @@ class SubsonicHandler { directory: { attrs: { id, name: dirName }, children: { - child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id)), + child: musics.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, undefined, username)), }, }, }, format) @@ -1730,7 +1742,7 @@ class SubsonicHandler { artist: { ...artistInfo, album: albums, - song: hotSongs.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, id)) + song: hotSongs.map((m: LX.Music.MusicInfo) => this.musicToSongFlat(m, id, id, username)) }, }, format) } @@ -1739,7 +1751,7 @@ class SubsonicHandler { attrs: artistInfo, children: { album: albums.map(a => ({ attrs: a })), - song: hotSongs.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, id)) + song: hotSongs.map((m: LX.Music.MusicInfo) => this.musicToSongXml(m, id, id, username)) }, }, }, format) @@ -2146,7 +2158,7 @@ class SubsonicHandler { [wrapKey]: { artist: pagedArtists, album: pagedAlbums, - song: pagedSongs.map(({ music, listId }) => this.musicToSongFlat(music, listId)), + song: pagedSongs.map(({ music, listId }) => this.musicToSongFlat(music, listId, undefined, username)), }, }, format) } @@ -2155,7 +2167,7 @@ class SubsonicHandler { children: { artist: pagedArtists.map(a => ({ attrs: a })), album: pagedAlbums.map(a => ({ attrs: a })), - song: pagedSongs.map(({ music, listId }) => this.musicToSongXml(music, listId)), + song: pagedSongs.map(({ music, listId }) => this.musicToSongXml(music, listId, undefined, username)), }, }, }, format) @@ -2281,21 +2293,22 @@ class SubsonicHandler { /** 统一元数据解析原语:本地/缓存 -> 在线回源;命中即回写 onlineSongCache */ private async resolveSongMeta(username: string, id: string): Promise<{ music: LX.Music.MusicInfo, listId: string } | null> { - console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步 查持久化(歌单/专辑库) + 内存/磁盘 onlineSongCache`) + const debug = !!global.lx.config['subsonic.enableDebug'] + if (debug) console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步 查持久化(歌单/专辑库) + 内存/磁盘 onlineSongCache`) const found = await this.findMusicById(username, id) if (found) { this.cacheOnlineSong(found.music) - console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步命中 listId=${found.listId}, name=${found.music.name || '(空)'}`) + if (debug) console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步命中 listId=${found.listId}, name=${found.music.name || '(空)'}`) return found } - console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步未命中 -> 第2步 在线回源(network)`) + if (debug) console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第1步未命中 -> 第2步 在线回源(network)`) const resolved = await this.resolveMusicById(id) if (resolved) { this.cacheOnlineSong(resolved) - console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源成功 name=${resolved.name}, 已写 onlineSongCache(内存+磁盘)`) + if (debug) console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源成功 name=${resolved.name}, 已写 onlineSongCache(内存+磁盘)`) return { music: resolved, listId: 'online' } } - console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源失败 -> 返回 null(将在 stream 中降级为 Unknown)`) + if (debug) console.log(`[Subsonic][trace] resolveSongMeta ${id}: 第2步回源失败 -> 返回 null(将在 stream 中降级为 Unknown)`) return null } @@ -2444,10 +2457,13 @@ class SubsonicHandler { console.warn(`[Subsonic] ${action} 歌曲 ${id} 跳过:findMusicById 未命中 且 resolveMusicById 失败,未做任何改动 (user=${username})`) continue } + if (!this.loveIdSets.has(username)) this.loveIdSets.set(username, new Set()) if (isStar) { await userSpace.listManage.listDataManage.listMusicAdd('love', [resolved], location) + this.loveIdSets.get(username)!.add(resolved.id) } else { await userSpace.listManage.listDataManage.listMusicRemove('love', [resolved.id]) + this.loveIdSets.get(username)!.delete(resolved.id) } const fromSource = hit!.listId === 'online' debugLog(`[Subsonic Debug] ${action} 歌曲 ${id} -> ${isStar ? '已加入' : '已移出'}我的收藏(love) 《${resolved.name}》${fromSource ? ' (从源取回)' : ''}(user=${username})`) @@ -2498,10 +2514,7 @@ class SubsonicHandler { } } collect(listData.loveList, 'love') - collect(listData.defaultList, 'default') - for (const list of listData.userList) { - collect((list.list || []) as LX.Music.MusicInfo[], list.id) - } + // 只返回我的收藏里的歌,不再汇总其他歌单 const allSongs = Array.from(allSongsMap.values()) // [新增] 包含收藏的歌手和专辑 @@ -2550,7 +2563,7 @@ class SubsonicHandler { if (format === 'json') { return this.sendResponse(res, { [wrapKey]: { - song: allSongs.map(item => this.musicToSongFlat(item.music, item.listId)), + song: allSongs.map(item => this.musicToSongFlat(item.music, item.listId, undefined, username)), album: mappedAlbums, artist: mappedArtists, }, @@ -2559,7 +2572,7 @@ class SubsonicHandler { return this.sendResponse(res, { [wrapKey]: { children: { - song: allSongs.map(item => this.musicToSongXml(item.music, item.listId)), + song: allSongs.map(item => this.musicToSongXml(item.music, item.listId, undefined, username)), album: mappedAlbums.map(a => ({ attrs: a })), artist: mappedArtists.map(a => ({ attrs: a })), }, @@ -2598,7 +2611,7 @@ class SubsonicHandler { if (cloudSongs.length > 0) { const parentId = `genre_${genreNameOrId}` const picked = cloudSongs.map((s: any) => ({ music: s, listId: parentId })) - return this.renderRandomSongs(res, picked, format, rootKey) + return this.renderRandomSongs(res, picked, format, rootKey, username) } } catch (e) { console.error(`[Subsonic] fetchSongsByGenre failed:`, e) @@ -2620,21 +2633,21 @@ class SubsonicHandler { [all[i], all[j]] = [all[j], all[i]] } const picked = all.slice(0, size) - return this.renderRandomSongs(res, picked, format, rootKey) + return this.renderRandomSongs(res, picked, format, rootKey, username) } - private renderRandomSongs(res: http.ServerResponse, picked: { music: LX.Music.MusicInfo, listId: string }[], format: string, rootKey: string = 'randomSongs') { + private renderRandomSongs(res: http.ServerResponse, picked: { music: LX.Music.MusicInfo, listId: string }[], format: string, rootKey: string = 'randomSongs', username?: string) { if (format === 'json') { return this.sendResponse(res, { [rootKey]: { - song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId, undefined, username)), }, }, format) } return this.sendResponse(res, { [rootKey]: { children: { - song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId, undefined, username)), }, }, }, format) @@ -2685,14 +2698,14 @@ class SubsonicHandler { if (format === 'json') { return this.sendResponse(res, { [wrapKey]: { - song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId, undefined, username)), }, }, format) } return this.sendResponse(res, { [wrapKey]: { children: { - song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId, undefined, username)), }, }, }, format) @@ -2746,7 +2759,31 @@ class SubsonicHandler { const result = await callUserApiGetMusicUrl('tx', musicInfo, quality, username) if (result && result.url) { - // console.log(`[Subsonic] Radio ${id} resolved URL: ${result.url.slice(0, 50)}...`) + if (global.lx.config['subsonic.cacheOnPlay'] && username) { + const songKey = `tx_${songmid}_${quality}` + const previous = this.subsonicActiveTasks.get(username) + if (previous && previous.songKey !== songKey) { + console.log(`[Subsonic] User ${username} switched radio track, aborting previous background cache task: ${previous.songKey}`) + previous.controller.abort() + } + + const controller = new AbortController() + this.subsonicActiveTasks.set(username, { songKey, controller }) + + void downloadAndCache(musicInfo, result.url, quality, username, controller.signal, false, true, true, { + requestedSource: 'tx', + downloadSource: 'tx', + sourceName: 'tx', + }).catch((err: any) => { + if (err?.message !== 'Aborted') { + console.error('[Subsonic] radio cacheOnPlay failed:', err?.message || err) + } + }).finally(() => { + if (this.subsonicActiveTasks.get(username)?.controller === controller) { + this.subsonicActiveTasks.delete(username) + } + }) + } res.writeHead(302, { Location: result.url }) return res.end() } else { @@ -2758,11 +2795,13 @@ class SubsonicHandler { return this.sendError(res, 0, 'Could not resolve radio track', format) } - // [新增] 本地缓存优先播放:若该歌曲已存在于用户的 cache 或 music 目录,直接流式回传本地文件,避免请求源站 - const cacheCheck = checkCache({ source, songmid, id, quality }, username, false) - if (cacheCheck.exists && cacheCheck.filename) { - console.log(`[Subsonic] Stream hit local cache for ${id} (${cacheCheck.quality || quality}): ${cacheCheck.filename} (${cacheCheck.folder})`) - return serveCacheFile(req, res, cacheCheck.filename, username) + // [新增] 本地缓存优先播放:受 subsonic.playCacheFirst 开关控制(默认开启),若该歌曲已存在于用户的 cache 或 music 目录,直接流式回传本地文件,避免请求源站 + if (global.lx.config['subsonic.playCacheFirst'] !== false) { + const cacheCheck = checkCache({ source, songmid, id, quality }, username, false) + if (cacheCheck.exists && cacheCheck.filename) { + console.log(`[Subsonic] Stream hit local cache for ${id} (${cacheCheck.quality || quality}): ${cacheCheck.filename} (${cacheCheck.folder})`) + return serveCacheFile(req, res, cacheCheck.filename, username) + } } // [修复] 像 star 一样:先用 findMusicById 查本地/缓存,查不到再在线回源补全真实元数据 @@ -2779,8 +2818,10 @@ class SubsonicHandler { musicInfo = { source, songmid, id, meta: { songId: songmid } } } // [诊断] 打印回源结果与客户端的歌曲元数据参数,便于排查 kw 等源仍为 Unknown 的问题 - console.log(`[Subsonic] stream resolve ${id}: name=${musicInfo.name || '(空)'} singer=${musicInfo.singer || '(空)'} album=${musicInfo.meta?.albumName || '(空)'}`) - console.log(`[Subsonic] stream params: name=${params.get('name') || ''} title=${params.get('title') || ''} artist=${params.get('artist') || ''} album=${params.get('album') || ''}`) + if (global.lx.config['subsonic.enableDebug']) { + console.log(`[Subsonic] stream resolve ${id}: name=${musicInfo.name || '(空)'} singer=${musicInfo.singer || '(空)'} album=${musicInfo.meta?.albumName || '(空)'}`) + console.log(`[Subsonic] stream params: name=${params.get('name') || ''} title=${params.get('title') || ''} artist=${params.get('artist') || ''} album=${params.get('album') || ''}`) + } // [修复] 客户端(音流)通常在 stream 请求里附带真实元数据(name/artist/album), // 用于补充 Subsonic 自身不完整的歌曲信息(kw 等无 getMusicInfo 的源尤其依赖它) if (!musicInfo.name) { @@ -2839,17 +2880,33 @@ class SubsonicHandler { if (result && result.url) { // [诊断] 打印缓存触发决策,便于排查 Subsonic 播放不缓存问题 console.log(`[Subsonic] stream cacheOnPlay: enabled=${global.lx.config['subsonic.cacheOnPlay']} user=${username} url=${String(result.url).slice(0, 90)}`) - // [新增] 播放时触发服务器缓存保存:受 subsonic.cacheOnPlay 开关控制, - // 后台落盘到该用户缓存目录;downloadAndCache 内部会去重(已存在则跳过),不会重复下载。 + // [新增] 播放时触发服务器缓存保存:受 subsonic.cacheOnPlay 开关控制 + // 后台落盘到该用户缓存目录;已在播放的上一首若未下载完成,在切换新歌曲时自动 abort 中断,避免连切刷歌堆积带宽 if (global.lx.config['subsonic.cacheOnPlay'] && username) { - void downloadAndCache(musicInfo, result.url, quality, username, undefined, false, true, true, { + const songKey = `${source}_${songmid}_${quality}` + const previous = this.subsonicActiveTasks.get(username) + if (previous && previous.songKey !== songKey) { + console.log(`[Subsonic] User ${username} switched track, aborting previous background cache task: ${previous.songKey}`) + previous.controller.abort() + } + + const controller = new AbortController() + this.subsonicActiveTasks.set(username, { songKey, controller }) + + void downloadAndCache(musicInfo, result.url, quality, username, controller.signal, false, true, true, { requestedSource: source, downloadSource: source, sourceName: source, }).then(() => { console.log(`[Subsonic] cacheOnPlay: cache task done for ${musicInfo.id} (${quality})`) }).catch((err: any) => { - console.error('[Subsonic] cacheOnPlay failed:', err?.message || err) + if (err?.message !== 'Aborted') { + console.error('[Subsonic] cacheOnPlay failed:', err?.message || err) + } + }).finally(() => { + if (this.subsonicActiveTasks.get(username)?.controller === controller) { + this.subsonicActiveTasks.delete(username) + } }) } res.writeHead(302, { Location: result.url }) @@ -3132,14 +3189,14 @@ class SubsonicHandler { if (format === 'json') { return this.sendResponse(res, { topSongs: { - song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongFlat(music, listId, undefined, username)), }, }, format) } return this.sendResponse(res, { topSongs: { children: { - song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId)), + song: picked.map(({ music, listId }) => this.musicToSongXml(music, listId, undefined, username)), }, }, }, format) diff --git a/src/types/config.d.ts b/src/types/config.d.ts index a3e0fcf9..fca321d6 100644 --- a/src/types/config.d.ts +++ b/src/types/config.d.ts @@ -272,6 +272,12 @@ declare namespace LX { */ 'subsonic.cacheOnPlay'?: boolean + /** + * 是否在 Subsonic 播放音乐时优先使用本地缓存/下载文件直接流式传输 (默认 true) + * 开启后,若服务器该用户目录下已存在此歌曲的缓存或下载文件,直接传输本地流,避免向源站请求在线直链 + */ + 'subsonic.playCacheFirst'?: boolean + /** * 歌手信息源优先级 */ From 6037de0dc72a3e22d2a2ae141d50f19c73c83524 Mon Sep 17 00:00:00 2001 From: XCQ0607 Date: Mon, 7 Sep 2026 10:29:30 +0800 Subject: [PATCH 11/24] =?UTF-8?q?fix(filemanager):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E5=90=8E=E5=8F=B0=E5=AF=BC=E8=88=AA=E8=B7=B3?= =?UTF-8?q?=E8=BD=AC=E5=B9=B6=E5=8D=87=E7=BA=A7=20Material=20=E7=8E=B0?= =?UTF-8?q?=E4=BB=A3=E4=B8=BB=E9=A2=98=20(#341)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - fix(filemanager): 修复快捷栏按钮无法准确返回自定义管理后台的问题 - 引入 `/js/config.js` 动态注入服务端运行态配置到 `window.CONFIG` - 新增 `goToAdmin()` 路由函数,动态获取 `admin.path`(默认兜底 `/admin`)实现精准跳转 - 将「返回主页」按钮文案优化为「返回后台」,并绑定点击拦截与动态导航事件 - feat(filemanager): 引入 elFinder Material Design 现代主题与视觉优化 - 集成 `@3.0.0` Material Theme 样式库,升级工具栏图标、文件列表与右键菜单交互 - 移除硬编码旧版工具栏底色覆盖,消除与整体现代暗色布局的反差 --- changelog.md | 4 ++++ public/filemanager.html | 18 +++++++++++------- public/js/config.js | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/changelog.md b/changelog.md index 7325f015..061bb912 100644 --- a/changelog.md +++ b/changelog.md @@ -17,6 +17,10 @@ - **Subsonic 在线元数据落盘持久化**: - 将此前仅存于内存的在线歌曲缓存升级为磁盘文件持久化(写入 `subsonic-online-cache.json`),引入防抖批量聚合与原子写入,彻底解决服务端重启导致检索元数据丢失的问题。 +- **文件管理器现代化与路由联动**: + - **动态感知管理后台路径 (#341)**: 将文件管理器快捷操作栏的「返回主页」按钮优化为「返回后台」,通过动态读取服务端 `admin.path` 环境变量与配置(`window.CONFIG['admin.path']`),支持在自定义管理后台路径下精准跳转回对应后台控制台。 + - **引入 Material 现代主题**: 引入现代 Material Design 样式,全面升级工具栏、列表区与右键菜单视觉效果,提供更具质感的扁平与圆角交互体验。 + ### 🔧 修复与优化 - **Subsonic 收藏 (红心) 状态全局联动修复**: diff --git a/public/filemanager.html b/public/filemanager.html index 926cca26..d38730c6 100644 --- a/public/filemanager.html +++ b/public/filemanager.html @@ -17,7 +17,8 @@ - + + @@ -93,10 +94,7 @@ /* elFinder 样式优化 */ .elfinder { font-family: inherit !important; - } - - .elfinder-toolbar { - background: #f8f9fa !important; + border: none !important; }