from __future__ import annotations from typing import Any import httpx class LastFmClient: BASE_URL = "https://ws.audioscrobbler.com/2.0/" def __init__(self, api_key: str | None, http: httpx.AsyncClient) -> None: self.api_key = api_key self.http = http @property def enabled(self) -> bool: return bool(self.api_key) async def track_similar(self, *, artist: str, track: str, limit: int = 20) -> list[dict[str, Any]]: if not self.api_key: return [] params = { "method": "track.getSimilar", "api_key": self.api_key, "artist": artist, "track": track, "limit": limit, "format": "json", "autocorrect": 1, } resp = await self.http.get(self.BASE_URL, params=params, timeout=20) resp.raise_for_status() data = resp.json() similar = ((data.get("similartracks") or {}).get("track")) or [] if isinstance(similar, dict): similar = [similar] return similar async def artist_similar(self, *, artist: str, limit: int = 15) -> list[dict[str, Any]]: if not self.api_key: return [] params = { "method": "artist.getSimilar", "api_key": self.api_key, "artist": artist, "limit": limit, "format": "json", "autocorrect": 1, } resp = await self.http.get(self.BASE_URL, params=params, timeout=20) resp.raise_for_status() data = resp.json() similar = ((data.get("similarartists") or {}).get("artist")) or [] if isinstance(similar, dict): similar = [similar] return similar