This commit is contained in:
@ -1,7 +1,7 @@
|
||||
from datetime import datetime
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, HttpUrl, field_validator
|
||||
from pydantic import BaseModel, HttpUrl, RootModel, field_validator
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
@ -62,6 +62,20 @@ class Image(BaseModel):
|
||||
return v
|
||||
|
||||
|
||||
class Cursors(BaseModel):
|
||||
after: int
|
||||
before: int
|
||||
|
||||
|
||||
class Paginated(BaseModel):
|
||||
href: HttpUrl
|
||||
limit: int
|
||||
next: HttpUrl | None
|
||||
offset: int = 0
|
||||
previous: HttpUrl | None
|
||||
total: int
|
||||
|
||||
|
||||
class ExternalUrls(BaseModel):
|
||||
spotify: HttpUrl
|
||||
|
||||
@ -72,6 +86,16 @@ class ExternalIDs(BaseModel):
|
||||
upc: str | None = None
|
||||
|
||||
|
||||
class Copyright(BaseModel):
|
||||
text: str
|
||||
type: Literal['C', 'P']
|
||||
|
||||
|
||||
class ResumePoint(BaseModel):
|
||||
fully_played: bool
|
||||
resume_position_ms: int
|
||||
|
||||
|
||||
class Artist(BaseModel):
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
@ -81,19 +105,28 @@ class Artist(BaseModel):
|
||||
uri: str
|
||||
|
||||
|
||||
class Cursor(BaseModel):
|
||||
after: int
|
||||
before: int
|
||||
|
||||
|
||||
class Context(BaseModel):
|
||||
type: Literal['artist', 'playlist', 'album', 'show', 'collection']
|
||||
href: HttpUrl
|
||||
class BaseTrack(BaseModel):
|
||||
artists: list[Artist]
|
||||
disc_number: int
|
||||
duration_ms: int
|
||||
explicit: bool
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
is_playable: bool | None = None
|
||||
restrictions: Restriction | None = None
|
||||
name: str
|
||||
track_number: int
|
||||
type: Literal['track']
|
||||
uri: str
|
||||
is_local: bool
|
||||
|
||||
|
||||
class Album(BaseModel):
|
||||
class AlbumTracks(Paginated):
|
||||
items: list[BaseTrack]
|
||||
|
||||
|
||||
class BaseAlbum(BaseModel):
|
||||
album_type: Literal['album', 'single', 'compilation']
|
||||
total_tracks: int
|
||||
external_urls: ExternalUrls
|
||||
@ -109,103 +142,27 @@ class Album(BaseModel):
|
||||
artists: list[Artist]
|
||||
|
||||
|
||||
class PlaylistOwner(BaseModel):
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
type: Literal['user']
|
||||
uri: str
|
||||
display_name: str | None
|
||||
|
||||
|
||||
class PlaylistTracks(BaseModel):
|
||||
href: HttpUrl
|
||||
total: int
|
||||
|
||||
|
||||
class Playlist(BaseModel):
|
||||
collaborative: bool
|
||||
description: str
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
name: str
|
||||
owner: PlaylistOwner
|
||||
public: bool
|
||||
snapshot_id: str
|
||||
items: PlaylistTracks
|
||||
type: Literal['playlist']
|
||||
uri: str
|
||||
|
||||
|
||||
class Track(BaseModel):
|
||||
album: Album
|
||||
artists: list[Artist]
|
||||
disc_number: int
|
||||
duration_ms: int
|
||||
explicit: bool
|
||||
class Album(BaseAlbum):
|
||||
external_ids: ExternalIDs
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
is_playable: bool | None = None
|
||||
restrictions: Restriction | None = None
|
||||
name: str
|
||||
track_number: int
|
||||
type: Literal['track']
|
||||
uri: str
|
||||
is_local: bool
|
||||
|
||||
|
||||
class EpisodeResumePoint(BaseModel):
|
||||
fully_played: bool
|
||||
resume_position_ms: int
|
||||
|
||||
|
||||
class Copyright(BaseModel):
|
||||
text: str
|
||||
type: Literal['C', 'P']
|
||||
|
||||
|
||||
class Show(BaseModel):
|
||||
copyrights: list[Copyright]
|
||||
description: str
|
||||
html_description: str
|
||||
explicit: bool
|
||||
external_ids: ExternalIDs | None = None
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
is_externally_hosted: bool
|
||||
languages: list[str]
|
||||
media_type: str
|
||||
name: str
|
||||
type: Literal['show']
|
||||
uri: str
|
||||
total_episodes: int
|
||||
tracks: AlbumTracks
|
||||
|
||||
|
||||
class Episode(BaseModel):
|
||||
description: str
|
||||
html_description: str
|
||||
duration_ms: int
|
||||
explicit: bool
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
is_externally_hosted: bool
|
||||
is_playable: bool
|
||||
languages: list[str]
|
||||
name: str
|
||||
release_date: datetime
|
||||
release_date_precision: Literal['year', 'month', 'day']
|
||||
resume_point: EpisodeResumePoint
|
||||
type: Literal['episode']
|
||||
uri: str
|
||||
restrictions: Restriction | None = None
|
||||
show: Show | None = None
|
||||
class Track(BaseTrack):
|
||||
album: BaseAlbum
|
||||
|
||||
|
||||
class UserSavedAlbum(BaseModel):
|
||||
added_at: datetime
|
||||
album: Album
|
||||
|
||||
|
||||
class UserSavedAlbums(Paginated):
|
||||
items: list[UserSavedAlbum]
|
||||
|
||||
|
||||
class ArtistsAlbums(Paginated):
|
||||
items: list[Album]
|
||||
|
||||
|
||||
class AudioBookAuthor(BaseModel):
|
||||
@ -236,17 +193,79 @@ class AudioBook(BaseModel):
|
||||
total_chapters: int
|
||||
|
||||
|
||||
class PlaybackStateActions(BaseModel):
|
||||
interrupting_playback: bool | None = None
|
||||
pausing: bool | None = None
|
||||
resuming: bool | None = None
|
||||
seeking: bool | None = None
|
||||
skipping_next: bool | None = None
|
||||
skipping_prev: bool | None = None
|
||||
toggling_repeat_context: bool | None = None
|
||||
toggling_shuffle: bool | None = None
|
||||
toggling_repeat_track: bool | None = None
|
||||
transferring_playback: bool | None = None
|
||||
class AudioBookChapter(BaseModel):
|
||||
chapter_number: int
|
||||
description: str
|
||||
html_description: str
|
||||
duration_ms: int
|
||||
explicit: bool
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
is_playable: bool
|
||||
languages: list[str]
|
||||
name: str
|
||||
release_date: datetime
|
||||
release_date_precision: Literal['year', 'month', 'day']
|
||||
resume_point: ResumePoint
|
||||
type: Literal['episode']
|
||||
uri: str
|
||||
restrictions: Restriction
|
||||
|
||||
|
||||
class AudiobookChapters(BaseModel):
|
||||
items: list[AudioBookChapter]
|
||||
|
||||
|
||||
class UserSavedAudiobooks(Paginated):
|
||||
items: list[AudioBook]
|
||||
|
||||
|
||||
class Chapter(AudioBookChapter):
|
||||
audiobook: AudioBook
|
||||
|
||||
|
||||
class Show(BaseModel):
|
||||
copyrights: list[Copyright]
|
||||
description: str
|
||||
html_description: str
|
||||
explicit: bool
|
||||
external_ids: ExternalIDs | None = None
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
is_externally_hosted: bool
|
||||
languages: list[str]
|
||||
media_type: str
|
||||
name: str
|
||||
type: Literal['show']
|
||||
uri: str
|
||||
total_episodes: int
|
||||
|
||||
|
||||
class Episode(AudioBookChapter):
|
||||
show: Show
|
||||
|
||||
|
||||
class UsedSavedEpisode(BaseModel):
|
||||
added_at: datetime
|
||||
episode: Episode
|
||||
|
||||
|
||||
class UserSavedEpisodes(Paginated):
|
||||
items: list[UsedSavedEpisode]
|
||||
|
||||
|
||||
class CheckUserSavedItems(RootModel[list[bool]]):
|
||||
pass
|
||||
|
||||
|
||||
class Context(BaseModel):
|
||||
type: Literal['artist', 'playlist', 'album', 'show', 'collection']
|
||||
href: HttpUrl
|
||||
external_urls: ExternalUrls
|
||||
uri: str
|
||||
|
||||
|
||||
class PlaybackState(BaseModel):
|
||||
@ -259,35 +278,94 @@ class PlaybackState(BaseModel):
|
||||
is_playing: bool
|
||||
item: Track | Episode | None
|
||||
currently_playing_type: Literal['track', 'episode', 'ad', 'unknown']
|
||||
# TODO: allows has 'disallows' inside? not sure about that
|
||||
# actions: PlaybackStateActions
|
||||
|
||||
|
||||
class PlayHistoryObject(BaseModel):
|
||||
class Devices(BaseModel):
|
||||
devices: list[Device]
|
||||
|
||||
|
||||
class RecentlyPlayedTrack(BaseModel):
|
||||
track: Track
|
||||
played_at: datetime
|
||||
context: Context | None = None
|
||||
context: Context
|
||||
|
||||
|
||||
class RecentlyPlayed(BaseModel):
|
||||
class RecentlyPlayedTracks(Paginated):
|
||||
cursors: Cursors
|
||||
items: list[RecentlyPlayedTrack]
|
||||
|
||||
|
||||
class UsersQueue(BaseModel):
|
||||
currently_playing: Track | Episode | None
|
||||
queue: list[Track | Episode]
|
||||
|
||||
|
||||
class PlaylistOwner(BaseModel):
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
limit: int
|
||||
next: HttpUrl | None
|
||||
cursors: Cursor
|
||||
total: int | None = None
|
||||
items: list[PlayHistoryObject]
|
||||
id: str
|
||||
type: Literal['user']
|
||||
uri: str
|
||||
display_name: str | None
|
||||
|
||||
|
||||
class SearchData(BaseModel):
|
||||
class PlaylistTrack(BaseModel):
|
||||
added_at: datetime
|
||||
added_by: PlaylistOwner
|
||||
is_local: bool
|
||||
item: Track | Episode
|
||||
|
||||
|
||||
class PlaylistTracks(Paginated):
|
||||
href: HttpUrl
|
||||
item: PlaylistTrack
|
||||
|
||||
|
||||
class SimplifiedPlaylistTracks(Paginated):
|
||||
href: HttpUrl
|
||||
limit: int
|
||||
next: HttpUrl | None
|
||||
offset: int
|
||||
previous: int | None
|
||||
total: int
|
||||
|
||||
|
||||
class SearchAlbumData(SearchData):
|
||||
class Playlist(BaseModel):
|
||||
type: Literal['playlist']
|
||||
uri: str
|
||||
collaborative: bool
|
||||
description: str
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
name: str
|
||||
owner: PlaylistOwner
|
||||
public: bool
|
||||
snapshot_id: str
|
||||
items: PlaylistTracks | None = None
|
||||
|
||||
|
||||
class SimplifiedPlaylist(BaseModel):
|
||||
type: Literal['playlist']
|
||||
uri: str
|
||||
collaborative: bool
|
||||
external_urls: ExternalUrls
|
||||
href: HttpUrl
|
||||
id: str
|
||||
images: list[Image]
|
||||
name: str
|
||||
owner: PlaylistOwner
|
||||
public: bool
|
||||
snapshot_id: str
|
||||
items: SimplifiedPlaylistTracks
|
||||
|
||||
|
||||
class UserPlaylists(Paginated):
|
||||
items: list[Playlist]
|
||||
|
||||
|
||||
class PlaylistImages(RootModel[list[Image]]):
|
||||
pass
|
||||
|
||||
|
||||
class SearchAlbumData(Paginated):
|
||||
items: list[Album]
|
||||
|
||||
|
||||
@ -295,7 +373,7 @@ class SearchAlbum(BaseModel):
|
||||
albums: SearchAlbumData
|
||||
|
||||
|
||||
class SearchArtistData(SearchData):
|
||||
class SearchArtistData(Paginated):
|
||||
items: list[Artist]
|
||||
|
||||
|
||||
@ -303,7 +381,7 @@ class SearchArtist(BaseModel):
|
||||
artists: SearchArtistData
|
||||
|
||||
|
||||
class SearchPlaylistData(SearchData):
|
||||
class SearchPlaylistData(Paginated):
|
||||
items: list[Playlist | None]
|
||||
|
||||
|
||||
@ -311,7 +389,7 @@ class SearchPlaylist(BaseModel):
|
||||
playlists: SearchPlaylistData
|
||||
|
||||
|
||||
class SearchTrackData(SearchData):
|
||||
class SearchTrackData(Paginated):
|
||||
items: list[Track]
|
||||
|
||||
|
||||
@ -319,7 +397,7 @@ class SearchTrack(BaseModel):
|
||||
tracks: SearchTrackData
|
||||
|
||||
|
||||
class SearchShowData(SearchData):
|
||||
class SearchShowData(Paginated):
|
||||
items: list[Show]
|
||||
|
||||
|
||||
@ -327,7 +405,7 @@ class SearchShow(BaseModel):
|
||||
shows: SearchShowData
|
||||
|
||||
|
||||
class SearchEpisodeData(SearchData):
|
||||
class SearchEpisodeData(Paginated):
|
||||
items: list[Episode]
|
||||
|
||||
|
||||
@ -335,7 +413,7 @@ class SearchEpisode(BaseModel):
|
||||
episodes: SearchEpisodeData
|
||||
|
||||
|
||||
class SearchAudiobookData(SearchData):
|
||||
class SearchAudiobookData(Paginated):
|
||||
items: list[AudioBook]
|
||||
|
||||
|
||||
@ -343,6 +421,28 @@ class SearchAudiobook(BaseModel):
|
||||
audiobooks: SearchAudiobookData
|
||||
|
||||
|
||||
class ShowEpisodes(Paginated):
|
||||
items: list[AudioBookChapter]
|
||||
|
||||
|
||||
class SavedShow(BaseModel):
|
||||
added_at: datetime
|
||||
show: Show
|
||||
|
||||
|
||||
class SavedShows(Paginated):
|
||||
items: list[SavedShow]
|
||||
|
||||
|
||||
class SavedTrack(BaseModel):
|
||||
added_at: datetime
|
||||
track: Track
|
||||
|
||||
|
||||
class SavedTracks(Paginated):
|
||||
items: list[SavedTrack]
|
||||
|
||||
|
||||
class UserProfile(BaseModel):
|
||||
id: str
|
||||
display_name: str
|
||||
@ -351,3 +451,19 @@ class UserProfile(BaseModel):
|
||||
images: list[Image]
|
||||
type: Literal['user']
|
||||
uri: str
|
||||
|
||||
|
||||
class UsersTopItemsTracks(Paginated):
|
||||
items: list[Track]
|
||||
|
||||
|
||||
class UsersTopItemsArtists(Paginated):
|
||||
items: list[Artist]
|
||||
|
||||
|
||||
class FollowedArtistsData(Paginated):
|
||||
items: list[Artist]
|
||||
|
||||
|
||||
class FollowedArtists(BaseModel):
|
||||
artists: FollowedArtistsData
|
||||
|
||||
Reference in New Issue
Block a user