import typing from marshmallow import EXCLUDE, fields from apollo_messages_views.constants.base import EventType from apollo_messages_views.constants.push_messages import MESSAGE_TYPE_TO_TOPIC from apollo_messages_views.schemas.base import BaseMessage, MetaExcludeUnknown, MetaItem from apollo_messages_views.schemas.fields import save_ctx from apollo_messages_views.utils.misc import get_artists_str from apollo_messages_views.utils.playlists import get_playlist_entry_body, get_playlist_update_body, \ get_playlist_exit_body, get_playlist_major_move_body from apollo_messages_views.utils.charts import get_chart_update_body class PushMessageOutputData(MetaExcludeUnknown): artist_name = fields.Function(lambda o: get_artists_str(o.get("track", {}).get("artists", []))) isrc = fields.Str(attribute="track.isrc") track_id = fields.Str(attribute="track.id") track_name = fields.Str(attribute="track.name") topic = fields.Function(lambda o, ctx: MESSAGE_TYPE_TO_TOPIC[ctx["meta"]["type"]]) position = fields.Function(lambda o: o.get("current_position") or o.get("previous_position")) vendor = fields.Function(lambda o, ctx: ctx["meta"]["dsp"]) country_code = fields.Function(lambda o, ctx: ctx["meta"]["country_code"]) chart_name = fields.Str(attribute="chart.name") target = fields.Method("get_target") playlist_name = fields.Str(attribute="playlist.name") playlist_id = fields.Str(attribute="playlist.id") playlist_image_url = fields.Str(attribute="playlist.image_url") change = fields.Method("get_change") def get_change(self, obj): if self.context["meta"]["type"] == EventType.TOP_CHART_MOVE.value: return obj["current_position"] - obj["previous_position"] def get_target(self, obj): return obj.get("playlist", {}).get("name") class PushMessageOutput(BaseMessage): class Meta: unknown = EXCLUDE ordered = True meta = save_ctx(fields.Nested, MetaItem, required=True) title = fields.Str(attribute="data.content.title") body = fields.Str(attribute="data.content.body") data = fields.Nested(PushMessageOutputData, attribute="data.content") def dump_by_devices(self, obj: typing.Any) -> typing.List[typing.Dict[str, typing.Any]]: result = self.dump(obj) recipient = obj["data"].pop("recipient") return [{"to": d["expo_token"], "device_id": d.get("id"), **result} for d in recipient["devices"]] class PlaylistTopEntryPushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_entry_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=False, ) class PlaylistStarredEntryPushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_entry_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=True, ) class PlaylistUpdatePushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_update_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", ) class PlaylistTopExitPushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_exit_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=False, ) class PlaylistStarredExitPushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_exit_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=True, ) class PlaylistTopMajorMovePushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_major_move_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=False, ) class PlaylistStarredMajorMovePushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_playlist_major_move_body( dsp=data["meta"]["dsp"], country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", is_starred=True, ) class ChartUpdatePushMessageOutput(PushMessageOutput): body = fields.Method("get_body") def get_body(self, data) -> str: return get_chart_update_body( country_code=data["meta"]["country_code"], content=data["data"]["content"], unknown_flag_as="", )