from flask import jsonify from flask_apispec import MethodResource, doc, marshal_with, use_kwargs from http import HTTPStatus from src.constants.core import CURRENT_PLACEMENT_TYPE, PAST_PLACEMENT_TYPE from src.constants.include import TrackPlaylistHistoryInclude, TrackPlaylistInclude from src.legacy.apple_music import serializers as apple_serializers from src.legacy.apple_music.vendor import AppleMusicPlaylists from src.legacy.core.pagination import paginate from src.legacy.core.util import multikeysort from src.legacy.redis_db import keys @doc("Endpoint to get Apple track added dates to playlists.") class TrackPlaylistsAddedDatesView(MethodResource): @use_kwargs(apple_serializers.TrackPlaylistsAddedDateViewParams, location="query") @marshal_with( apple_serializers.TrackPlaylistsAddedDateOutputSchema(many=True), description="Playlists added dates.", code=200 ) @marshal_with(None, code=401, description="Authentication failed") def get(self, **data): return AppleMusicPlaylists().get_track_playlists_added_date( data["playlist_ids"], data["song_id"], data["market"] ) @doc("Returns list of tracks in Apple Music playlist.") class PlaylistTrackListViewV1(MethodResource): @use_kwargs(apple_serializers.PlaylistTracklistV1ViewParams, location="query") @marshal_with( apple_serializers.TrackPlaylistsOutputSchema, code=200, description="Paginated Apple Music playlist`s list of tracks.", apply=False, ) @marshal_with(None, code=401, description="Authentication failed.") @paginate(cache_key_template=keys.APPLE_PLAYLIST_TRACKLIST, full_data=True) def get(self, **data): playlist_id, market = data["playlist_id"], data["market"] image_size, order_by = data["image_size"], data["order_by"] playlist_vendor = AppleMusicPlaylists() items = playlist_vendor.get_playlist_tracklist(playlist_id, market, image_size) items = playlist_vendor.search_across_tracks_in_playlist(items, data["search"], data["source_track_isrc"]) items = multikeysort(items, order_by) return items @doc("Returns list of tracks in Apple Music playlist for allocation graphs.") class PlaylistTrackListAllocationGraphView(MethodResource): @use_kwargs(apple_serializers.PlaylistTracklistAllocationGraphViewParams, location="query") @marshal_with( apple_serializers.PlaylistTracklistAllocationGraphViewSchema, code=200, description="Paginated Apple Music playlist`s tracklist data for allocated graphs.", ) @marshal_with(None, code=401, description="Authentication failed.") @paginate(cache_key_template=keys.APPLE_PLAYLIST_TRACKLIST_ALLOCATION_GRAPH, full_data=True) def get(self, **data): playlist_id, market = data["playlist_id"], data["market"] playlist_vendor = AppleMusicPlaylists() return playlist_vendor.get_playlist_tracklist_allocation_graph_query(playlist_id, market).all() @doc("Returns all data related to the selected track in selected playlist.") class TrackInPlaylistViewV1(MethodResource): @use_kwargs(apple_serializers.TrackInPlaylistV1ViewParams, location="query") @marshal_with( apple_serializers.TrackInPlaylistV1OutputSchema, code=200, description="Track data in Apple Music playlist.", apply=False, ) @marshal_with(None, code=401, description="Authentication failed.") def get(self, **data): isrc, market = data["isrc"], data["market"] playlist_id, image_size = data["playlist_id"], data["image_size"] playlist_type = data["playlist_type"] playlist_vendor = AppleMusicPlaylists() if playlist_type == CURRENT_PLACEMENT_TYPE: track_data, context = playlist_vendor.get_track_in_playlist_data(isrc, playlist_id, market, image_size) elif playlist_type == PAST_PLACEMENT_TYPE: track_data, context = playlist_vendor.get_track_in_past_playlist_data(isrc, playlist_id, market, image_size) schema = apple_serializers.TrackInPlaylistV1OutputSchema() schema.context = context return jsonify(schema.dump(track_data)) @doc("Returns Apple Music track's playlists list.") class TrackPlaylistsViewV1(MethodResource): @use_kwargs(apple_serializers.TrackPlaylistsV1ViewParams, location="query") @marshal_with(None, code=401, description="Authentication failed.") @marshal_with( apple_serializers.TrackPlaylistsV1OutputSchema, code=200, description="Track data in Apple Music playlist.", apply=False, ) @paginate(cache_key_template=keys.APPLE_TRACK_PLAYLISTS_V1, full_data=True) def get(self, **data): isrc, markets_list = data["isrc"], data["markets_list"] vendor = AppleMusicPlaylists() track_playlists_data = vendor.get_track_playlists_data( isrc_list=[isrc], markets_list=markets_list, image_size=data["image_size"], search=data["search"], playlists_ids=None, include_username=False, include_playlist_count=False, include_streams_7_days=False, include_isrc=True, include_owner=False, category_id=None, ) items, playlist_ids = vendor.flatten_playlists_data(track_playlists_data) items = vendor.show_recent_adds(items, data["recent_adds_only"]) items = multikeysort(items, data["order_by"]) return items @doc("Returns Apple Music track's previous playlists list.") class TrackPreviousPlaylistsViewV1(MethodResource): @use_kwargs(apple_serializers.TrackPreviousPlaylistsV1ViewParams, location="query") @marshal_with(None, code=401, description="Authentication failed.") @marshal_with( apple_serializers.TrackPreviousPlaylistsV1OutputSchema, code=200, description="Track data in Apple Music playlist.", apply=False, ) @paginate(cache_key_template=keys.APPLE_TRACK_PREVIOUS_PLAYLISTS_V1, full_data=True, response_kwargs=True) def get(self, **data): include = data["include"] vendor = AppleMusicPlaylists() track_previous_playlists_data = vendor.get_track_previous_playlists_data( data["isrc_list"], markets_list=data["markets_list"], search=data["search"], exclude_current_playlists=data["exclude_current_playlists"], image_size=data["image_size"], include_owner=( TrackPlaylistHistoryInclude.OWNER.value in include or TrackPlaylistHistoryInclude.CATEGORIES.value in include ), category_id=data["category_id"], ) playlists_without_country = [ i["id"] for j in track_previous_playlists_data for i in j["data"] if i["country_code"] is None ] if playlists_without_country: owner_markets = vendor.get_apple_owner_market_data(playlists_without_country, data["markets_list"]) track_previous_playlists_data = vendor.fill_missing_countries( track_previous_playlists_data, owner_markets, data["markets_list"] ) if TrackPlaylistHistoryInclude.CATEGORIES.value in include: categories = dict(categories=vendor.get_playlists_categories(track_previous_playlists_data)) else: categories = dict(categories=[]) items, playlist_ids = vendor.flatten_playlists_data(track_previous_playlists_data) if data["exclude_current_playlists"]: items = vendor.show_recent_removals(items, data["recent_removals_only"]) items = multikeysort(items, data["order_by"]) return items, categories @doc("Returns playlists' markets data.") class PlaylistsMarketsViewV1(MethodResource): @use_kwargs(apple_serializers.PlaylistsMarketsInputSchema, location="query") @marshal_with(None, code=401, description="Authentication failed.") @marshal_with( apple_serializers.PlaylistsMarketsOutputSchema, code=200, description="Playlists markets data.", apply=False ) def get(self, **data): items = AppleMusicPlaylists().get_playlists_markets(data["playlist_ids"], data["include"]) return {"items": items} @doc("Returns playlists' data in selected market.") class PlaylistsDataViewV1(MethodResource): @use_kwargs(apple_serializers.PlaylistsMarketDataInputSchema, location="query") @marshal_with(None, code=401, description="Authentication failed.") @marshal_with( apple_serializers.PlaylistMarketDataOutputSchema, code=200, description="Playlists data in selected market.", apply=False, ) def get(self, **data): items = AppleMusicPlaylists().get_playlists_data(data["playlist_ids"], data["market"]) return {"items": items} @doc("Returns playlists data for ID and country_code pairs list.") class PlaylistsBulkViewV1(MethodResource): @use_kwargs(apple_serializers.PlaylistsBulkInputSchema(), location="json") @marshal_with(None, code=HTTPStatus.UNAUTHORIZED, description="Authentication failed.") @marshal_with( apple_serializers.PlaylistMarketDataOutputSchema, code=HTTPStatus.OK, description="Playlists info.", apply=False, ) def post(self, items): result = AppleMusicPlaylists().get_playlists_markets_data(items) return {"items": result} @doc("Returns a list of track's Apple Music playlists.") class TrackPlaylistsViewV2(MethodResource): @use_kwargs(apple_serializers.TrackPlaylistsV2ViewParams, location="query") @marshal_with(None, code=HTTPStatus.UNAUTHORIZED, description="Authentication failed.") @marshal_with( apple_serializers.TrackPlaylistsV2OutputSchema, code=HTTPStatus.OK, description="List of track's Apple Music playlist.", apply=False, ) @paginate(cache_key_template=keys.APPLE_TRACK_PLAYLISTS_V2, full_data=True, response_kwargs=True) def get(self, **data): isrc_list = data["isrc_list"] include = data["include"] vendor = AppleMusicPlaylists() track_playlists_data = vendor.get_track_playlists_data( isrc_list=isrc_list, markets_list=data["markets_list"], image_size=data["image_size"], search=data["search"], playlists_ids=None, include_playlist_count=(TrackPlaylistInclude.TRACK_COUNT.value in include), include_username=(TrackPlaylistInclude.USERNAME.value in include), include_streams_7_days=(TrackPlaylistInclude.PLAYLIST_STREAMS.value in include), include_isrc=False, include_owner=( TrackPlaylistInclude.OWNER.value in include or TrackPlaylistInclude.CATEGORIES.value in include ), category_id=data["category_id"], ) playlists_without_country = [ i["id"] for j in track_playlists_data for i in j["data"] if i["country_code"] is None ] if playlists_without_country: owner_markets = vendor.get_apple_owner_market_data(playlists_without_country, data["markets_list"]) track_playlists_data = vendor.fill_missing_countries( track_playlists_data, owner_markets, data["markets_list"] ) if TrackPlaylistInclude.CATEGORIES.value in include: categories = dict(categories=vendor.get_playlists_categories(track_playlists_data)) else: categories = dict(categories=[]) items, playlist_ids = vendor.flatten_playlists_data(track_playlists_data) items = vendor.show_recent_adds(items, data["recent_adds_only"]) items = multikeysort(items, data["order_by"]) return items, categories