add search

This commit is contained in:
oskvr37
2025-01-13 23:38:23 +01:00
parent a638374539
commit 44d5917006
6 changed files with 185 additions and 10 deletions
+41 -2
View File
@@ -26,8 +26,47 @@ class TestApi(unittest.TestCase):
def test_ready(self):
session = self.api.getSession()
self.assertEqual(session["userId"], int(self.api.user_id))
self.assertEqual(session["countryCode"], self.api.country_code)
self.assertEqual(session.userId, int(self.api.user_id))
self.assertEqual(session.countryCode, self.api.country_code)
def test_track(self):
track = self.api.getTrack(103805726)
self.assertEqual(track.title, "Stronger")
def test_artist_albums(self):
self.api.getArtistAlbums(25022)
def test_album(self):
album = self.api.getAlbum(103805723)
self.assertEqual(album.title, "Graduation")
def test_album_items(self):
album_items = self.api.getAlbumItems(103805723, limit=10)
self.assertEqual(len(album_items.items), 10)
album_items = self.api.getAlbumItems(103805723, limit=10, offset=10)
self.assertEqual(len(album_items.items), 4)
def test_playlist(self):
playlist = self.api.getPlaylist("84974059-76af-406a-aede-ece2b78fa372")
self.assertEqual(playlist.title, "Kanye West Essentials")
def test_playlist_items(self):
playlist_items = self.api.getPlaylistItems(
"84974059-76af-406a-aede-ece2b78fa372"
)
self.assertEqual(len(playlist_items.items), 25)
def test_favorites(self):
favorites = self.api.getFavorites()
self.assertGreaterEqual(len(favorites.PLAYLIST), 0)
self.assertGreaterEqual(len(favorites.ALBUM), 0)
self.assertGreaterEqual(len(favorites.VIDEO), 0)
self.assertGreaterEqual(len(favorites.TRACK), 0)
self.assertGreaterEqual(len(favorites.ARTIST), 0)
def test_search(self):
self.api.search("Kanye West")
if __name__ == "__main__":
+9 -1
View File
@@ -13,6 +13,7 @@ from .types import (
Playlist,
PlaylistItems,
Favorites,
Search,
)
API_URL = "https://api.tidal.com/v1"
@@ -52,7 +53,7 @@ class TidalApi:
def getSession(self):
return SessionResponse(
**self._request(
f"sessions",
"sessions",
)
)
@@ -124,3 +125,10 @@ class TidalApi:
{"countryCode": self.country_code},
)
)
def search(self, query: str):
return Search(
**self._request(
"search", {"countryCode": self.country_code, "query": query}
)
)
+1
View File
@@ -2,6 +2,7 @@ from typing import TypedDict, Literal
from .api import *
from .track import *
from .search import *
TrackArg = Literal["low", "normal", "high", "master"]
+6 -6
View File
@@ -1,5 +1,5 @@
from pydantic import BaseModel
from typing import Optional, List, Literal
from typing import Optional, List, Literal, Dict
from .track import Track
@@ -46,7 +46,7 @@ class Album(BaseModel):
releaseDate: str
copyright: str
type: str
version: Optional[str]
version: Optional[str] = None
url: str
cover: Optional[str] = None
videoCover: Optional[str] = None
@@ -81,19 +81,19 @@ class Playlist(BaseModel):
title: str
numberOfTracks: int
numberOfVideos: int
creator: _Creator
description: str
creator: _Creator | Dict
description: Optional[str] = None
duration: int
lastUpdated: str
created: str
type: str
publicPlaylist: bool
url: str
image: str
image: Optional[str] = None
popularity: int
squareImage: str
promotedArtists: List[ArtistAlbum]
lastItemAddedAt: str
lastItemAddedAt: Optional[str] = None
class _PlaylistItem(BaseModel):
+127
View File
@@ -0,0 +1,127 @@
from pydantic import BaseModel
from typing import Optional, List, Literal, Dict, Union
from tiddl.types.track import Track
from tiddl.types.api import Items, Playlist
class _ArtistRole(BaseModel):
categoryId: int
category: Literal[
"Artist",
"Songwriter",
"Performer",
"Producer",
"Engineer",
"Production team",
"Misc",
]
class _ArtistMix(BaseModel):
ARTIST_MIX: str
class Artist(BaseModel):
id: int
name: str
artistTypes: Optional[List[Literal["ARTIST", "CONTRIBUTOR"]]] = None
url: Optional[str] = None
picture: Optional[str] = None
selectedAlbumCoverFallback: Optional[str] = None
popularity: Optional[int] = None
artistRoles: Optional[List[_ArtistRole]] = None
mixes: Optional[_ArtistMix | Dict] = None
class SearchAritsts(Items):
items: List[Artist]
class ArtistSearchAlbum(BaseModel):
id: int
name: str
type: Literal["MAIN", "FEATURED"]
picture: str
class SearchAlbum(BaseModel):
id: int
title: str
duration: int
streamReady: bool
streamStartDate: Optional[str] = None
allowStreaming: bool
premiumStreamingOnly: bool
numberOfTracks: int
numberOfVideos: int
numberOfVolumes: int
releaseDate: str
copyright: str
type: str
version: Optional[str] = None
url: str
cover: Optional[str] = None
videoCover: Optional[str] = None
explicit: bool
upc: str
popularity: int
audioQuality: str
audioModes: List[str]
artists: List[ArtistSearchAlbum | Dict]
class SearchAlbums(Items):
items: List[SearchAlbum]
class SearchPlaylists(Items):
items: List[Playlist]
class SearchTracks(Items):
items: List[Track]
class Video(BaseModel):
id: int
title: str
volumeNumber: int
trackNumber: int
releaseDate: str
imagePath: Optional[str] = None
imageId: str
vibrantColor: str
duration: int
quality: str
streamReady: bool
adSupportedStreamReady: bool
djReady: bool
stemReady: bool
streamStartDate: str
allowStreaming: bool
explicit: bool
popularity: int
type: str
adsUrl: Optional[str] = None
adsPrePaywallOnly: bool
artists: List[Artist]
album: Optional[str] = None
class SearchVideo(Items):
items: List[Video]
class TopHit(BaseModel):
value: Union[Artist, Track, Playlist, SearchAlbum]
type: Literal["ARTISTS", "TRACKS", "PLAYLISTS", "ALBUMS"]
class Search(BaseModel):
artists: SearchAritsts
albums: SearchAlbums
playlists: SearchPlaylists
tracks: SearchTracks
videos: SearchVideo
topHit: TopHit
+1 -1
View File
@@ -63,7 +63,7 @@ class Track(BaseModel):
audioQuality: str
audioModes: List[str]
mediaMetadata: Dict[str, List[str]]
artist: _Artist
artist: Optional[_Artist] = None
artists: List[_Artist]
album: _Album
mixes: Dict[str, str]