from datetime import date, datetime from http import HTTPStatus from marshmallow import Schema from typing import List, Optional, Type from server.cache.base import get_value_by_key_template from server.client import services from server.constants import DSP from server.constants.distributors import DISTRIBUTORS from server.constants.playlists.delphi.by_api.track_positions_playlists import TrackPositionsPlaylists from server.constants.playlists.v0.misc import PlaylistTracklistOrder from server.scenarios.playlists.tracks.core import check_delphi_include, process_track_in_playlists_items from server.utils.common import unpack_enum_list from server.utils.pagination import multikeysort from server.utils.parallel import make_requests from server.utils.playlists.v0.spotify.misc import filter_playlist_tracklist async def get_playlist_tracklist( playlist_id: str, dsp: DSP, history_date: Optional[date] = None, country_code_list: List[str] = None, streams_country_code_list: List[str] = None, include_list: Optional[List[TrackPositionsPlaylists.INCLUDE]] = None, is_sony_country_code: Optional[str] = None, # 'is_sony' is overridden by passing 'distributors' parameters include_is_sony: bool = False, include_audio_features: bool = False, include_playlist: bool = False, distributors_country_code: Optional[str] = None, distributors: Optional[List[DISTRIBUTORS]] = None, ) -> List[dict]: """Get current (date = None) or history playlist tracklist. Args: playlist_id: Playlist ID. dsp: Playlist DSP filter. history_date: Tracklist date. country_code_list: Playlist country code filter. streams_country_code_list: Streams country code list. include_list: Include list. is_sony_country_code: Country code for is Sony check. include_is_sony: Include is_sony flag. include_audio_features: Include audio features fields. include_playlist: For current get playlist data or not. distributors_country_code: Country code for distributors check (same as for is_sony_country_code) distributors: Distributors list - passing non empty value overrides is_sony_country_code and include_is_sony, they will be ignored. Returns: Playlists tracks. """ include_list = check_delphi_include(include_list, include_is_sony) playlist_data = None if history_date: result = await services.dsp.get_public_track_positions_playlists( start_date=history_date, end_date=history_date, playlist_id=playlist_id, dsp=dsp.value, country_code=country_code_list, streams_country_code=streams_country_code_list, include=unpack_enum_list(include_list), ) else: result, playlist_data = await make_requests( ( ( services.dsp.get_public_track_positions_playlists_current_tracklist, dict( playlist_id=playlist_id, dsp=dsp.value, country_code=country_code_list, streams_country_code=streams_country_code_list, include=unpack_enum_list(include_list), ), ), ( services.dsp.get_public_playlists_info, dict( playlist_id=playlist_id, allowed_status_codes=(HTTPStatus.NOT_FOUND,), # case when user manually opens non-tracked pl ), None, include_playlist, ), ) ) return await process_track_in_playlists_items( result["items"], dsp=dsp, is_sony_country_code=is_sony_country_code, include_is_sony=include_is_sony, include_audio_features=include_audio_features, with_tracks=True, # check playlist_id to exclude 404 response playlist_map={playlist_id: playlist_data} if playlist_data and "playlist_id" in playlist_data else None, distributors=distributors, distributors_country_code=distributors_country_code, ) async def get_playlist_tracklist_v_3_1_v_3_2( playlist_id: str, search: List[str], source_track_isrc: Optional[str], order_by: List[str], dsp: DSP, schema: Type[Schema], cache_key: str, image_size: int = 640, **kwargs, ) -> List[dict]: country_code = kwargs.get("country_code") if dsp == DSP.APPLE else None # it is required for apple only cache_value, cache_key = await get_value_by_key_template( cache_key_template=cache_key, kwargs=dict( playlist_id=playlist_id, search=None, source_track_isrc=None, order_by=[PlaylistTracklistOrder.CURR_POSITION], **({"country_code": country_code} if country_code else {}), image_size=image_size, ), str_to_date=False, ) if cache_value: items = cache_value else: items = await get_playlist_tracklist( dsp=dsp, playlist_id=playlist_id, include_list=[TrackPositionsPlaylists.INCLUDE.TRACK_INFO], country_code_list=country_code and [country_code], include_playlist=True, ) items = schema(many=True, context={"image_size": image_size, "utc_now": datetime.utcnow().date()}).dump(items) if search: items = filter_playlist_tracklist(items, search, source_track_isrc) items = multikeysort(items, order_by) return items