from enum import Enum from typing import List from external_api.base.available_providers import StreamingProvider from external_api.base.analytics_models import StreamingStats, TrackStreamsQuery, TrackStreamsResult from external_api.base.clients.client import ApiClient from external_api.base.search_models import ( ApolloSearchResponse, Track, Album, ApolloSpotifyPlaylist, ApolloApplePlaylistsResponse, ApolloApplePlaylist, PlaylistImageModel, ) from external_api.playlists.schemas import PlaylistsQuery, PlaylistResults, PlaylistProvider, PlaylistModel from external_api.base.search_models import ApolloSpotifyPlaylistsResponse from utils.async_helpers import await_all MAX_IMAGE_SIZE = 640 class SearchType(Enum): TRACK = "track" ALBUM = "album" class ApolloClient: http_client: ApiClient def __init__(self, client: ApiClient): self.http_client = client async def search(self, query: str, types: List[SearchType], offset: int, limit: int) -> ApolloSearchResponse: item_types = ",".join(t.value for t in types) params = {"offset": offset, "limit": limit, "query": query, "item_type": item_types} return await self.http_client.get( "/vendor-api/spotify/v1/search", params=params, response_type=ApolloSearchResponse ) async def get_spotify_streams_analytics(self, query: TrackStreamsQuery) -> TrackStreamsResult: params = {"isrc": query.isrc, "start_date": query.start_date, "end_date": query.end_date} endpoint = "/apollo-api/spotify/track-per-country/" streaming_stats = await self.http_client.get_list(endpoint, params=params, response_type=StreamingStats) return TrackStreamsResult(provider=StreamingProvider.Spotify, streams=streaming_stats) async def get_apple_streams_analytics(self, query: TrackStreamsQuery) -> TrackStreamsResult: params = {"isrc": query.isrc, "start_date": query.start_date, "end_date": query.end_date} endpoint = "/apollo-api/apple-music/track-per-country/" streaming_stats = await self.http_client.get_list(endpoint, params=params, response_type=StreamingStats) return TrackStreamsResult(provider=StreamingProvider.Apple, streams=streaming_stats) async def get_album_tracks(self, album_id: str) -> List[Track]: def get_track_details(track_id: str): return self.http_client.get("/vendor-api/spotify/v1/tracks/{}".format(track_id), response_type=Track) albums_result = await self.http_client.get( "/vendor-api/spotify/v1/albums/{}".format(album_id), response_type=Album ) tasks = list(map(lambda x: get_track_details(x.id), albums_result.tracks.items)) results = await await_all(tasks) return results async def get_spotify_playlists(self, model: PlaylistsQuery) -> PlaylistResults: query = model.query if model.query else " " params = {"query": query, "item_type": "playlist"} endpoint = "/vendor-api/spotify/v1/search" results = await self.http_client.get(endpoint, params=params, response_type=ApolloSpotifyPlaylistsResponse) mapped_models = [self.__map_spotify_playlist(playlist) for playlist in results.playlists.items] return PlaylistResults(mapped_models, PlaylistProvider.Spotify) def __map_spotify_playlist(self, playlist: ApolloSpotifyPlaylist) -> PlaylistModel: return PlaylistModel(playlist.id, playlist.name, playlist.owner.display_name, playlist.images) async def get_apple_playlists(self, model: PlaylistsQuery) -> PlaylistResults: query = model.query if model.query else " " params = {"query": query, "item_type": "playlists"} endpoint = "/vendor-api/apple/v1/search" response = await self.http_client.get(endpoint, params=params, response_type=ApolloApplePlaylistsResponse) if not response.results.playlists: return PlaylistResults([], PlaylistProvider.Apple) playlists = response.results.playlists.data mapped_models = [self.__map_apple_playlist(playlist) for playlist in playlists if playlist.attributes] return PlaylistResults(mapped_models, PlaylistProvider.Apple) def __map_apple_playlist(self, playlist: ApolloApplePlaylist) -> PlaylistModel: attributes = playlist.attributes if not attributes.artwork: return PlaylistModel(playlist.id, attributes.name, attributes.curatorName, []) image_width = min(attributes.artwork.width, MAX_IMAGE_SIZE) image_height = min(attributes.artwork.height, MAX_IMAGE_SIZE) imege_url = attributes.artwork.url.replace("{h}", str(image_height)).replace("{w}", str(image_width)) image = PlaylistImageModel(url=imege_url, width=image_width, height=image_height) return PlaylistModel(playlist.id, attributes.name, attributes.curatorName, [image])