from __future__ import annotations from typing import Iterable, Optional import requests from src import config from src.data_info import PlaylistInfo, TrackInfo from src.api_client.atlas.base import BaseAtlasApiClient from src.api_client.errors import VendorApiError __all__ = ["VendorAPIClient"] class VendorAPIClient(BaseAtlasApiClient): default_error_cls = VendorApiError api_base_url = config.VENDOR_API_BASE_URL cache_timeout = config.VENDOR_API_CACHE_TIMEOUT image_base_url = config.IMAGE_BASE_URL batch_size: int = 100 instance: Optional[VendorAPIClient] = None @classmethod def get_client(cls, **kwargs): if not cls.instance: cls.instance = VendorAPIClient( auth_url=config.ATLAS_BASE_URL, client_id=config.ATLAS_CLIENT_ID, client_secret=config.ATLAS_CLIENT_SECRET, audience=config.ATLAS_AUDIENCE, **kwargs, ) return cls.instance @property def cache_headers(self): return {"X-Data-Timeout": str(self.cache_timeout)} def get_spotify_playlist_info(self, playlist_id: str, use_cache: bool = False) -> PlaylistInfo: request = requests.Request( method="get", url=f"{self.api_base_url}/spotify/v1/playlists/{playlist_id}", params={"fields": "name,description,tracks.total,owner(id,display_name)"}, headers=self.cache_headers if use_cache else {}, ) result = self.send_request_with_retry(request).json() return PlaylistInfo( title=result["name"], description=result["description"], total_tracks=result["tracks"]["total"], image_url=f"{self.image_base_url}/playlists/by_spotify_id/{playlist_id}", user_id=result["owner"]["id"], user_name=result["owner"]["display_name"], ) def get_spotify_playlist_tracks(self, playlist_id: str, use_cache: bool = False) -> Iterable[TrackInfo]: request = requests.Request( method="get", url=f"{self.api_base_url}/spotify/v1/playlists/{playlist_id}/tracks", params={"fields": "total,items.track(id,name,artists.name,external_ids.isrc)"}, headers=self.cache_headers if use_cache else {}, ) result = self.send_request_with_retry(request).json() for track_item in result: track_data = track_item["track"] if not track_data: continue yield TrackInfo( id=track_data["id"], title=track_data.get("name", ""), artists=[artist["name"] for artist in track_data.get("artists", []) if "name" in artist], isrc=track_data.get("external_ids", {}).get("isrc"), )