From 75e790c63bede81b7c2493482bc7cbe085ab9119 Mon Sep 17 00:00:00 2001 From: Xoconoch Date: Tue, 10 Jun 2025 15:21:46 -0600 Subject: [PATCH] starting to standarize this stuff --- deezspot/models/callback/__init__.py | 11 ++++++ deezspot/models/callback/album.py | 44 ++++++++++++++++++++++++ deezspot/models/callback/artist.py | 39 +++++++++++++++++++++ deezspot/models/callback/common.py | 20 +++++++++++ deezspot/models/callback/playlist.py | 51 ++++++++++++++++++++++++++++ deezspot/models/callback/track.py | 27 +++++++++++++++ 6 files changed, 192 insertions(+) create mode 100644 deezspot/models/callback/__init__.py create mode 100644 deezspot/models/callback/album.py create mode 100644 deezspot/models/callback/artist.py create mode 100644 deezspot/models/callback/common.py create mode 100644 deezspot/models/callback/playlist.py create mode 100644 deezspot/models/callback/track.py diff --git a/deezspot/models/callback/__init__.py b/deezspot/models/callback/__init__.py new file mode 100644 index 0000000..f184df0 --- /dev/null +++ b/deezspot/models/callback/__init__.py @@ -0,0 +1,11 @@ +#!/usr/bin/python3 + +""" +Callback data models for the music metadata schema. +""" + +from .common import IDs, ReleaseDate +from .artist import artistObject, artistTrackObject +from .album import albumObject, albumTrackObject, albumArtistObject, trackAlbumObject +from .track import trackObject +from .playlist import playlistObject, trackPlaylistObject, albumTrackPlaylistObject, artistTrackPlaylistObject \ No newline at end of file diff --git a/deezspot/models/callback/album.py b/deezspot/models/callback/album.py new file mode 100644 index 0000000..b4ab008 --- /dev/null +++ b/deezspot/models/callback/album.py @@ -0,0 +1,44 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass, field +from typing import List, Optional, Dict, Any + +from .common import IDs, ReleaseDate + + +@dataclass +class trackAlbumObject: + """Track when nested inside an album context.""" + type: str = "trackAlbum" + title: str = "" + disc_number: int = 1 + track_number: int = 1 + duration_ms: int = 0 + genres: List[str] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) + + +@dataclass +class albumTrackObject: + """Album when nested inside a track context.""" + type: str = "albumTrack" + album_type: str = "" # "album" | "single" | "compilation" + title: str = "" + release_date: Dict[str, Any] = field(default_factory=dict) # ReleaseDate as dict + total_tracks: int = 0 + genres: List[str] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) + + +@dataclass +class albumObject: + """A standalone album/single/compilation, with nested trackAlbumObject[] for its tracks.""" + type: str = "album" + album_type: str = "" # "album" | "single" | "compilation" + title: str = "" + release_date: Dict[str, Any] = field(default_factory=dict) # ReleaseDate as dict + total_tracks: int = 0 + genres: List[str] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) + # Nested: album's tracks without redundant album info + tracks: List[trackAlbumObject] = field(default_factory=list) \ No newline at end of file diff --git a/deezspot/models/callback/artist.py b/deezspot/models/callback/artist.py new file mode 100644 index 0000000..37b29ad --- /dev/null +++ b/deezspot/models/callback/artist.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass, field +from typing import List, Optional + +from .common import IDs + + +@dataclass +class artistTrackObject: + """ + An artist when nested inside a track context. + No genres, no albums—just identifying info. + """ + type: str = "artistTrack" + name: str = "" + ids: IDs = field(default_factory=IDs) + + +@dataclass +class albumArtistObject: + """Album when nested inside an artist context.""" + type: str = "albumArtist" + album_type: str = "" # "album" | "single" | "compilation" + title: str = "" + release_date: dict = field(default_factory=dict) # ReleaseDate as dict + total_tracks: int = 0 + ids: IDs = field(default_factory=IDs) + + +@dataclass +class artistObject: + """A full artist record, with nested albumArtistObject[] for a discography.""" + type: str = "artist" + name: str = "" + genres: List[str] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) + # Nested: artist's albums without redundant artist info + albums: List[albumArtistObject] = field(default_factory=list) \ No newline at end of file diff --git a/deezspot/models/callback/common.py b/deezspot/models/callback/common.py new file mode 100644 index 0000000..d05d567 --- /dev/null +++ b/deezspot/models/callback/common.py @@ -0,0 +1,20 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass +from typing import Optional + + +@dataclass +class IDs: + """IDs used across objects; isrc only required on items supporting it.""" + spotify: Optional[str] = None + deezer: Optional[str] = None + isrc: Optional[str] = None + + +@dataclass +class ReleaseDate: + """Mandatory release date structure.""" + year: int + month: Optional[int] = None # null if unknown + day: Optional[int] = None # null if unknown \ No newline at end of file diff --git a/deezspot/models/callback/playlist.py b/deezspot/models/callback/playlist.py new file mode 100644 index 0000000..7b67123 --- /dev/null +++ b/deezspot/models/callback/playlist.py @@ -0,0 +1,51 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass, field +from typing import List, Optional, Dict, Any + +from .common import IDs +from .artist import artistObject + + +@dataclass +class albumTrackPlaylistObject: + """Album when nested inside a track in a playlist context.""" + type: str = "albumTrackPlaylist" + album_type: str = "" # "album" | "single" | "compilation" + title: str = "" + release_date: Dict[str, Any] = field(default_factory=dict) # ReleaseDate as dict + ids: IDs = field(default_factory=IDs) + + +@dataclass +class artistTrackPlaylistObject: + """Artist when nested inside a track in a playlist context.""" + type: str = "artistTrackPlaylist" + name: str = "" + genres: List[str] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) + + +@dataclass +class trackPlaylistObject: + """Track when nested inside a playlist context.""" + type: str = "trackPlaylist" + title: str = "" + position: int = 0 # Position in the playlist + duration_ms: int = 0 # mandatory + # Nested objects instead of string references + artist: artistTrackPlaylistObject = field(default_factory=artistTrackPlaylistObject) + album: albumTrackPlaylistObject = field(default_factory=albumTrackPlaylistObject) + ids: IDs = field(default_factory=IDs) + + +@dataclass +class playlistObject: + """A user‑curated playlist, nesting trackPlaylistObject[].""" + type: str = "playlist" + title: str = "" + description: Optional[str] = None + collaborative: bool = False + owner: artistObject = field(default_factory=artistObject) + tracks: List[trackPlaylistObject] = field(default_factory=list) + ids: IDs = field(default_factory=IDs) \ No newline at end of file diff --git a/deezspot/models/callback/track.py b/deezspot/models/callback/track.py new file mode 100644 index 0000000..f0260de --- /dev/null +++ b/deezspot/models/callback/track.py @@ -0,0 +1,27 @@ +#!/usr/bin/python3 + +from dataclasses import dataclass, field +from typing import List, Optional + +from .common import IDs +from .album import albumTrackObject +from .artist import artistTrackObject + + +@dataclass +class trackObject: + """A full track record, nesting albumTrackObject and artistTrackObject.""" + type: str = "track" + title: str = "" + disc_number: int = 1 + track_number: int = 1 + duration_ms: int = 0 # mandatory + genres: List[str] = field(default_factory=list) + + # Nested album summary + album: albumTrackObject = field(default_factory=albumTrackObject) + + # Nested lean artist summary (no genres/albums) + artist: artistTrackObject = field(default_factory=artistTrackObject) + + ids: IDs = field(default_factory=IDs) \ No newline at end of file