from collections import defaultdict from typing import Iterable, List from sqlalchemy import or_ from apollo_main_db.sony import SonyUPCRegion from core.clients import clients from core.constants import VENDOR_SPOTIFY, IdType, MusicServices, ReleaseTypes, VendorType from main_db.base import session from redis_db import keys from redis_db.decorators import cache_requests def albums_is_sony(upc_list: Iterable[str], market: str) -> List[str]: """Check albums is Sony or not by UPC. Args: upc_list: List of album UPC. market: Market code. Returns: List of Sony UPC. """ query = ( session.query(SonyUPCRegion.upc) .filter(SonyUPCRegion.upc.in_(upc_list)) .filter(SonyUPCRegion.release_type_id == ReleaseTypes.SONY) .filter(SonyUPCRegion.music_service_id == MusicServices.SPOTIFY) ) # If it is 2 letter country code then we should filter results using it. # Otherwise it is generic markets like global or latin that does not exist in DB (or API), we should ignore that # and use any country DB row that met other conditions. if len(market) == 2: query = query.filter(or_(SonyUPCRegion.country.is_(None), SonyUPCRegion.country == market)) sony_upc_list_result = query.distinct().all() return [i[0] for i in sony_upc_list_result] @cache_requests(keys.SPOTIFY_TRACK_IS_SONY, keys.DSP_CACHE_TTL, ids_index=0, cache_key_parts=(1,)) def _check_spotify(spotify_ids: List[str], market: str) -> List[dict]: """Check Spotify tracks if Sony or not. Args: spotify_ids (List[str]): Spotify track ID list. market (str): Market code. Returns: List[dict]: Sony spotify track ID and is_sony dict list. """ # get tracks info from Spotify API to find albums spotify_tracks_info = clients.vendor.get_tracks(spotify_ids, VENDOR_SPOTIFY, market) spotify_album_mapping = defaultdict(list) for track in spotify_tracks_info: for album_id in track["album_ids"]: spotify_album_mapping[album_id].append(track["id"]) # get albums info from Spotify API to find UPC spotify_albums_info = clients.vendor.get_albums(list(spotify_album_mapping.keys()), VENDOR_SPOTIFY, market) upc_mapping = {a["upc"]: a["id"] for a in spotify_albums_info if "upc" in a and a["upc"]} # check UPC / region to get if these albums are Sony or not sony_upc_list = albums_is_sony(upc_mapping.keys(), market) sony_spotify_ids = [] for upc in sony_upc_list: sony_spotify_ids.extend(spotify_album_mapping[upc_mapping[upc]]) return [{"id": spotify_id, "is_sony": spotify_id in sony_spotify_ids} for spotify_id in spotify_ids] def check_is_sony(ids_list: List[str], id_type: IdType, vendor: VendorType, market: str or None = None) -> List: """Get if tracks are Sony or not. Args: ids_list (List[str] or None): Spotify track ID/Apple track ID/ISRC list to check. id_type (IdType): type of ids vendor (VendorType): type of vendor market (str or None): Market code. Returns: List: List of any track ID that is Sony. """ result = [] # check Spotify track IDs if ids_list and vendor == VendorType.SPOTIFY and id_type == IdType.ID: if not market: raise ValueError() spotify_track_sony = _check_spotify(ids_list, market) result.extend([t["id"] for t in spotify_track_sony if t["is_sony"]]) # TODO: implement this check for apple return result