From a3ab5adcbae922e91b2ffd6448de60d530225f85 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Sat, 11 Apr 2026 18:47:54 -0700 Subject: [PATCH] Backfill MusicBrainz recording ID from Navidrome during database scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Navidrome provides musicBrainzId on tracks — now captured during database updates so the MusicBrainz enrichment worker can skip tracks that already have an MBID. Uses COALESCE on UPDATE to never overwrite existing enrichment data with NULL (safe for Plex/Jellyfin which don't provide this field). Inspired by PR #279 — fixed data loss bug in the original where unconditional UPDATE would erase existing MBIDs. --- core/navidrome_client.py | 1 + database/music_database.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/navidrome_client.py b/core/navidrome_client.py index b366a5f4..81b49f67 100644 --- a/core/navidrome_client.py +++ b/core/navidrome_client.py @@ -120,6 +120,7 @@ class NavidromeTrack: self._album_id = navidrome_data.get('albumId', '') self._artist_id = navidrome_data.get('artistId', '') + self.musicBrainzId = navidrome_data.get('musicBrainzId') def _parse_date(self, date_str: Optional[str]) -> Optional[datetime]: if not date_str: diff --git a/database/music_database.py b/database/music_database.py index 1f5de289..2c4ab73d 100644 --- a/database/music_database.py +++ b/database/music_database.py @@ -4638,6 +4638,9 @@ class MusicDatabase: except Exception: pass + # Extract MusicBrainz recording ID from server if available (Navidrome provides this) + mbid = getattr(track_obj, 'musicBrainzId', None) or None + # Check if track already exists — UPDATE to preserve enrichment columns, # INSERT only for genuinely new tracks cursor.execute("SELECT 1 FROM tracks WHERE id = ? LIMIT 1", (track_id,)) @@ -4646,20 +4649,21 @@ class MusicDatabase: if is_new_track: cursor.execute(""" INSERT INTO tracks - (id, album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) - """, (track_id, album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist)) + (id, album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist, musicbrainz_recording_id, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) + """, (track_id, album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist, mbid)) else: # Update server-provided fields only — preserves spotify_track_id, deezer_id, - # isrc, bpm, musicbrainz IDs, and all other enrichment data + # isrc, bpm, and all other enrichment data cursor.execute(""" UPDATE tracks SET album_id = ?, artist_id = ?, title = ?, track_number = ?, duration = ?, file_path = ?, bitrate = ?, server_source = ?, track_artist = COALESCE(?, track_artist), + musicbrainz_recording_id = COALESCE(?, musicbrainz_recording_id), updated_at = CURRENT_TIMESTAMP WHERE id = ? - """, (album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist, track_id)) + """, (album_id, artist_id, title, track_number, duration, file_path, bitrate, server_source, track_artist, mbid, track_id)) conn.commit()