From 0acdd6d0b08a552bd70f42f48e1f3fd5f28a218b Mon Sep 17 00:00:00 2001 From: zarzet <42882290+zarzet@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:28:15 +0700 Subject: [PATCH] fix(metadata): match recording IDs across inconsistent catalogs --- go_backend/title_match_utils.go | 22 +++++++- go_backend/title_match_utils_test.go | 82 ++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/go_backend/title_match_utils.go b/go_backend/title_match_utils.go index f11d5182..8dd55f61 100644 --- a/go_backend/title_match_utils.go +++ b/go_backend/title_match_utils.go @@ -1,6 +1,7 @@ package gobackend import ( + "regexp" "strings" "unicode" @@ -254,7 +255,15 @@ func titlesMatch(expectedTitle, foundTitle string) bool { return false } +var trackTitleAnnotationPattern = regexp.MustCompile(`(?i)[(\[]\s*(?:(?:feat\.?|ft\.?|featuring)\s+[^)\]]+|from\s+["“][^)\]]+["”]\s*)[)\]]`) + +func normalizeTrackIdentityTitle(title string) string { + return normalizeLooseTitle(trackTitleAnnotationPattern.ReplaceAllString(title, " ")) +} + func trackTitlesMatch(expectedTitle, foundTitle string) bool { + expectedTitle = trackTitleAnnotationPattern.ReplaceAllString(expectedTitle, " ") + foundTitle = trackTitleAnnotationPattern.ReplaceAllString(foundTitle, " ") expected := normalizeLooseTitle(expectedTitle) found := normalizeLooseTitle(foundTitle) if expected != "" && expected == found { @@ -417,7 +426,7 @@ func hasStrongTrackIdentity(req DownloadRequest, resolved resolvedTrackInfo) boo return false } - titleExact := exactLooseIdentityMatch(req.TrackName, resolved.Title, normalizeLooseTitle) + titleExact := exactLooseIdentityMatch(req.TrackName, resolved.Title, normalizeTrackIdentityTitle) if !titleExact { return false } @@ -471,6 +480,17 @@ func trackMatchesRequest(req DownloadRequest, resolved resolvedTrackInfo, logPre diff = -diff } if diff > 10 { + // Catalog durations can disagree even for the same recording. Require + // both its ISRC and matching names; a preview still cannot qualify. + if exactISRCMatch && req.TrackName != "" && resolved.Title != "" && + exactLooseIdentityMatch(req.TrackName, resolved.Title, normalizeTrackIdentityTitle) && + req.ArtistName != "" && resolved.ArtistName != "" && + artistsMatch(req.ArtistName, resolved.ArtistName) && + !(resolved.Duration <= 35 && expectedDurationSec > 45) { + GoLog("[%s] Accepted catalog duration difference for matching ISRC and recording names: expected %ds, got %ds\n", + logPrefix, expectedDurationSec, resolved.Duration) + return true + } GoLog("[%s] Verification failed: duration mismatch — expected %ds, got %ds\n", logPrefix, expectedDurationSec, resolved.Duration) return false diff --git a/go_backend/title_match_utils_test.go b/go_backend/title_match_utils_test.go index 9228dfda..08f3960c 100644 --- a/go_backend/title_match_utils_test.go +++ b/go_backend/title_match_utils_test.go @@ -230,6 +230,88 @@ func TestTrackMetadataTolerancePreservesRecordingIdentity(t *testing.T) { } } +func TestTrackIdentityIgnoresCreditAndSoundtrackAnnotations(t *testing.T) { + for _, tc := range []struct { + name string + expected string + found string + want bool + }{ + {"soundtrack", "Signal", `Signal (From "Original Soundtrack")`, true}, + {"mix credit", "Signal - Tiger Style Mix", "Signal (feat. Guest) [Tiger Style Mix]", true}, + {"mix soundtrack", "Signal - Tiger Style Mix", `Signal (Tiger Style Mix) [From "Original Soundtrack"]`, true}, + {"different mix", "Signal - Tiger Style Mix", "Signal (feat. Guest) [Club Mix]", false}, + {"original and mix", "Signal", "Signal (feat. Guest) [Tiger Style Mix]", false}, + {"unrelated title", "Signal", `Another Song (From "Signal")`, false}, + } { + t.Run(tc.name, func(t *testing.T) { + req := DownloadRequest{ + TrackName: tc.expected, ArtistName: "Composer, Singer & Writer", + AlbumName: "Original Soundtrack", DurationMS: 280000, + } + resolved := resolvedTrackInfo{ + Title: tc.found, ArtistName: "Singer & Composer", + AlbumName: "Collection", Duration: 283, + } + if got := trackMatchesRequest(req, resolved, "test"); got != tc.want { + t.Fatalf("trackMatchesRequest = %v, want %v", got, tc.want) + } + tracks := []ExtTrackMetadata{{ + Name: resolved.Title, Artists: resolved.ArtistName, AlbumName: resolved.AlbumName, + DurationMS: resolved.Duration * 1000, ProviderID: "provider", + }} + if got := selectBestMetadataEnrichmentTrack(req, tracks) != nil; got != tc.want { + t.Fatalf("metadata enrichment match = %v, want %v", got, tc.want) + } + resolved.Duration = 244 + if trackMatchesRequest(req, resolved, "test") { + t.Fatal("title annotations must not bypass a duration mismatch") + } + }) + } +} + +func TestTrackIdentityResolvesConflictingCatalogDurations(t *testing.T) { + for _, tc := range []struct { + title string + expected int + found int + }{ + {"Signal", 280000, 244}, + {"Signal (Tiger Style Mix)", 243000, 280}, + } { + t.Run(tc.title, func(t *testing.T) { + req := DownloadRequest{ + TrackName: tc.title, ArtistName: "Composer, Singer & Writer", AlbumName: "Soundtrack", + ISRC: "USAAA0000001", DurationMS: tc.expected, + } + resolved := resolvedTrackInfo{ + Title: tc.title, ArtistName: "Singer & Composer", AlbumName: "Collection", + ISRC: req.ISRC, Duration: tc.found, + } + if !trackMatchesRequest(req, resolved, "test") { + t.Fatal("matching ISRC and recording names should resolve inconsistent catalog durations") + } + for _, isrc := range []string{"", "USAAA0000002"} { + resolved.ISRC = isrc + if trackMatchesRequest(req, resolved, "test") { + t.Fatal("duration discrepancy requires an exact ISRC") + } + } + resolved.ISRC = req.ISRC + resolved.Duration = 30 + if trackMatchesRequest(req, resolved, "test") { + t.Fatal("a preview must not qualify as a catalog duration discrepancy") + } + resolved.Duration = tc.found + resolved.Title += " (Live)" + if trackMatchesRequest(req, resolved, "test") { + t.Fatal("inconsistent names and durations must not qualify on ISRC alone") + } + }) + } +} + func TestTitlesMatch_EmojiStrict(t *testing.T) { if titlesMatch("🪐", "Higher Power") { t.Fatal("expected emoji title not to match unrelated textual title")