diff --git a/database/music_database.py b/database/music_database.py index 30957762..c44ebc10 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -5547,6 +5547,18 @@ class MusicDatabase: # Use the best title similarity (direct or cleaned) best_title_similarity = max(title_similarity, clean_title_similarity) + # Length ratio penalty: if the DB title is significantly longer/shorter than the + # search title, it's likely a different track (e.g. "Believe" vs "Believe In Me"). + # SequenceMatcher gives high scores when the shorter string is fully contained + # in the longer one, which causes false positives for prefix/suffix matches. + len_search = len(clean_search_title) if clean_search_title else len(search_title_norm) + len_db = len(clean_db_title) if clean_db_title else len(db_title_norm) + if len_search > 0 and len_db > 0: + len_ratio = min(len_search, len_db) / max(len_search, len_db) + if len_ratio < 0.7: + # Titles differ in length by more than 30% — penalize heavily + best_title_similarity *= len_ratio + # Require minimum title similarity to prevent a perfect artist match from # carrying a bad title match over the threshold (e.g. "Time" vs "Time Flies") if best_title_similarity < 0.6: diff --git a/web_server.py b/web_server.py index b868498a..314c924b 100644 --- a/web_server.py +++ b/web_server.py @@ -19246,6 +19246,15 @@ def get_version_info(): "title": "What's New in SoulSync", "subtitle": f"Version {SOULSYNC_VERSION} — Latest Changes", "sections": [ + { + "title": "🔧 Fix Partial Name Matching False Positives (#225)", + "description": "Track ownership check no longer falsely matches prefix/suffix variations", + "features": [ + "• 'Believe' no longer matches 'Believe In Me' — length ratio penalty prevents partial title matches", + "• Titles differing in length by more than 30% get their similarity score penalized proportionally", + "• Exact matches and cleaned matches (e.g. remastered tags stripped) are unaffected" + ] + }, { "title": "🔧 Fix Pipeline Stops When Metadata Match Fails (#224)", "description": "Playlist sync no longer drops tracks that failed iTunes/Apple Music discovery", diff --git a/webui/static/helper.js b/webui/static/helper.js index b29148af..5fa5efa4 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3403,6 +3403,7 @@ function closeHelperSearch() { const WHATS_NEW = { '2.1': [ // Newest features first + { title: 'Fix Partial Title Matching', desc: '"Believe" no longer falsely matches "Believe In Me" — length ratio penalty prevents prefix false positives' }, { title: 'Fix Pipeline Blocking on Discovery Fail', desc: 'Playlist sync no longer drops tracks that failed metadata discovery — continues with original name/artist for download' }, { title: 'Playlist Explorer', desc: 'New page: expand playlists into visual discovery trees of albums and discographies — select and add to wishlist', page: 'playlist-explorer' }, { title: 'Fix Invalid .LRC Lyrics Files', desc: 'Plain lyrics now saved as .txt — only synced (timestamped) lyrics get the .lrc extension' },