from marshmallow import Schema, fields, validate from marshmallow.validate import Range, OneOf from server.core.schemas import BaseSchema, GenreSchema, CountrySchema from server.dna.constants import TRACK from server.artist.schemas import ArtistSearchByNameRequestSchema from server.artist.constants import COUNTRIES_LIST_SLUG_NAME from server.track.constants import GENRES_LIST_SLUG_NAME # Request Schemas ====================================================================================================== class TiktokTrackDiscoveryCountRequestSchema(BaseSchema): min_posts_latest = fields.Integer(allow_none=True) max_posts_latest = fields.Integer(allow_none=True) min_views = fields.Integer(allow_none=True) max_views = fields.Integer(allow_none=True) min_likes = fields.Integer(allow_none=True) max_likes = fields.Integer(allow_none=True) min_comments = fields.Integer(allow_none=True) max_comments = fields.Integer(allow_none=True) min_mentions = fields.Integer(allow_none=True) max_mentions = fields.Integer(allow_none=True) chart_type = fields.String(load_default="LIKES", validate=OneOf(["VIEWS", "LIKES"])) class YoutubeTrackDiscoveryCountRequestSchema(BaseSchema): min_videos = fields.Integer(allow_none=True) max_videos = fields.Integer(allow_none=True) min_views = fields.Integer(allow_none=True) max_views = fields.Integer(allow_none=True) min_likes = fields.Integer(allow_none=True) max_likes = fields.Integer(allow_none=True) min_comments = fields.Integer(allow_none=True) max_comments = fields.Integer(allow_none=True) min_latest_release_days = fields.TimeDelta(precision=fields.TimeDelta.DAYS, allow_none=True) chart_type = fields.String(load_default="LIKES", validate=OneOf(["VIEWS", "LIKES"])) class SpotifyTrackDiscoveryCountRequestSchema(BaseSchema): min_monthly_listeners = fields.Integer(allow_none=True) max_monthly_listeners = fields.Integer(allow_none=True) min_playlists = fields.Integer(allow_none=True) max_playlists = fields.Integer(allow_none=True) min_streams = fields.Integer(allow_none=True) max_streams = fields.Integer(allow_none=True) min_popularity = fields.Integer(allow_none=True) max_popularity = fields.Integer(allow_none=True) chart_type = fields.String(load_default="STREAMS", validate=OneOf(["STREAMS", "MONTHLY_LISTENERS"])) class SoundCloudTrackDiscoveryCountRequestSchema(BaseSchema): min_followers = fields.Integer(allow_none=True) max_followers = fields.Integer(allow_none=True) min_plays = fields.Integer(allow_none=True) max_plays = fields.Integer(allow_none=True) min_likes = fields.Integer(allow_none=True) max_likes = fields.Integer(allow_none=True) min_comments = fields.Integer(allow_none=True) max_comments = fields.Integer(allow_none=True) min_latest_release_days = fields.TimeDelta(precision=fields.TimeDelta.DAYS, allow_none=True) chart_type = fields.String(load_default="PLAYS", validate=OneOf(["PLAYS", "FOLLOWERS", "LIKES", "COMMENTS"])) class TrackDiscoveryCountRequestSchema(BaseSchema): tiktok = fields.Nested(TiktokTrackDiscoveryCountRequestSchema) youtube = fields.Nested(YoutubeTrackDiscoveryCountRequestSchema) spotify = fields.Nested(SpotifyTrackDiscoveryCountRequestSchema) soundcloud = fields.Nested(SoundCloudTrackDiscoveryCountRequestSchema) countries = fields.List( fields.String(), allow_none=True, validate=[validate.Length(min=1), validate.ContainsOnly(COUNTRIES_LIST_SLUG_NAME)], ) genres = fields.List( fields.String(), allow_none=True, validate=[validate.Length(min=1), validate.ContainsOnly(GENRES_LIST_SLUG_NAME)], ) class TrackDiscoveryRequestSchema(TrackDiscoveryCountRequestSchema): limit = fields.Integer(validate=Range(min=1, max=100), load_default=100) offset = fields.Integer(validate=Range(min=0), load_default=0) class TrackSearchByNameRequestSchema(ArtistSearchByNameRequestSchema): class Meta: fields = ( "limit", "offset", "name", ) # Response Schemas ===================================================================================================== class TikTokTrackDiscoveryResponseSchema(BaseSchema): likes = fields.Integer() comments = fields.Integer() views = fields.Integer() posts_latest = fields.Integer() mentions = fields.Integer() views_change = fields.Integer() chart_data = fields.List(fields.Integer()) chart_type = fields.String(validate=OneOf("Likes", "Views")) class YoutubeTrackDiscoveryResponseSchema(BaseSchema): likes = fields.Integer() comments = fields.Integer() views = fields.Integer() videos = fields.Integer() latest_release_date = fields.Str() views_change = fields.Integer() chart_data = fields.List(fields.Integer()) chart_type = fields.String(validate=OneOf("Likes", "Views")) class SpotifyTrackDiscoveryResponseSchema(BaseSchema): monthly_listeners = fields.Integer() playlists = fields.Integer() popularity = fields.Integer() spotify_artist_id = fields.String() spotify_track_id = fields.String() streams = fields.Integer() streams_change = fields.Integer() chart_data = fields.List(fields.Integer()) chart_type = fields.String(validate=OneOf("STREAMS", "MONTHLY_LISTENERS")) class SoundCloudTrackDiscoveryResponseSchema(BaseSchema): followers = fields.Integer() plays = fields.Integer() likes = fields.Integer() comments = fields.Integer() plays_change = fields.Integer() soundcloud_track_id = fields.String() chart_data = fields.List(fields.Integer()) chart_type = fields.String(validate=OneOf(["PLAYS", "FOLLOWERS", "LIKES", "COMMENTS"])) class BaseTrackDiscoveryResponseSchema(BaseSchema): id = fields.String() # chartmetric track_id name = fields.String() isrc = fields.String() artwork_url = fields.URL() artwork_url_alt = fields.URL() label = fields.String() artist_name = fields.String() cm_artist_id = fields.String() release_date = fields.String() spotify_track_id = fields.String() country = fields.Nested(CountrySchema) genres = fields.List(fields.Nested(GenreSchema)) class TrackDiscoveryResponseSchema(BaseTrackDiscoveryResponseSchema): tiktok = fields.Nested(TikTokTrackDiscoveryResponseSchema) youtube = fields.Nested(YoutubeTrackDiscoveryResponseSchema) spotify = fields.Nested(SpotifyTrackDiscoveryResponseSchema) soundcloud = fields.Nested(SoundCloudTrackDiscoveryResponseSchema) class TrackSearchByNameDataResponseSchema(Schema): name = fields.String() artwork_url = fields.String() artwork_url_alt = fields.String() artist_name = fields.String() score = fields.Float() class TrackSearchByNameResponseSchema(Schema): entity_id = fields.String() entity_type = fields.String(validate=OneOf([TRACK])) data = fields.Nested(TrackSearchByNameDataResponseSchema) class TrackDiscoveryCountResponseSchema(Schema): total_count = fields.Integer() class BaseTrackDiscoveryResultResponseSchema(BaseSchema): likes_chart = fields.List(fields.Integer()) views_chart = fields.List(fields.Integer()) last_chart_date = fields.String() class TiktokTrackDiscoveryResultResponseSchema( BaseTrackDiscoveryResultResponseSchema, TikTokTrackDiscoveryResponseSchema ): class Meta: exclude = ("chart_data", "views_change") class YoutubeTrackDiscoveryResultResponseSchema( BaseTrackDiscoveryResultResponseSchema, YoutubeTrackDiscoveryResponseSchema ): class Meta: exclude = ("chart_data",) class SpotifyTrackDiscoveryResultResponseSchema(SpotifyTrackDiscoveryResponseSchema): class Meta: exclude = ("chart_data",) streams_chart = fields.List(fields.Integer()) monthly_listeners_chart = fields.List(fields.Integer()) last_chart_date = fields.String() class SoundCloudTrackDiscoveryResultResponseSchema(SoundCloudTrackDiscoveryResponseSchema): class Meta: exclude = ("chart_data",) plays_chart = fields.List(fields.Integer()) likes_chart = fields.List(fields.Integer()) comments_chart = fields.List(fields.Integer()) followers_chart = fields.List(fields.Integer()) last_chart_date = fields.String() class TrackDiscoveryResultResponseSchema(BaseTrackDiscoveryResponseSchema): tiktok = fields.Nested(TiktokTrackDiscoveryResultResponseSchema) youtube = fields.Nested(YoutubeTrackDiscoveryResultResponseSchema) spotify = fields.Nested(SpotifyTrackDiscoveryResultResponseSchema) soundcloud = fields.Nested(SoundCloudTrackDiscoveryResultResponseSchema)