"""Sound Recording metadata logic.""" import copy from datetime import datetime from typing import Any, Mapping from ddtrace import tracer from oto import response as oto_response from analytics.connectors import dynamo from analytics.constants import cache from analytics.schemas.sound_recording_metadata import SoundRecordingMetadataSchema from analytics.utils.cache import cache_in_redis PRODUCT = "product" TRACK_NUMBER = "track_number" TRACK_CD = "track_cd" IS_DELETED = "is_deleted" def _to_dynamo_permissions_filter(permissions: Mapping[str, Any]) -> dict: return { "artist_ids": permissions.get("permission_artist_ids"), "subaccount_ids": permissions.get("permission_subaccount_ids"), "label_ids": permissions.get("permission_label_ids"), } def _add_fallback_artists_list(track, products): """Use the release-artist list when the track has no artists.""" track_copy = copy.deepcopy(track) if not track.get("artists"): if products: release_artist = products[0].get("release_artist", "") else: release_artist = "" track_copy["artists"] = [{"artist_name": release_artist, "type": "performer"}] return track_copy def _patch_track(track): """Unpack nested objects from a Dynamo track record.""" track_copy = copy.deepcopy(track) try: track_copy["product"]["release_date"] = datetime.strptime( track_copy["product"]["release_date"], "%Y-%m-%d" ).date() track_copy["product"]["sales_start_date"] = datetime.strptime( track_copy["product"]["sales_start_date"], "%Y-%m-%d" ).date() except KeyError: track_copy["product"]["release_date"] = datetime.strptime( "1901-01-01", "%Y-%m-%d" ).date() track_copy["product"]["sales_start_date"] = datetime.strptime( "1901-01-01", "%Y-%m-%d" ).date() track_copy["product"]["artists"] = [ {"artist_name": track_copy["product"]["release_artist"], "type": "performer"} ] track_copy["artist_name"] = track_copy["product"]["release_artist"] return track_copy def _patch_sound_recording(sound_recording): return _add_fallback_artists_list(sound_recording, sound_recording["products"]) def _is_not_deleted(item): return not ( item.get(IS_DELETED, False) or item.get(PRODUCT, {}).get(IS_DELETED, False) ) @tracer.wrap(name="get_sound_recording_metadata") @cache_in_redis(ttl=cache.ONE_HOUR) def get_sound_recording_metadata( query_params: Mapping[str, Any], permissions: Mapping[str, Any] ): """Return metadata for the given ISRC.""" isrc = query_params["isrc"] include_deleted = query_params.get("include_deleted", False) permissions_filter = _to_dynamo_permissions_filter(permissions) tracks = sorted( list( map( _patch_track, dynamo.query_by_range_key( dynamo.create_track_key(isrc), permissions_filter=permissions_filter, ), ) ), key=lambda track: (_is_not_deleted(track), track["product"]["release_date"]), reverse=True, ) sound_recording = next(iter(tracks), None) if not sound_recording: return oto_response.Response(status=404) sound_recording["products"] = list( map( lambda track: track[PRODUCT], tracks if include_deleted else filter(_is_not_deleted, tracks), ) ) return oto_response.Response( SoundRecordingMetadataSchema.normalize( _patch_sound_recording(sound_recording), permissions_filter ) )