"""DDEX Tracks extended metadata generation.""" from typing import Dict import jmespath from constants.artist_role_mappings import DDEX_ARTIST_TYPE_ORCHARD_TO_SME from constants.country_code_mapping import COUNTRY_ID_MAP from constants.ownership_mappings import OWNERSHIP_TYPE_MAPPING from constants.ownership_mappings import ( US_PUBLISHING_OBLIGATION_MAPPING as US_PUB_MAPPING, ) from .e import E def generate_tracks(source_data: Dict): """Generate a Tracks extended metadata node.""" tracks = [] # Video products get Publisher from another source than 'tracks'. video_product = {} video_product = source_data.get('videoProduct', {}) for track in jmespath.search('tracks', source_data) or []: tracks.append(generate_track_element(track, video_product)) return E('Tracks', *tracks) def generate_track_element(track: Dict, video_product: Dict): """Generate a Track extended metadata node.""" return E( 'Track', E('ISRC', jmespath.search('isrc', track)), E('Lyrics', jmespath.search('lyrics', track)), E( 'OwnershipRights', OWNERSHIP_TYPE_MAPPING.get(jmespath.search('ownershipRights', track)), ), E( 'RecordingCountry', COUNTRY_ID_MAP.get(jmespath.search('recordingCountryId', track)), ), E( 'CopyrightOwnerCountry', COUNTRY_ID_MAP.get(jmespath.search('originalRightsHolderCountryId', track)), ), *build_publishing_obligation(track, video_product), *build_related_track_info(track, video_product), *add_publisher_names(track, video_product), ) def add_publisher_names(track: Dict, video_product: Dict): """Create a list of publisher names for given track.""" publishers = jmespath.search('publishing.publisherNames', track) or [] if not publishers and video_product: # check we have an associated track before proceeding if video_product.get('associatedTrack'): publishers = jmespath.search( 'associatedTrack.publishing.publisherNames', video_product ) publisher_nodes = [] if publishers: for pub in publishers: publisher_nodes.append(E('Publisher', E('PublisherName', pub))) return publisher_nodes def build_publishing_obligation(track: Dict, video_product: Dict): """Create USPublishingObligation node.""" obligation = jmespath.search('publishing.usPublishingObligation', track) # Check for video if obligation is not found if not obligation: obligation = jmespath.search( 'associatedTrack.publishing.usPublishingObligation', video_product ) return E('USPublishingObligation', US_PUB_MAPPING.get(obligation)) def build_related_track_info(track: Dict, video_product: Dict): """Create related track information.""" # If we are not a video product, we can skip this # We must have an associated track to proceed. associated_track = {} if video_product: associated_track = video_product.get('associatedTrack', {}) if not associated_track: return [] track_info = E( 'RelatedAudioTrackInformation', E('ISRC', associated_track.get('isrc')), *build_artist_info(associated_track), ) return track_info def build_artist_info(associated_track: Dict): """Use associated track to define artist values.""" participations = associated_track.get('participations', []) artist_nodes = [] for participant in participations: name = participant.get('participant').get('name') ddex_role = DDEX_ARTIST_TYPE_ORCHARD_TO_SME.get( participant.get('participatedAs') ) artist_nodes.append( E( 'Artist', E('Name', name), *match_store_ids(participant.get('participant')), E('ArtistRole', ddex_role), ) ) return artist_nodes def match_store_ids(participant: Dict): """Find spotify and itunes ids for given participant.""" artist_ids = [] spotify_id = participant.get('participant', {}).get('spotifyId') apple_id = participant.get('participant', {}).get('appleMusicId') if spotify_id: artist_ids.append( E( 'ArtistId', 'spotify:artist:' + spotify_id if spotify_id else None, {'Namespace': 'spotify'}, ) ) if apple_id: artist_ids.append(E('ArtistId', apple_id, {'Namespace': 'itunes'})) return artist_ids