Compare commits
4 Commits
fa89e49f29
...
latest
| Author | SHA1 | Date | |
|---|---|---|---|
| 7627e9e273 | |||
| 3cbed95c08 | |||
| c15db42e5b | |||
| 80a97758a6 |
@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "oxidespotify"
|
name = "oxidespotify"
|
||||||
version = "1.0.0"
|
version = "1.0.2"
|
||||||
description = "Client for Spotify API"
|
description = "Client for Spotify API"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
authors = [{ name = "Miwory", email = "miwory.uwu@gmail.com" }]
|
authors = [{ name = "Miwory", email = "miwory.uwu@gmail.com" }]
|
||||||
|
|||||||
@ -1,7 +1,13 @@
|
|||||||
from datetime import datetime
|
from datetime import date, datetime
|
||||||
from typing import Literal
|
from typing import Annotated, Literal
|
||||||
|
|
||||||
from pydantic import BaseModel, HttpUrl, RootModel, field_validator
|
from pydantic import (
|
||||||
|
BaseModel,
|
||||||
|
BeforeValidator,
|
||||||
|
HttpUrl,
|
||||||
|
RootModel,
|
||||||
|
field_validator,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
@ -22,6 +28,21 @@ class InternalError(Error):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_spotify_date(v: str) -> str:
|
||||||
|
parts = v.split('-')
|
||||||
|
if len(parts) == 1:
|
||||||
|
return f'{v}-01-01'
|
||||||
|
if len(parts) == 2:
|
||||||
|
return f'{v}-01'
|
||||||
|
|
||||||
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
PrecisionedReleaseDate = Annotated[
|
||||||
|
date, BeforeValidator(normalize_spotify_date)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class Token(BaseModel):
|
class Token(BaseModel):
|
||||||
token_type: Literal['Bearer']
|
token_type: Literal['Bearer']
|
||||||
access_token: str
|
access_token: str
|
||||||
@ -72,8 +93,8 @@ class Paginated(BaseModel):
|
|||||||
limit: int
|
limit: int
|
||||||
next: HttpUrl | None
|
next: HttpUrl | None
|
||||||
offset: int = 0
|
offset: int = 0
|
||||||
previous: HttpUrl | None
|
previous: HttpUrl | None = None
|
||||||
total: int
|
total: int = 0
|
||||||
|
|
||||||
|
|
||||||
class ExternalUrls(BaseModel):
|
class ExternalUrls(BaseModel):
|
||||||
@ -134,7 +155,7 @@ class BaseAlbum(BaseModel):
|
|||||||
id: str
|
id: str
|
||||||
images: list[Image]
|
images: list[Image]
|
||||||
name: str
|
name: str
|
||||||
release_date: datetime
|
release_date: PrecisionedReleaseDate
|
||||||
release_date_precision: Literal['year', 'month', 'day']
|
release_date_precision: Literal['year', 'month', 'day']
|
||||||
restrictions: Restriction | None = None
|
restrictions: Restriction | None = None
|
||||||
type: Literal['album']
|
type: Literal['album']
|
||||||
@ -206,7 +227,7 @@ class AudioBookChapter(BaseModel):
|
|||||||
is_playable: bool
|
is_playable: bool
|
||||||
languages: list[str]
|
languages: list[str]
|
||||||
name: str
|
name: str
|
||||||
release_date: datetime
|
release_date: PrecisionedReleaseDate
|
||||||
release_date_precision: Literal['year', 'month', 'day']
|
release_date_precision: Literal['year', 'month', 'day']
|
||||||
resume_point: ResumePoint
|
resume_point: ResumePoint
|
||||||
type: Literal['episode']
|
type: Literal['episode']
|
||||||
@ -287,7 +308,7 @@ class Devices(BaseModel):
|
|||||||
class RecentlyPlayedTrack(BaseModel):
|
class RecentlyPlayedTrack(BaseModel):
|
||||||
track: Track
|
track: Track
|
||||||
played_at: datetime
|
played_at: datetime
|
||||||
context: Context
|
context: Context | None = None
|
||||||
|
|
||||||
|
|
||||||
class RecentlyPlayedTracks(Paginated):
|
class RecentlyPlayedTracks(Paginated):
|
||||||
@ -323,7 +344,7 @@ class PlaylistTracks(Paginated):
|
|||||||
|
|
||||||
class SimplifiedPlaylistTracks(Paginated):
|
class SimplifiedPlaylistTracks(Paginated):
|
||||||
href: HttpUrl
|
href: HttpUrl
|
||||||
total: int
|
total: int = 0
|
||||||
|
|
||||||
|
|
||||||
class Playlist(BaseModel):
|
class Playlist(BaseModel):
|
||||||
|
|||||||
Reference in New Issue
Block a user