from abc import abstractmethod from datetime import date from typing import Dict, Type from marshmallow import Schema, fields from apollo_notifications.constants import SPOTIFY_PLAYLIST_IMAGE_URL_MASK from apollo_notifications.playlists.utils import (build_playlist_update_push_message, build_track_in_playlist_push_message, get_playlist_update_push_key, get_track_in_playlist_push_key) from apollo_notifications.serializers import PushBaseSchema, PushDataBaseSchema from apollo_notifications.utils import dump_datetime, get_country_code, get_country_flag class SpotifyPlaylistImageMixin: """Mixin to provide spotify playlist image url based on playlist_id.""" playlist_image_url = fields.Method("get_playlist_image_url") def get_playlist_image_url(self, item): return SPOTIFY_PLAYLIST_IMAGE_URL_MASK.format(playlist_id=item.playlist_id) class ApplePlaylistImageMixin: """Mixin to provide apple playlist image url based on playlist_id.""" playlist_image_url = fields.Str(attribute="playlist_image_url") # track in playlist class PushDataTrackInPlaylistSchema(PushDataBaseSchema): """Base schema for track ih playlists push message data.""" isrc = fields.Str(attribute="isrc") country_code = fields.Method("get_country_code") artist_name = fields.Str(attribute="artist_name") position = fields.Int(attribute="position") target = fields.Method("get_target") topic = fields.Method("get_topic") vendor = fields.Method("get_vendor") track_id = fields.Str(attribute="track_id") track_name = fields.Str(attribute="track_name") playlist_id = fields.Str(attribute="playlist_id") playlist_name = fields.Str(attribute="playlist_name") date = fields.Method("get_date") def get_target(self, track): return track.playlist_name def get_topic(self, track): return self.context["topic"] def get_vendor(self, track): return self.context["vendor"] def get_country_code(self, track): return self.context["country_code"] def get_date(self, track): return self.context["date"] class PushPlaylistBaseSchema(PushBaseSchema): """Base schema for playlists push message.""" _data_schema_cls: Type[Schema] title = fields.Method("get_title") tokens = fields.Method("get_tokens") user_id = fields.Str(attribute="user_id") account_id = fields.Function( lambda item, context: context["users_map"].get(item["user_id"]) if context.get("users_map") else None ) message = fields.Method("get_message") def __init__( self, title: str, topic: str, vendor: str, message_template: str, date: date, market: str, *args, push_cls=None, push_data_cls=None, users_map: Dict[str, int] = None, **kwargs ): super().__init__(*args, push_cls=push_cls, push_data_cls=push_data_cls, **kwargs) self.context = self.get_base_context(title, topic, vendor, message_template, date, market, users_map) @abstractmethod def _get_message_key(self, item) -> str: pass @abstractmethod def get_message(self, item) -> str: pass def get_title(self, item): return self.context["title"] def get_tokens(self, item): return item.device_tokens.split(',') @staticmethod def get_base_context(title, topic, vendor, message_template, date, market, users_map): country_code = get_country_code(market) return dict( title=title, topic=topic, vendor=vendor, template=message_template, market=market, date=date, country_code=country_code, country_flag=get_country_flag(country_code), users_map=users_map, ) class PushTrackInPlaylistSchema(PushPlaylistBaseSchema): """Base schema for track in playlists push message.""" _data_schema_cls = PushDataTrackInPlaylistSchema def _get_message_key(self, track) -> str: ctx = self.context return str(get_track_in_playlist_push_key( ctx["date"], track.playlist_id, track.user_id, ctx["topic"], ctx["market"], ctx["vendor"], track.isrc)) def get_message(self, track): return build_track_in_playlist_push_message(track, self.context["template"], self.context["country_flag"]) class StarredSpotifyPlaylistEntryPushDataSchema(SpotifyPlaylistImageMixin, PushDataTrackInPlaylistSchema): """Schema to create push data for starred track to starred playlist entry event.""" pass class StarredSpotifyPlaylistEntryPushSchema(PushTrackInPlaylistSchema): """Schema to create push for starred track to starred playlist entry event.""" _data_schema_cls = StarredSpotifyPlaylistEntryPushDataSchema class StarredApplePlaylistEntryPushDataSchema(ApplePlaylistImageMixin, PushDataTrackInPlaylistSchema): """Schema to create push data for starred track to starred playlist entry event.""" pass class StarredApplePlaylistEntryPushSchema(PushTrackInPlaylistSchema): """Schema to create push for starred track to starred playlist entry event.""" _data_schema_cls = StarredApplePlaylistEntryPushDataSchema # playlist update class PlaylistUpdatePushDataSchema(PushDataBaseSchema): """Base schema for playlist push message data.""" country_code = fields.Method("get_country_code") target = fields.Method("get_target") topic = fields.Method("get_topic") vendor = fields.Method("get_vendor") playlist_id = fields.Str(attribute="playlist_id") playlist_name = fields.Str(attribute="playlist_name") date = fields.Method("get_date") def get_date(self, item): return dump_datetime(item.date) def get_target(self, item): return item.playlist_name def get_topic(self, item): return self.context["topic"] def get_vendor(self, item): return self.context["vendor"] def get_country_code(self, item): return self.context["country_code"] class PlaylistUpdatePushSchema(PushPlaylistBaseSchema): """Basic schema to create push for playlist update event.""" _data_schema_cls: Type[Schema] def _get_message_key(self, item) -> str: ctx = self.context return str(get_playlist_update_push_key( dump_datetime(item.date), item.playlist_id, item.user_id, ctx["topic"], ctx["market"], ctx["vendor"])) def get_message(self, item): return build_playlist_update_push_message(item, self.context["template"], self.context["country_flag"]) class SpotifyPlaylistUpdatePushDataSchema(SpotifyPlaylistImageMixin, PlaylistUpdatePushDataSchema): """Schema to create push data for starred playlist update event.""" pass class SpotifyPlaylistUpdatePushSchema(PlaylistUpdatePushSchema): """Schema to create push for starred playlist update event.""" _data_schema_cls = SpotifyPlaylistUpdatePushDataSchema class ApplePlaylistUpdatePushDataSchema(ApplePlaylistImageMixin, PlaylistUpdatePushDataSchema): """Schema to create push data for starred playlist update event.""" pass class ApplePlaylistUpdatePushSchema(PlaylistUpdatePushSchema): """Schema to create push for starred playlist update event.""" _data_schema_cls = ApplePlaylistUpdatePushDataSchema