fix(backend): consistent album for no-album downloads + tolerant editor resolve

Two-part fix for "[Unknown Album]" vs "Singles" mismatch that broke the
metadata editor (File not found):

- Download: always write an album tag, defaulting to "Singles" so it matches
  the on-disk folder (album || 'Singles'). No-album tracks no longer show as
  "[Unknown Album]" while living in a "Singles" folder. (Future downloads.)
- Editor resolve: Subsonic getSong returns a *virtual* tag-built path (e.g.
  "[Unknown Album]/Title.mp3" with raw "|"), not the physical file ("Singles/
  Artist - Title_YTPMV.mp3"). Add findExistingTrack as a final fallback, and
  make its normalizer map the sanitized chars (/ \ : * ? " < > | and _) to a
  space so a title tag matches the sanitized filename. (Fixes existing tracks.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-06-30 20:33:20 +02:00
1 parent 63a7260c94
commit 445a7bf583
3 files changed
+14 -4

No files matched your search

+6 -2
View File
@@ -17,7 +17,7 @@ const crypto = require('crypto');
const CONFIG = require('./lib/config');
const { jobs, updateJob, log } = require('./lib/jobs');
const { sanitize, lookupItunesTrackMeta, fetchItunesTracks, searchItunesAlbumTracks } = require('./lib/metadata');
const { sanitize, lookupItunesTrackMeta, fetchItunesTracks, searchItunesAlbumTracks, findExistingTrack } = require('./lib/metadata');
const { downloadTrack, downloadAlbumTracks } = require('./lib/downloader');
const { buildRomajiIndex, clearRomajiCache, isTokenizerReady, fetchNdSongs, romajiForStorage } = require('./lib/romaji');
@@ -1178,7 +1178,11 @@ app.post('/api/edit-metadata', async (req, res) => {
const found = rebased
|| _findFileRecursive(CONFIG.musicPath, fileName)
|| _findFileInDir(rebasedDir || originalDir, fileName)
|| _findFileByStemOrRomaji(CONFIG.musicPath, titleStem);
|| _findFileByStemOrRomaji(CONFIG.musicPath, titleStem)
// Last resort: Subsonic getSong returns a *virtual* (tag-built) path, so the folder
// can be "[Unknown Album]" while the file actually sits in "Singles" with an artist
// prefix. findExistingTrack matches by normalized artist+title across all album folders.
|| findExistingTrack(CONFIG.musicPath, ndSong.albumArtist || ndSong.artist || '', ndSong.title || '');
if (found) { filePath = found; }
else return res.status(404).json({ error: `File not found: ${filePath} (music root: ${CONFIG.musicPath})` });
}