import asyncio from apollo_utils.core.constants.dsp import DSP from apollo_utils.service.utils.amazon import AmazonId from http import HTTPStatus from typing import Any, Dict, Iterable from server.client import services from server.schemas.favorites.playlists import V1FavoritesPlaylistsDetailed from server.utils.mappers.playlists.misc import get_country_playlist_id, map_country_playlist_id from server.utils.playlists.amazon.playlist_id import set_amazon_is_personalised_false, set_amazon_playlist_full_id from server.utils.processor import processor from server.utils.processor.core import apply_by_item from server.utils.processor.playlists.playlists import playlist_basic_processors, set_favorites_data def _update_spotify_potentially_removed_playlists(playlists: Iterable[Dict[str, Any]], original_status: HTTPStatus): """Check spotify playlists and if original_status occur assign needed fields from original response that will be processed to make sure we return playlist_id to be able to unstarr such a playlist Args: playlists: Iterable of spotify playlist Dict(s) original_status: status to handle """ for i in playlists: if "code" in i.keys() and i["original"]["status_code"] == original_status: pl_id = i["original"]["response"]["path"].replace("/v3/public/playlists/current/", "") i.update({"dsp_playlist_id": pl_id, "dsp": {"dsp_id": DSP.SPOTIFY.value}}) async def get_meta_playlists_info(headers: Dict, params: Dict) -> Dict[str, Any]: result = await services.user_data.get_v1_favorites_playlists( headers=V1FavoritesPlaylistsDetailed.Headers().dump(headers), **params ) result_items = result["items"] if not result_items: return result apple_tasks, spotify_tasks, amazon_tasks = [], [], [] country_playlist_id_to_favorites_data = {} for item in result_items: _id, dsp = item["id"], item["vendor"] country_playlist_id_to_favorites_data[ get_country_playlist_id(dsp=dsp, playlist_id=_id, country_code=item.get("country_code")) ] = item if dsp == DSP.APPLE.value: apple_tasks.append( services.dsp.get_public_playlists_info( playlist_id=f"{DSP.APPLE.value}_{_id}", apple_country_code=item["country_code"] ) ) elif dsp == DSP.SPOTIFY.value: spotify_tasks.append( services.dsp.get_public_current_playlists_info( playlist_id=f"{DSP.SPOTIFY.value}_{_id}", allowed_status_codes=(HTTPStatus.NOT_FOUND,) ) ) elif dsp == DSP.AMAZON.value: amazon_id = AmazonId.parse_from(_id) amazon_tasks.append( services.dsp.get_public_playlists_info(playlist_id=f"{DSP.AMAZON.value}_{amazon_id.int_market_id}") ) apple_list_length = len(apple_tasks) spotify_last_task_index = len(spotify_tasks) + apple_list_length meta_list = await asyncio.gather(*(apple_tasks + spotify_tasks + amazon_tasks)) apple_list, spotify_list, amazon_list = ( meta_list[:apple_list_length], meta_list[apple_list_length:spotify_last_task_index], meta_list[spotify_last_task_index:], ) _update_spotify_potentially_removed_playlists(spotify_list, HTTPStatus.NOT_FOUND) items_per_dsp = {DSP.APPLE: apple_list, DSP.SPOTIFY: spotify_list, DSP.AMAZON: amazon_list} iterators_per_dsp = {} for dsp, dsp_items in items_per_dsp.items(): processors = playlist_basic_processors(dsp=dsp) if dsp == DSP.AMAZON: processors.extend( [set_amazon_playlist_full_id, set_amazon_is_personalised_false] ) # set full_id instead group_id for amazon playlists processors.append( map_country_playlist_id) # extra id to set favorites data by, need it because apple playlists are market-related apply_by_item( dsp_items, processors=processors, processors_by_id=[processor(set_favorites_data, data=country_playlist_id_to_favorites_data)], id_getter=lambda i: i.get("country_playlist_id"), ) iterators_per_dsp[dsp.value] = iter(dsp_items) # restore order by user_date data result["items"] = [next(iterators_per_dsp[item["vendor"]]) for item in result_items] return result