diff --git a/packages/backend/src/services/backgroundJobService.ts b/packages/backend/src/services/backgroundJobService.ts index 35023f2..4bc8ccd 100644 --- a/packages/backend/src/services/backgroundJobService.ts +++ b/packages/backend/src/services/backgroundJobService.ts @@ -222,13 +222,15 @@ class BackgroundJobService { }); // Quick filename matching logic - const normalizedS3Filename = filename.replace(/\.[^/.]+$/, '').toLowerCase(); + // Decode URL-encoded sequences so %20, %27 etc. are compared correctly + const safeDecode = (s: string): string => { try { return decodeURIComponent(s); } catch { return s; } }; + const normalizedS3Filename = safeDecode(filename).replace(/\.[^/.]+$/, '').toLowerCase(); let matchedSong = null; for (const song of allSongs) { if (song.location) { const rekordboxFilename = song.location.split(/[/\\]/).pop() || song.location; - const normalizedRekordboxFilename = rekordboxFilename.replace(/\.[^/.]+$/, '').toLowerCase(); + const normalizedRekordboxFilename = safeDecode(rekordboxFilename).replace(/\.[^/.]+$/, '').toLowerCase(); if (normalizedS3Filename === normalizedRekordboxFilename) { matchedSong = song; diff --git a/packages/backend/src/services/songMatchingService.ts b/packages/backend/src/services/songMatchingService.ts index 5e581d3..d072a16 100644 --- a/packages/backend/src/services/songMatchingService.ts +++ b/packages/backend/src/services/songMatchingService.ts @@ -487,8 +487,10 @@ export class SongMatchingService { private matchLocation(filename: string, location: string): { score: number; reason: string } { if (!filename || !location) return { score: 0, reason: '' }; - const cleanFilename = this.cleanString(filename); - const cleanLocation = this.cleanString(location); + // Decode URL-encoded sequences so Rekordbox paths with %20 etc. match S3 keys correctly + const safeDecode = (s: string): string => { try { return decodeURIComponent(s); } catch { return s; } }; + const cleanFilename = this.cleanString(safeDecode(filename)); + const cleanLocation = this.cleanString(safeDecode(location)); // Extract filename from location path (handle different path separators) const pathParts = cleanLocation.split(/[\/\\]/);