"""Source-artist → library lookup helpers. Extracted from `web_server.py` so the logic can be imported and unit-tested without booting the Flask app, Spotify client, Soulseek connection, etc. Two concepts live here: * ``SOURCE_ID_FIELD`` — the per-source column on the ``artists`` table that stores the external service ID (Spotify track ID, Deezer artist ID, …). This map is what ties a result clicked in the source-aware Search results back to a library record so we can serve the richer library view. * ``find_library_artist_for_source`` — given a source-aware click (e.g. ``deezer:525046``), try to locate a matching library artist. First by direct column match against the source's ID column, then by case- insensitive name match scoped to the active media server. """ from __future__ import annotations import logging from typing import Optional logger = logging.getLogger("artist_source_lookup") SOURCE_ONLY_ARTIST_SOURCES = frozenset({ "spotify", "itunes", "deezer", "discogs", "hydrabase", "musicbrainz", "amazon", }) SOURCE_ID_FIELD = { "spotify": "spotify_artist_id", "itunes": "itunes_artist_id", "deezer": "deezer_id", "discogs": "discogs_id", "hydrabase": "soul_id", "musicbrainz": "musicbrainz_id", "amazon": "amazon_id", } def find_library_artist_for_source( database, source: str, source_artist_id: str, artist_name: Optional[str] = None, active_server: Optional[str] = None, ) -> Optional[str]: """Return the library PK of an artist matching the source-aware click. Lookup order: 1. Direct match on the source-specific ID column (server-agnostic — any library record with the right external ID is a hit). 2. Case-insensitive name match within ``active_server`` (defaults to the active media server when not provided), so we don't jump the user across server contexts on a name collision. Returns ``None`` on miss or on any database error. """ column = SOURCE_ID_FIELD.get(source) if not column: return None try: with database._get_connection() as conn: cursor = conn.cursor() cursor.execute( f"SELECT id, name FROM artists WHERE {column} = ? LIMIT 1", (str(source_artist_id),), ) row = cursor.fetchone() if row: return row[0] if artist_name and active_server: cursor.execute( "SELECT id FROM artists " "WHERE LOWER(name) = LOWER(?) AND server_source = ? LIMIT 1", (artist_name, active_server), ) row = cursor.fetchone() if row: return row[0] except Exception as e: logger.debug( f"Library upgrade lookup failed for {source}:{source_artist_id}: {e}" ) return None