from apollo_utils.service.legacy.schemas.mixins.market import MarketGlobalMixin from apollo_utils.service.schemas.fields.list import SplitUniqueListField from apollo_utils.service.schemas.mixins.date import DateRangeMixin from apollo_utils.service.schemas.mixins.isrc import IsrcListRequiredMixin, IsrcRequiredMixin from apollo_utils.service.schemas.mixins.misc import HandleAllMixin from apollo_utils.service.schemas.mixins.search import SearchNoneLowerMixin from apollo_utils.service.schemas.mixins.validate import ValidateCategoriesByWithIncludeMixin, \ ValidateOrderByWithIncludeMixin from marshmallow import Schema, fields, validate from src.constants.core import CURRENT_PLACEMENT_TYPE, PLACEMENT_TYPES, BuzzCategories from src.constants.include import NMFTrackInclude, TrackPlaylistHistoryInclude, TrackPlaylistInclude from src.constants.order import NMFTrackOrder, TrackPlaylistsOrder, TrackPlaylistsOrderSpotifyV2, \ TrackPlaylistsOrderV2, TrackPreviousPlaylistsOrder from src.legacy.core.serializers import BasePaginationOutputSchema, FullMarketCodeToGlobalMixin, \ MarketListOptionalMixin, PaginationMixin, QueryWebArgs, UniqueArgsListField, get_pagination_mixin from src.schemas.core import QueryParams class TracklistPlaylistOutputItemSchema(Schema): track_id = fields.String() current_position = fields.Integer() added_date = fields.Date() name = fields.String() isrc = fields.String() album_id = fields.String() class TracklistPlaylistOutputSchema(BasePaginationOutputSchema): items = fields.List(fields.Nested(TracklistPlaylistOutputItemSchema)) class TrackPlaylistsTrendsViewParams(QueryWebArgs, PaginationMixin): """Schema for input validation of TrackPlaylistsTrendsView.""" isrc = fields.String(validate=validate.Length(equal=12), required=True) playlist_ids = SplitUniqueListField(fields.String(), validate=validate.Length(min=1, max=50), required=True) class PersonalizedPlaylistsViewParams(QueryWebArgs): """Schema for input validation of PersonalizedPlaylistsView. Unset 'playlist_ids' to get all personalized playlists. """ playlist_ids = fields.List(fields.String(validate=validate.Length(min=1, max=22)), required=False) class TracksPlaylistsStatsParams(QueryParams, IsrcListRequiredMixin): """Query parameters schema for Spotify tracks/playlists-stats request.""" dates = SplitUniqueListField(fields.Date(), required=True, validate=validate.Length(min=1, max=5)) categories = SplitUniqueListField( fields.Integer(validate=validate.OneOf(BuzzCategories.ALL)), validate=validate.Length(min=1), load_default=(BuzzCategories.SONY, BuzzCategories.SPOTIFY), ) class TracksPlaylistsStatsCurrentOutputSchema(Schema): """Response schema current part for Spotify tracks/playlists-stats.""" category_id = fields.Integer(required=True, validate=validate.OneOf(BuzzCategories.ALL)) playlist_count = fields.Integer(required=True) class TracksPlaylistsStatsHistoryOutputSchema(Schema): """Response schema history part for Spotify tracks/playlists-stats.""" category_id = fields.Integer(required=True, validate=validate.OneOf(BuzzCategories.ALL)) added = fields.Integer(required=True) removed = fields.Integer(required=True) date = fields.Date(required=True) class TracksPlaylistsStatsOutputSchema(Schema, IsrcRequiredMixin): """Response Schema for Spotify tracks/playlists-stats.""" current = fields.List(fields.Nested(TracksPlaylistsStatsCurrentOutputSchema), required=True) history = fields.List(fields.Nested(TracksPlaylistsStatsHistoryOutputSchema), required=True) class PlaylistTracklistV1OutputSchema(BasePaginationOutputSchema): """Output schema of Spotify PlaylistTrackListViewV1.""" items = fields.List(fields.Nested(fields.Dict())) class PersonalizedPlaylistTracklistViewParams(QueryWebArgs): """Schema for input validation of Spotify PersonalizedPlaylistTracklistView.""" playlist_id = fields.String(validate=validate.Length(max=50), required=True) class PersonalizedPlaylistTracklistOutputSchema(BasePaginationOutputSchema): """Output schema of Spotify PersonalizedPlaylistTracklistView.""" items = fields.List(fields.Dict()) class TrackInPlaylistViewParams(QueryWebArgs, IsrcRequiredMixin): """Spotify track in playlist view params if retrieved from db.""" playlist_id = fields.String(required=True) playlist_type = fields.String( required=False, validate=validate.OneOf(PLACEMENT_TYPES), missing=CURRENT_PLACEMENT_TYPE, default=CURRENT_PLACEMENT_TYPE, ) class TrackInPlaylistPositionChangesViewParams(QueryWebArgs): """Spotify tracks in playlist view params""" isrc = fields.String(missing=None, default=None) playlist_id = fields.String(required=True) class TrackInPlaylistOutputSchema(Schema): """Spotify track in playlist data from db view output schema.""" playlist_id = fields.String(default=None) earliest_added_date = fields.Date(default=None) added_date = fields.Date(default=None) removed_date = fields.Date(default=None) playlist_name = fields.String(default=None) country_code = fields.String() playlist_image = fields.String() current_position = fields.Integer(default=None) track_id = fields.String(default=None) track_name = fields.String(default=None) isrc = fields.String() personalized = fields.Boolean(default=None) changed_date = fields.Date(default=None) class TrackInPlaylistPositionChangeOutputSchema(Schema): """Spotify track in playlist data from db view output schema.""" pass class RecentAddsOnlyMixin: recent_adds_only = fields.Boolean(default=False, missing=False) class TrackPlaylistsV1ViewParams( IsrcListRequiredMixin, QueryWebArgs, MarketListOptionalMixin, SearchNoneLowerMixin, FullMarketCodeToGlobalMixin, PaginationMixin, RecentAddsOnlyMixin, ): """Spotify query params deserializer for track playlists view.""" order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(TrackPlaylistsOrder.values())), default=[TrackPlaylistsOrder.ADDED_DATE.value], missing=[TrackPlaylistsOrder.ADDED_DATE.value], ) class RecentRemovalsOnlyMixin: recent_removals_only = fields.Boolean(default=True, missing=True) class ExcludeCurrentPlaylistsMixin: exclude_current_playlists = fields.Boolean(default=True, missing=True) class TrackPreviousPlaylistsV1ViewParams( QueryWebArgs, MarketListOptionalMixin, IsrcListRequiredMixin, SearchNoneLowerMixin, FullMarketCodeToGlobalMixin, PaginationMixin, RecentRemovalsOnlyMixin, ExcludeCurrentPlaylistsMixin, ValidateCategoriesByWithIncludeMixin, ValidateOrderByWithIncludeMixin, HandleAllMixin, ): """Spotify query params deserializer for track previous playlists view.""" order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(TrackPreviousPlaylistsOrder.values())), default=[TrackPreviousPlaylistsOrder.REMOVED_DATE_DESC.value, TrackPreviousPlaylistsOrder.PLAYLIST_ID.value], missing=[TrackPreviousPlaylistsOrder.REMOVED_DATE_DESC.value, TrackPreviousPlaylistsOrder.PLAYLIST_ID.value], ) order_by_dependencies = { TrackPreviousPlaylistsOrder.FOLLOWERS.value: TrackPlaylistHistoryInclude.FOLLOWERS.value, TrackPreviousPlaylistsOrder.FOLLOWERS_DESC.value: TrackPlaylistHistoryInclude.FOLLOWERS.value, } include = SplitUniqueListField( fields.String(validate=validate.OneOf(TrackPlaylistHistoryInclude.values(with_all=True))), default=[], missing=[], ) fields_with_all = {"include": TrackPlaylistHistoryInclude} category_id = fields.Int(default=None, missing=None) class TrackPlaylistsV2ViewParams( QueryWebArgs, IsrcListRequiredMixin, MarketListOptionalMixin, SearchNoneLowerMixin, FullMarketCodeToGlobalMixin, ValidateCategoriesByWithIncludeMixin, ValidateOrderByWithIncludeMixin, HandleAllMixin, get_pagination_mixin(page_limit=None), ): """Spotify query params deserializer for track playlists view.""" order_by = SplitUniqueListField( fields.String(validate=validate.OneOf(TrackPlaylistsOrderSpotifyV2.values())), default=None, missing=None, ) include = SplitUniqueListField( fields.String(validate=validate.OneOf(TrackPlaylistInclude.values(with_all=True))), default=[], missing=[] ) streams_markets_list = SplitUniqueListField( fields.String(validate=validate.Length(max=10, min=2)), data_key="streams_market", missing=None ) order_by_dependencies = { TrackPlaylistsOrderV2.PLAYLIST_STREAMS.value: TrackPlaylistInclude.PLAYLIST_STREAMS.value, TrackPlaylistsOrderV2.PLAYLIST_STREAMS_DESC.value: TrackPlaylistInclude.PLAYLIST_STREAMS.value, TrackPlaylistsOrderV2.FOLLOWERS.value: TrackPlaylistInclude.FOLLOWERS.value, TrackPlaylistsOrderV2.FOLLOWERS_DESC.value: TrackPlaylistInclude.FOLLOWERS.value, } fields_with_all = {"include": TrackPlaylistInclude} category_id = fields.Int(default=None, missing=None) class TrackPlaylistOutputSchema(Schema): added_date = fields.Date() country_code = fields.String() current_position = fields.Integer() id = fields.String() image_url = fields.String() name = fields.String() personalized = fields.Boolean() track_id = fields.String() updated_date = fields.Date() class TrackPlaylistV1OutputSchema(TrackPlaylistOutputSchema): trend = fields.Integer(default=None) position_change_date = fields.Date(default=None) is_new = fields.Boolean() class TrackPlaylistsV1OutputSchema(Schema): """Spotify output schema serializer for track playlists view.""" items = fields.List(fields.Nested(TrackPlaylistV1OutputSchema)) count = fields.Integer(default=0) next = fields.String(default=None) previous = fields.String(default=None) class TrackPreviousPlaylistV1OutputSchema(Schema): removed_date = fields.Date() country_code = fields.String() id = fields.String() image_url = fields.String() name = fields.String() personalized = fields.Boolean() track_id = fields.String() updated_date = fields.Date() added_date = fields.Date() category_id = fields.Integer() category_name = fields.String() followers = fields.Integer(default=0) class TrackPreviousPlaylistsV1OutputSchema(BasePaginationOutputSchema): """Output schema of Spotify TrackPreviousPlaylistsV1.""" items = fields.List(fields.Nested(TrackPreviousPlaylistV1OutputSchema)) class TrackPlaylistV2OutputSchema(TrackPlaylistOutputSchema): playlist_streams = fields.Integer(default=0) followers = fields.Integer(default=0) username = fields.String() track_count = fields.Integer(default=0) category_id = fields.Integer() category_name = fields.String() class TrackPlaylistsV2OutputSchema(TrackPlaylistsV1OutputSchema): """Spotify output schema serializer for track playlists view.""" items = fields.List(fields.Nested(TrackPlaylistV2OutputSchema)) class PlaylistsMarketsInputSchema(QueryWebArgs): """Spotify query params deserializer for playlist markets view.""" playlist_ids = SplitUniqueListField(fields.String(), data_key="id", required=True) class PlaylistsMarketsOutputSchema(Schema): """Spotify output schema for playlists markets view.""" class PlaylistMarketsSchema(Schema): class MarketSchema(Schema): id = fields.Integer(required=True) code = fields.String(required=True) full_name = fields.String(required=True) name = fields.String(required=True) market = fields.Nested(MarketSchema) id = fields.String() items = fields.List(fields.Nested(PlaylistMarketsSchema)) class PlaylistsMarketDataInputSchema(QueryWebArgs): """Spotify query params deserializer for playlists market data view.""" playlist_ids = SplitUniqueListField(fields.String(), data_key="id", required=True) include_owner_data = fields.Boolean(default=False, missing=False) class PlaylistMarketDataOutputSchema(Schema): """Spotify output schema for playlist in selected market data view.""" class PlaylistMarketDataSchema(Schema): country_code = fields.String() name = fields.String() id = fields.String() curator_name = fields.String(default=None) image_url = fields.String() personalized = fields.Boolean(default=False, missing=False) updated_date = fields.Date() items = fields.List(fields.Nested(PlaylistMarketDataSchema)) class CoordinatesOutputSchema(Schema): """Coordinates response schema for any graph coordinates.""" x = fields.Integer() y = fields.Integer(default=None) class PlaylistBaseGraphItemSchema(Schema): """Response Schema for playlist graph element.""" playlist_id = fields.String() coordinates = fields.List(fields.Nested(CoordinatesOutputSchema)) class PlaylistDateRangeOutputSchema(Schema): """Playlists total in date ranges output schema.""" current_range = fields.Integer(default=0) prev_range = fields.Integer(default=0) dates = fields.Dict() class PlaylistsListenersGraphV1ViewParams(QueryWebArgs, DateRangeMixin, FullMarketCodeToGlobalMixin, PaginationMixin): """Spotify query params deserializer for playlists listeners graph view.""" playlist_id = SplitUniqueListField( fields.String(), validate=validate.Length(min=1, max=10), data_key="id", required=True ) market = SplitUniqueListField( fields.String(validate=validate.Length(max=10, min=2)), validate=validate.Length(min=1), required=True ) class PlaylistsListenersGraphV1OutputSchema(Schema): """Spotify playlists listeners graph output schema.""" class PlaylistListenersGraphItemSchema(PlaylistBaseGraphItemSchema): country_code = fields.String() items = fields.List(fields.Nested(PlaylistListenersGraphItemSchema)) count = fields.Integer(default=0) dates = fields.Dict() class PlaylistListenersDateRangeV1ViewParams( QueryWebArgs, DateRangeMixin, FullMarketCodeToGlobalMixin, MarketGlobalMixin ): """Spotify query params deserializer for playlists listeners in date ranges view.""" pass class PlaylistListenersDateRangeV1OutputSchema(PlaylistDateRangeOutputSchema): """Spotify playlists listeners num in date ranges output schema.""" class PlaylistsFollowersGraphV1ViewParams(QueryWebArgs, DateRangeMixin, PaginationMixin): """Spotify query params deserializer for playlists followers graph view.""" playlist_id = SplitUniqueListField( fields.String(), validate=validate.Length(min=1, max=10), data_key="id", required=True ) class PlaylistsFollowersGraphV1OutputSchema(Schema): """Spotify playlists followers graph output schema.""" items = fields.List(fields.Nested(PlaylistBaseGraphItemSchema)) count = fields.Integer(default=0) dates = fields.Dict() class PlaylistFollowersDateRangeV1ViewParams(QueryWebArgs, DateRangeMixin): """Spotify query params deserializer for playlists followers in date ranges view.""" class PlaylistFollowersDateRangeV1OutputSchema(PlaylistDateRangeOutputSchema): """Spotify playlists followers num in date ranges output schema.""" class NMFPlaylistsOutputSchema(Schema): playlist_id = fields.String(data_key="playlistId") name = fields.String() market = fields.String(data_key="countryCode") rank = fields.Integer() followers = fields.Integer(default=0) last_date = fields.Date(data_key="fridayLastUpdatedDate") last_added = fields.DateTime(data_key="trackLastAdded", format="%Y-%m-%dT%H:%M:%S+00:00") class NMFTracklistInputSchema(QueryWebArgs, get_pagination_mixin(page_limit=None)): nmf_date = fields.Date(required=True) class NMFTrackRequest(QueryWebArgs, IsrcRequiredMixin, get_pagination_mixin(page_limit=None)): order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(NMFTrackOrder.values())), default=[NMFTrackOrder.POSITION.value, NMFTrackOrder.CODE.value], missing=[NMFTrackOrder.POSITION.value, NMFTrackOrder.CODE.value], ) include = SplitUniqueListField( fields.String(validate=validate.OneOf(NMFTrackInclude.values(with_all=True))), default=[], missing=[] ) region = fields.String(missing=None, default=None) fields_with_all = {"include": NMFTrackInclude} class NMFTracklistPlaylistItem(Schema): playlistId = fields.String() countryCode = fields.String() addedDate = fields.DateTime() position = fields.Integer() playlistImageUrl = fields.String() class NMFTracklistItem(Schema): isrc = fields.String() trackId = fields.String() topTenFeatureCount = fields.Integer() playlists = fields.List(fields.Nested(NMFTracklistPlaylistItem)) class NMFTracklistOutputSchema(Schema): items = fields.List(fields.Nested(NMFTracklistItem)) class NMFTrackPlaylistResponseItem(Schema): code = fields.String() name = fields.String() position = fields.Integer() playlist_id = fields.String() dsp = fields.String() playlist_name = fields.String() image_url = fields.String() class NMFTrackRegionResponseItem(Schema): name = fields.String() code = fields.String() placements = fields.Integer() total = fields.Integer() class NMFTrackResponse(Schema): items = fields.List(fields.Nested(NMFTrackPlaylistResponseItem)) total = fields.Integer() positions_avg = fields.Integer() positions_top_total = fields.Integer() top_playlist_image_url = fields.String() regions = fields.List(fields.Nested(NMFTrackRegionResponseItem)) class NMFCompletenessResponse(Schema): last_updated = fields.String() markets_delayed = fields.List(fields.String()) class PersonalizedPlaylistTrackListV1OutputSchema(Schema): class TracksInPlaylist(Schema): track_id = fields.String() current_position = fields.Integer() added_date = fields.Date() name = fields.String() isrc = fields.String() album_id = fields.String() artists = fields.List(fields.String()) class TrackKeysInPlaylist(Schema): ids = fields.List(fields.String()) tracklist = fields.List(fields.Nested(TracksInPlaylist)) track_keys = fields.Nested(TrackKeysInPlaylist)