fix(download): dedup missed re-downloads when the title contains ' - ' (KH triple/quadruple)

findExistingTrack split the filename at the first ' - ' assuming 'Artist - Title',
so a title with internal dashes ('Kingdom Hearts 2 - Dearly Beloved - Main Theme')
or a garbage/absent artist prefix ('01-01 - …') was mis-parsed → the duplicate went
undetected and got re-downloaded (3-4x). Now match the query title against BOTH the
full stem AND the part after the first ' - ', so titles with dashes and prefix-only
filenames are recognized. Normal 'Artist - Title' files still match; no false
positives; remix-vs-base distinction preserved. Unit-tested on the exact KH case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Opus 4.8 committed 2026-08-12 17:06:14 +02:00
1 parent 75dceba97b
commit b788fedec3
2 files changed
+61 -4

No files matched your search

+11 -4
View File
@@ -90,11 +90,18 @@ function findExistingTrack(musicRoot, firstArtist, cleanTitle) {
if (!AUDIO_EXTS.includes(ext)) continue;
// Strip extension + leading track prefix ("01 - ", "01-15 – " etc.)
const stem = f.slice(0, -(ext.length + 1)).replace(/^\d[\d-]*\s*[-–—]\s*/, '');
// Stem may be "Artist - Title" or just "Title"
// Candidate titles from the filename. The old code only used the part AFTER the first
// " - " (assuming "Artist - Title"), which mis-parses titles that themselves contain
// " - " (e.g. "Kingdom Hearts 2 - Dearly Beloved - Main Theme") or filenames with a
// garbage/absent artist prefix ("01-01 - …") → the duplicate went undetected and got
// re-downloaded. Now match if ANY reading equals the query title:
// 1) the FULL stem (title with internal dashes, or no clean artist prefix)
// 2) the part after the first " - " (normal "Artist - Title")
const di = stem.indexOf(' - ');
const rawTitle = di >= 0 ? stem.slice(di + 3) : stem;
const normStemTitle = norm(rawTitle.replace(_RELEASE_SUFFIX_RE, ''));
if (titleVariants.has(normStemTitle)) return path.join(albumPath, f);
const candidates = di >= 0 ? [stem, stem.slice(di + 3)] : [stem];
for (const cand of candidates) {
if (titleVariants.has(norm(cand.replace(_RELEASE_SUFFIX_RE, '')))) return path.join(albumPath, f);
}
}
} catch {}
}