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.image import ImageSizeMixin from apollo_utils.service.schemas.mixins.isrc import IsrcListRequiredMixin, IsrcRequiredMixin, SourceTrackISRCLowerMixin from apollo_utils.service.schemas.mixins.market import MarketListTopMixin, MarketRequiredMixin, MarketUsMixin 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 apollo_utils.service.schemas.swagger.types import ApispecTypes from marshmallow import Schema, fields, validate from src.constants.core import CURRENT_PLACEMENT_TYPE, DEFAULT_IMAGE_SIZE, PLACEMENT_TYPES from src.constants.include import TrackPlaylistHistoryInclude, TrackPlaylistInclude from src.constants.order import PlaylistTracklistOrder, TrackPlaylistsOrder, TrackPlaylistsOrderV2, \ TrackPreviousPlaylistsOrder from src.legacy.apple_music.constants import APPLE_GLOBAL_MARKET_REPLACEMENT, APPLE_MAX_IMAGE_SIZE, \ PlaylistMarketsIncludeFields from src.legacy.core.serializers import BasePaginationOutputSchema, JsonBodySchema, PaginationMixin, QueryWebArgs, \ UniqueArgsListField, get_pagination_mixin class TrackPlaylistsOutputItemSchema(Schema): """Schema for output validation of TrackPlaylistsView.""" id = fields.String() added_date = fields.Date() changed_date = fields.Date() country_code = fields.String() image_url = fields.URL() name = fields.String() position = fields.Integer() trend = fields.Integer() week_streams = fields.Integer() class TrackPlaylistsOutputSchema(BasePaginationOutputSchema): items = fields.List(fields.Nested(TrackPlaylistsOutputItemSchema)) class TrackPlaylistsAddedDateViewParams(QueryWebArgs, MarketGlobalMixin): """Schema for input validation of TrackPlaylistsAddedDatesView.""" song_id = fields.String(required=True) playlist_ids = SplitUniqueListField(fields.String(), validate=validate.Length(min=1, max=50), required=True) class TrackPlaylistsAddedDateOutputSchema(Schema): """Output schema for Track playlists added dates view.""" id = fields.String() added_date = fields.Date() class PlaylistTracklistV1ViewParams( QueryWebArgs, MarketUsMixin, PaginationMixin, SearchNoneLowerMixin, SourceTrackISRCLowerMixin ): """Schema for input validation of Apple Music PlaylistTrackListViewV1.""" playlist_id = fields.String(validate=validate.Length(max=50), required=True) order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(PlaylistTracklistOrder.ALL)), default=[PlaylistTracklistOrder.CURR_POSITION], missing=[PlaylistTracklistOrder.CURR_POSITION], ) image_size = fields.Int(missing=DEFAULT_IMAGE_SIZE, validate=validate.Range(max=APPLE_MAX_IMAGE_SIZE, min=1)) class PlaylistTracklistV1OutputSchema(BasePaginationOutputSchema): """Output schema of Apple Music PlaylistTrackListViewV1.""" items = fields.List(fields.Nested(fields.Dict())) class PlaylistTracklistAllocationGraphViewParams(QueryWebArgs, get_pagination_mixin(page_limit=None)): """Schema for input validation of Apple Music PlaylistTrackListAllocationGraphView.""" playlist_id = fields.String(validate=validate.Length(max=50), required=True) market = fields.String(validate=validate.Length(max=10, min=2), missing=APPLE_GLOBAL_MARKET_REPLACEMENT) class PlaylistTrackAllocatedGraphOutputItemSchema(Schema): """Schema for output validation of PlaylistTrackListAllocationGraphView.""" current_position = fields.Integer() track_id = fields.Integer() isrc = fields.String() release_date = fields.Date() album_release_date = fields.Date() class PlaylistTracklistAllocationGraphViewSchema(BasePaginationOutputSchema): items = fields.List(fields.Nested(PlaylistTrackAllocatedGraphOutputItemSchema)) class TrackInPlaylistV1ViewParams(QueryWebArgs, MarketGlobalMixin, IsrcRequiredMixin): """Apple track in playlist view params.""" playlist_id = fields.String(required=True) image_size = fields.Int(missing=DEFAULT_IMAGE_SIZE, validate=validate.Range(max=APPLE_MAX_IMAGE_SIZE, min=1)) playlist_type = fields.String( required=False, validate=validate.OneOf(PLACEMENT_TYPES), missing=CURRENT_PLACEMENT_TYPE, default=CURRENT_PLACEMENT_TYPE, ) class TrackInPlaylistV1OutputSchema(Schema): """Apple track in playlist view output schema.""" isrc = fields.String(default=None) playlist_id = fields.String(default=None) track_id = fields.String(default=None) playlist_name = fields.String(default=None) track_name = fields.String(default=None) country_code = fields.String(default=None) playlist_image = fields.Method("get_playlist_image") current_position = fields.Integer(default=None) added_date = fields.Method("get_added_date", example=ApispecTypes.DATE) removed_date = fields.Date(default=None) track_image = fields.Method("get_track_image") changed_date = fields.Date(default=None) previous_position = fields.Integer( dump_default=None, ) trend = fields.Method("get_trend", example=ApispecTypes.INTEGER) is_new = fields.Method("get_is_new", example=ApispecTypes.BOOLEAN) def get_playlist_image(self, *args): return self.context.get("playlist_image") def get_track_image(self, *args): return self.context.get("track_image") def get_trend(self, obj): is_new = self.get_is_new(obj) no_trend = self.context.get("no_trend") return None if is_new or no_trend else self.context.get("trend") def get_is_new(self, obj): added_date = self.context.get("added_date") today = self.context.get("today") if not added_date or not obj.changed_date: return False try: return not obj.previous_position and added_date == today except AttributeError: return def get_added_date(self, *args): return self.context.get("added_date") class RecentAddsOnlyMixin: recent_adds_only = fields.Boolean(default=False, missing=False) class TrackPlaylistsV1ViewParams( QueryWebArgs, SearchNoneLowerMixin, MarketListTopMixin, PaginationMixin, ImageSizeMixin, RecentAddsOnlyMixin ): """Apple Music query params deserializer for track playlists view.""" isrc = fields.String(validate=validate.Length(equal=12), required=True) order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(TrackPlaylistsOrder.values())), default=[TrackPlaylistsOrder.ADDED_DATE.value], missing=[TrackPlaylistsOrder.ADDED_DATE.value], ) class TrackPlaylistsV2ViewParams( QueryWebArgs, IsrcListRequiredMixin, SearchNoneLowerMixin, MarketListTopMixin, ImageSizeMixin, RecentAddsOnlyMixin, ValidateCategoriesByWithIncludeMixin, ValidateOrderByWithIncludeMixin, HandleAllMixin, get_pagination_mixin(page_limit=None), ): """Apple Music query params deserializer for track playlists view.""" order_by = UniqueArgsListField( fields.String(validate=validate.OneOf(TrackPlaylistsOrderV2.values())), default=[TrackPlaylistsOrderV2.ADDED_DATE.value], missing=[TrackPlaylistsOrderV2.ADDED_DATE.value], ) include = SplitUniqueListField( fields.String(validate=validate.OneOf(TrackPlaylistInclude.values(with_all=True))), default=[], missing=[] ) order_by_dependencies = { TrackPlaylistsOrderV2.PLAYLIST_STREAMS.value: TrackPlaylistInclude.PLAYLIST_STREAMS.value, TrackPlaylistsOrderV2.PLAYLIST_STREAMS_DESC.value: TrackPlaylistInclude.PLAYLIST_STREAMS.value, } fields_with_all = {"include": TrackPlaylistInclude} category_id = fields.Int(default=None, missing=None) class TrackPlaylistV1OutputSchema(Schema): added_date = fields.Date() country_code = fields.String() current_position = fields.Integer() id = fields.String() image_url = fields.String() name = fields.String() position_change_date = fields.Date(default=None) track_id = fields.String() trend = fields.Integer(default=None) updated_date = fields.Date() is_new = fields.Boolean() class TrackPlaylistsV1OutputSchema(Schema): """Apple Music 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 TrackPlaylistV2OutputSchema(TrackPlaylistV1OutputSchema): playlist_streams = fields.Integer(default=0) username = fields.String() track_count = fields.Integer(default=0) category_id = fields.Integer() category_name = fields.String() class TrackPlaylistsV2OutputSchema(TrackPlaylistsV1OutputSchema): """Apple Music output schema serializer for track playlists view.""" items = fields.List(fields.Nested(TrackPlaylistV2OutputSchema)) class PlaylistsMarketsInputSchema(QueryWebArgs): """Apple Music query params deserializer for playlists markets view.""" playlist_ids = SplitUniqueListField(fields.String(), data_key="id", required=True) include = SplitUniqueListField(fields.String(validate=validate.OneOf(PlaylistMarketsIncludeFields.ALL)), missing=[]) class PlaylistsMarketsOutputSchema(Schema): """Apple Music 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() top_markets = fields.List(fields.Nested(MarketSchema), required=False) other_markets = fields.List(fields.Nested(MarketSchema), required=False) items = fields.List(fields.Nested(PlaylistMarketsSchema)) class PlaylistsMarketDataInputSchema(QueryWebArgs, MarketRequiredMixin): """Apple Music query params deserializer for playlists market data view.""" playlist_ids = SplitUniqueListField(fields.String(), data_key="id", required=True) class PlaylistMarketDataOutputSchema(Schema): """Apple Music 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) curator_id = fields.String(default=None) image_url = fields.String() updated_date = fields.Date() items = fields.List(fields.Nested(PlaylistMarketDataSchema)) class PlaylistsBulkInputSchema(JsonBodySchema): """Apple Music body deserializer for playlists bulk data view.""" class PlaylistsBulkInputItemSchema(JsonBodySchema): playlist_id = fields.String(data_key="id", required=True) country_code = fields.String(validate=validate.Length(max=10, min=2), required=True) items = fields.List( fields.Nested(PlaylistsBulkInputItemSchema, required=True), required=True, validate=validate.Length(min=1), ) 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, MarketListTopMixin, IsrcListRequiredMixin, SearchNoneLowerMixin, PaginationMixin, RecentRemovalsOnlyMixin, ExcludeCurrentPlaylistsMixin, ValidateCategoriesByWithIncludeMixin, ImageSizeMixin, HandleAllMixin, ): """Apple Music 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], ) 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 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() category_id = fields.Integer() category_name = fields.String() added_date = fields.Date() class TrackPreviousPlaylistsV1OutputSchema(BasePaginationOutputSchema): """Apple Music output schema serializer for track playlists view.""" items = fields.List(fields.Nested(TrackPreviousPlaylistV1OutputSchema))