From 52451f50863ae247c8e6d1e2b2e8180a1e562018 Mon Sep 17 00:00:00 2001 From: Honey Date: Fri, 29 May 2026 01:30:04 +0200 Subject: [PATCH] fix: resolve Japanese-path songs stored as romaji files When Navidrome has a Japanese path in its DB but the file was saved with a romaji filename by the download pipeline, the existing fallback chain compared the Japanese title stem against romaji filenames and always failed. Added _findFileByStemOrRomaji which converts the stem via romajiForStorage before the final recursive search, covering all three endpoints: edit-metadata, delete-song, song-sorttags. Co-Authored-By: Claude Sonnet 4.6 --- backend/novasonic-server.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index 1c5854f..1ea9705 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -116,6 +116,19 @@ function _findFileByStem(dir, titleStem, depth = 0) { return null; } +// Like _findFileByStem but also tries a romaji-converted stem. +// Handles the case where Navidrome has a Japanese path in its DB but the file +// on disk was stored with a romaji filename by the download pipeline. +function _findFileByStemOrRomaji(dir, stem) { + const direct = _findFileByStem(dir, stem); + if (direct) return direct; + try { + const rt = (romajiForStorage(stem) || '').toLowerCase().trim(); + if (rt && rt !== stem) return _findFileByStem(dir, rt); + } catch {} + return null; +} + // ─── QUEUE ──────────────────────────────────────────────────────────────────── let activeDownloads = 0; const downloadQueue = []; @@ -730,7 +743,7 @@ app.get('/api/song-sorttags', async (req, res) => { const found = rebased || _findFileRecursive(CONFIG.musicPath, fileName) || _findFileInDir(rebasedDir || path.dirname(filePath), fileName) - || _findFileByStem(CONFIG.musicPath, titleStem); + || _findFileByStemOrRomaji(CONFIG.musicPath, titleStem); if (found) filePath = found; else return res.status(404).json({ error: 'File not found' }); } try { @@ -865,7 +878,7 @@ app.post('/api/edit-metadata', async (req, res) => { const found = rebased || _findFileRecursive(CONFIG.musicPath, fileName) || _findFileInDir(rebasedDir || originalDir, fileName) - || _findFileByStem(CONFIG.musicPath, titleStem); + || _findFileByStemOrRomaji(CONFIG.musicPath, titleStem); if (found) { filePath = found; } else return res.status(404).json({ error: `File not found: ${filePath} (music root: ${CONFIG.musicPath})` }); } @@ -1053,7 +1066,7 @@ app.post('/api/delete-song', async (req, res) => { const found = _rebasePath(filePath, CONFIG.musicPath) || _findFileRecursive(CONFIG.musicPath, fileName) || _findFileInDir(path.dirname(filePath), fileName) - || _findFileByStem(CONFIG.musicPath, titleStem); + || _findFileByStemOrRomaji(CONFIG.musicPath, titleStem); if (found) filePath = found; else return res.status(404).json({ error: 'File not found on disk' }); }