""" Author: Uyanide pywang0608@foxmail.com Date: 2026-04-05 02:13:49 Description: Musixmatch metadata enricher (matcher.track.get by Spotify track ID) """ from typing import Optional from loguru import logger from .base import BaseEnricher from ..authenticators.musixmatch import MusixmatchAuthenticator from ..models import TrackMeta from ..config import MUSIXMATCH_TRACK_MATCH_URL class MusixmatchSpotifyEnricher(BaseEnricher): """Fill title, artist, album, and length from Musixmatch using Spotify track ID.""" def __init__(self, auth: MusixmatchAuthenticator) -> None: self.auth = auth @property def name(self) -> str: return "musixmatch" @property def provides(self) -> set[str]: return {"title", "artist", "album", "length"} async def enrich(self, track: TrackMeta) -> Optional[dict]: if not track.trackid: return None logger.debug(f"Musixmatch enricher: looking up trackid={track.trackid}") try: data = await self.auth.get_json( MUSIXMATCH_TRACK_MATCH_URL, {"track_spotify_id": track.trackid}, ) except Exception as e: logger.warning(f"Musixmatch enricher: request failed: {e}") return None if data is None: return None body = data.get("message", {}).get("body") t = body.get("track") if isinstance(body, dict) else None if not isinstance(t, dict): logger.debug( f"Musixmatch enricher: no track data for trackid={track.trackid}" ) return None updates: dict = {} if isinstance(t.get("track_name"), str) and t["track_name"]: updates["title"] = t["track_name"] if isinstance(t.get("artist_name"), str) and t["artist_name"]: updates["artist"] = t["artist_name"] if isinstance(t.get("album_name"), str) and t["album_name"]: updates["album"] = t["album_name"] if isinstance(t.get("track_length"), int) and t["track_length"] > 0: updates["length"] = t["track_length"] * 1000 if updates: logger.debug(f"Musixmatch enricher: filled {list(updates.keys())}") return updates or None