"""Neo4j queries for global participants.""" from typing import Any from ddtrace import tracer from neo4j import Session from contributor.queries.neo4j import contributors as contributor_queries get_global_participant_by_id = """ MATCH (gp:GlobalParticipant {id: $id}) WHERE gp.name <> "Various Artists" AND NOT (gp)-[:MERGED_TO]->(:GlobalParticipant) AND ($is_admin OR EXISTS { MATCH (gp)-[:REPRESENTS]->(lp:LabelParticipant) <-[:HAS_LABEL_PARTICIPANT]-()<-[:HAS_ACCESS_TO|HAS_ADMIN_ACCESS_TO] -(p:Profile {profileType: 'LabelProfile'}) WHERE p.profileId IN $profile_ids }) OPTIONAL MATCH (gp)-[:REPRESENTS]->(:Participant:Chartmetric) -[:HAS_AGGREGATED_PARTICIPANT_SOCIAL_STAT]->(stat:AggregatedParticipantSocialStat) WITH gp, max(toInteger(stat.monthlyListeners)) AS monthlyListeners RETURN gp, monthlyListeners """ get_global_participants_by_ids = """ UNWIND $ids AS id MATCH (gp:GlobalParticipant {id: id}) WHERE gp.name <> "Various Artists" AND NOT (gp)-[:MERGED_TO]->(:GlobalParticipant) AND ($is_admin OR EXISTS { MATCH (gp)-[:REPRESENTS]->(lp:LabelParticipant) <-[:HAS_LABEL_PARTICIPANT]-()<-[:HAS_ACCESS_TO|HAS_ADMIN_ACCESS_TO] -(p:Profile {profileType: 'LabelProfile'}) WHERE p.profileId IN $profile_ids }) WITH DISTINCT gp OPTIONAL MATCH (gp)-[:REPRESENTS]->(:Participant:Chartmetric) -[:HAS_AGGREGATED_PARTICIPANT_SOCIAL_STAT]->(stat:AggregatedParticipantSocialStat) WITH gp, max(toInteger(stat.monthlyListeners)) AS monthlyListeners RETURN gp, monthlyListeners """ contributors_by_global_participant_id = """ MATCH (gp:GlobalParticipant {id: $global_participant_id}) WHERE gp.name <> "Various Artists" AND NOT (gp)-[:MERGED_TO]->(:GlobalParticipant) OPTIONAL MATCH (gp)-[:REPRESENTS]->(lp:LabelParticipant) WHERE lp IS NULL OR $is_admin OR EXISTS { MATCH (p:Profile {profileType: 'LabelProfile'}) -[:HAS_ACCESS_TO|HAS_ADMIN_ACCESS_TO]->() -[:HAS_LABEL_PARTICIPANT]->(lp) WHERE p.profileId IN $profile_ids } WITH gp, lp OPTIONAL MATCH (lp)<-[:HAS_LABEL_PARTICIPANT]-(vendor:Vendor) OPTIONAL MATCH (lp)<-[:HAS_LABEL_PARTICIPANT]-(subaccount:Subaccount) WITH gp, lp, CASE WHEN subaccount IS NOT NULL THEN subaccount ELSE vendor END AS label OPTIONAL MATCH (gp)-[:REPRESENTS]->(:Participant:Chartmetric) -[:HAS_AGGREGATED_PARTICIPANT_SOCIAL_STAT]->(stat:AggregatedParticipantSocialStat) WITH gp, lp, label, max(toInteger(stat.monthlyListeners)) AS gp_monthly_listeners ORDER BY lp.uuid RETURN gp.id AS global_participant_id, collect(CASE WHEN lp IS NOT NULL THEN {lp: lp, label: label, gp: gp, gp_monthly_listeners: gp_monthly_listeners} END) AS contributors """ def _str_or_none(value) -> str | None: return str(value) if value is not None else None def _gp_node_to_dict(gp, monthly_listeners: int | None = None) -> dict[str, Any] | None: if gp is None: return None return { "id": gp["id"], "name": gp.get("name"), "spotify_id": _str_or_none(gp.get("spotifyId")), "apple_music_id": _str_or_none(gp.get("appleMusicId")), "chartmetric_id": _str_or_none(gp.get("chartmetricId")), "image_url": gp.get("imageUrl"), "monthly_listeners": ( int(monthly_listeners) if monthly_listeners is not None else None ), } @tracer.wrap() def get_by_id( session: Session, id: str, profile_ids: list[int], is_admin: bool = False, ) -> dict[str, Any] | None: result = session.run( get_global_participant_by_id, id=id, profile_ids=profile_ids, is_admin=is_admin ) record = result.single() if record is None: return None try: monthly_listeners = record["monthlyListeners"] except KeyError, TypeError: monthly_listeners = None return _gp_node_to_dict( record["gp"], monthly_listeners=monthly_listeners, ) @tracer.wrap() def get_by_ids( session: Session, ids: list[str], profile_ids: list[int], is_admin: bool = False, ) -> list[dict[str, Any]]: result = session.run( get_global_participants_by_ids, ids=ids, profile_ids=profile_ids, is_admin=is_admin, ) global_participants = [] for record in result: try: monthly_listeners = record["monthlyListeners"] except KeyError, TypeError: monthly_listeners = None global_participants.append( _gp_node_to_dict(record["gp"], monthly_listeners=monthly_listeners) ) return global_participants @tracer.wrap() def get_contributors( session: Session, global_participant_id: str, profile_ids: list[int], is_admin: bool = False, ) -> list[dict[str, Any]] | None: result = session.run( query=contributors_by_global_participant_id, global_participant_id=global_participant_id, profile_ids=profile_ids, is_admin=is_admin, ) record = result.single() if record is None: return None return [ contributor_queries._node_to_dict( c["lp"], label=c.get("label"), gp=c.get("gp"), gp_monthly_listeners=c.get("gp_monthly_listeners"), ) for c in record["contributors"] if c is not None and c.get("lp") is not None ]