from marshmallow import ValidationError, fields, post_load, validate, validates_schema from server.core.constants import DEFAULT_IMAGE_SIZE from server.core.deserializers import ListField, OffsetDefaultMixin, QueryWebArgs from server.spotify.constants import SPOTIFY_TRACK_IMAGE_SIZES, AlbumField, PlaylistField class LimitDefaultMixin: limit = fields.Integer(missing=10, validate=validate.Range(min=0, max=50)) class LimitOffsetMixin: limit = fields.Integer(validate=validate.Range(min=0, max=50)) offset = fields.Integer(validate=validate.Range(min=0)) @post_load def fix_pagination_params(self, data, **kwargs): if "limit" in data and "offset" not in data: data["offset"] = 0 if "limit" not in data and "offset" in data: data["limit"] = 20 return data class FieldsMixin: fields = fields.String() @post_load def fix_fields(self, data, **kwargs): if data.get("fields"): data["fields"] += ",id" return data class IdsMixin: ids = ListField(fields.Str(), validate=validate.Length(min=1), required=True) class MarketMixin: market = fields.String(missing=None) class AdditionalTypesMixin: additional_types = ListField(fields.String(validate=validate.Length(min=1))) class TrackDeserializer(QueryWebArgs, MarketMixin): pass class TracksDeserializer(QueryWebArgs, MarketMixin): ids = ListField(fields.Str(), validate=validate.Length(min=1)) isrc_list = ListField(fields.Str(), validate=validate.Length(min=1), data_key="isrc") @validates_schema def validate_fields_set(self, data, **kwargs): if not data.get("ids") and not data.get("isrc_list"): raise ValidationError("Please specify one of ids or isrc fields.") class TracksImagesDeserializer(QueryWebArgs, IdsMixin, MarketMixin): image_size = fields.Int(missing=DEFAULT_IMAGE_SIZE, validate=validate.OneOf(SPOTIFY_TRACK_IMAGE_SIZES)) class PlaylistDeserializer(QueryWebArgs, MarketMixin, FieldsMixin, AdditionalTypesMixin): items_fields = ListField(fields.String(validate=validate.OneOf(PlaylistField.ALL))) limit = fields.Integer(validate=validate.Range(min=0, max=100)) offset = fields.Integer(validate=validate.Range(min=0)) class PlaylistTracksDeserializer(QueryWebArgs, MarketMixin, FieldsMixin, AdditionalTypesMixin): limit = fields.Integer(validate=validate.Range(min=0, max=100)) offset = fields.Integer(validate=validate.Range(min=0)) class PlaylistsDeserializer(QueryWebArgs, IdsMixin, MarketMixin, FieldsMixin, AdditionalTypesMixin): pass class PlaylistsImagesDeserializer(QueryWebArgs, IdsMixin, MarketMixin): pass class SearchDeserializer(QueryWebArgs, MarketMixin, LimitDefaultMixin, OffsetDefaultMixin): query = fields.Str(validate=validate.Length(min=2)) q = fields.Str() item_type = ListField(fields.Str(), missing=["track"]) type = ListField(fields.Str()) include_external = fields.Str() @validates_schema def validate_fields(self, data, **kwargs): if not data.get("query") and not data.get("q"): raise ValidationError("Please specify one of q or query fields.") class AlbumDeserializer(QueryWebArgs, MarketMixin, LimitOffsetMixin): fields = ListField(fields.String(validate=validate.OneOf(AlbumField.ALL))) class AlbumsDeserializer(QueryWebArgs, IdsMixin, MarketMixin): pass class ArtistsDeserializer(QueryWebArgs, IdsMixin): pass