import asyncio from apollo_utils.core.constants.dsp import DSP from apollo_utils.core.constants.market import Market from typing import Any, Dict, Iterable, List, Optional, Tuple, Union from server.client import services from server.constants import DSP_SPOTIFY_APPLE from server.constants.distributors import DISTRIBUTORS from server.domains.distributors import merge_response from server.scenarios.distributors.is_sony import IsSonyInclude, tracks_is_sony from server.utils.common import filter_by_prefixes, no_prefix_str, to_dict async def get_distributors( country_code: str or None, track_id: Optional[List[str]] = None, # _ upc: Optional[List[str]] = None, distributors: Optional[Iterable[DISTRIBUTORS]] = None, track_list: Optional[List[dict]] = None, album_list: Optional[List[dict]] = None, include: Optional[Iterable[str]] = None, # available options are IsSonyInclude ) -> Tuple[List[dict], Dict[str, Any]]: """Get distributors for track or album. One and only one of track_id or upc must be specified. Returns only track_id/upc that have relation with any distributor. @param country_code: Country code to get distributors for. @param track_id: List of track in format _, where is one of apple/spotify. @param upc: List of album UPCs. @param distributors: List of distributors to get data for. If None, all distributors will be used. @param track_list: List of vendor track objects to avoid extra call for is_sony check. @param album_list: List of vendor album objects to avoid extra call for is_sony check. @param include: Iterable of additional data to include in extra_data. Available options are IsSonyInclude. @return: Tuple of List of items { "upc": str, "track_id": Optional[str], _ "distributed_by: str (lowercase) } and extra_data dict. """ by_track = bool(track_id) if not (bool(upc) ^ by_track): raise ValueError("One and only one of track_id or upc must be specified.") distributors, include = set([d.value for d in (distributors or DISTRIBUTORS)]), set(include or []) apollo_country_code, delphi_country_code = [ Market.convert_global(country_code or Market.GLOBAL, cc) for cc in (Market.GLOBAL, Market.WORLDWIDE) ] tasks, sme, non_sme = [], False, False if DISTRIBUTORS.SME.value in distributors: sme = True if by_track: tasks.append( tracks_is_sony( track_id_list=filter_by_prefixes(values=track_id, prefixes=(DSP.SPOTIFY.value,), trim_prefix=True), country_code=apollo_country_code, track_list=track_list, album_list=album_list, include=include | {IsSonyInclude.TRACK_UPC_MAPPING}, ), ) else: tasks.append(services.apollo.get_albums_is_sony(upc=upc, market=apollo_country_code)) if distributors != {DISTRIBUTORS.SME.value}: # if not only SME non_sme = True tasks.append( services.dsp.get_tracks_brands_tagging(track_id=track_id, upc=upc, country_code=delphi_country_code) ) response = await asyncio.gather(*tasks) return merge_response( response, sme=sme, non_sme=non_sme, sme_by_track=by_track, distributors=distributors, include=include, requested_ids=track_id or upc, ) async def get_upc_distributors_map( country_code: str, upc: List[str], distributors: Optional[Iterable[DISTRIBUTORS]] = None, include: Optional[Iterable[str]] = None, # available options are IsSonyInclude ): result, extra_data = await get_distributors( country_code=country_code, upc=upc, distributors=distributors, include=include, ) result = to_dict( key_name="upc", values=result, value_name="distributed_by", ) return (result, extra_data) if include else result async def get_tracks_distributors_map( country_code: str, dsp_track_id: Optional[List[str]] = None, track_id: Optional[List[str]] = None, dsp: Optional[DSP_SPOTIFY_APPLE] = None, distributors: Optional[Iterable[DISTRIBUTORS]] = None, track_list: Optional[List[dict]] = None, include: Optional[Iterable[str]] = None, # available options are IsSonyInclude remove_result_dsp_prefix: bool = False, ) -> Union[Dict[str, Any], Tuple[Dict[str, Any], Dict[str, Any]]]: if not (bool(dsp_track_id) ^ bool(track_id)): raise ValueError("One and only one of track_id or dsp_track_id must be specified.") if track_id: if not dsp: raise ValueError( "Dsp must be specified for track_id," " or use 'dsp_track_id' in _ format instead." ) dsp_track_id = [f"{dsp.value}_{t}" for t in track_id] result, extra_data = await get_distributors( country_code=country_code, track_id=dsp_track_id, distributors=distributors, track_list=track_list, include=include, ) result = to_dict( key_name="track_id", values=result, value_name="distributed_by", key_name_func=(lambda x: no_prefix_str(x, delimiter="_")) if remove_result_dsp_prefix else None, ) return (result, extra_data) if include else result