import asyncio import datetime from typing import Any, Dict from server.client import services from server.constants import DSP from server.constants.playlists.delphi.core.include import PlaylistDates, Playlists from server.constants.tracks import CURRENT_PLACEMENT_TYPE, PAST_PLACEMENT_TYPE from server.scenarios.playlists.tracks.core import process_track_in_playlists_items from server.utils.glom import glom from server.utils.mappers.core.getters import getter from server.utils.parallel import get_awaitable_or_default class TrackInPlaylistScenario: def __init__(self, playlist_id: str, country_code: str, isrc: str, playlist_type: str, dsp: DSP): self.playlist_id = playlist_id self.country_code = country_code self.isrc = isrc self.playlist_type = playlist_type self.dsp = dsp async def _get_playlist_dsp_sync_date_time(self, playlist_item: Dict[str, Any]) -> Dict[str, str]: """Get dsp_sync_date_time for playlist by playlist_id or set default value of today 1. For personalised playlists we make a call to Delphi public/track-positions/playlist/dates endpoint and get the latest dsp_sync_date_time for a particular playlist by playlist_id 2. For non-personalised playlists we assume that dsp_sync_date_time is today() because the data we get is straight from dsp Args: playlist_item: Dict of playlist information Returns: {"dsp_sync_date_time": date we get based on playlist} """ dsp_sync_date_time_task = get_awaitable_or_default( f=services.dsp.get_public_track_positions_playlists_dates, condition=playlist_item.get("is_personalised", False), default=datetime.date.today().isoformat(), playlist_id=self.playlist_id, ) result = await asyncio.gather(dsp_sync_date_time_task) return {"dsp_sync_date_time": getter(result[0], "items.0.dsp_sync_date_time.0", none_result=result[0])} async def get_current_spotify_data(self): current_response, playlist_response = await asyncio.gather( services.dsp.get_public_track_positions_playlists_current_tracklist( playlist_id=self.playlist_id, dsp=DSP.SPOTIFY.value, ), services.dsp.get_public_current_playlists_info(playlist_id=self.playlist_id), ) playlist_row = {} for row in current_response["items"]: if row["isrc"] == self.isrc: playlist_row = row break playlist_row["playlist"] = playlist_response playlist_row["playlist_dates"] = await self._get_playlist_dsp_sync_date_time(playlist_response) return playlist_row async def get_current_apple_data(self): playlist_row = await services.dsp.get_public_track_positions_playlists( dsp=self.dsp.value, isrc=self.isrc, country_code=self.country_code, playlist_id=self.playlist_id, include=[Playlists.PLAYLISTS.value], ) playlist_row = glom(playlist_row, "items.0", default={}) return playlist_row async def get_past_data(self): playlist_row = await services.dsp.get_public_track_positions_previous_playlists( dsp=self.dsp.value, isrc=self.isrc, playlist_id=self.playlist_id, country_code=self.country_code if self.dsp.value == DSP.APPLE.value else None, sort_by="playlist_id", include=[ Playlists.PLAYLISTS.value, PlaylistDates.PLAYLIST_DATES.value, PlaylistDates.DSP_SYNC_DATE_TIME.value, ], ) playlist_row = glom(playlist_row, "items.0", default={}) return playlist_row async def process_data(self, playlist_row): playlist_row = await process_track_in_playlists_items( [ playlist_row, ], dsp=self.dsp, with_playlists=True, ) return playlist_row[0] async def get_track_in_playlist(self): playlist_row = {} if self.playlist_type == CURRENT_PLACEMENT_TYPE and self.dsp == DSP.SPOTIFY: playlist_row = await self.get_current_spotify_data() elif self.playlist_type == CURRENT_PLACEMENT_TYPE and self.dsp == DSP.APPLE: playlist_row = await self.get_current_apple_data() elif self.playlist_type == PAST_PLACEMENT_TYPE: playlist_row = await self.get_past_data() return await self.process_data(playlist_row)