Added mix downloading

This commit is contained in:
Oskar Dudziński
2025-09-29 19:45:05 +02:00
parent 0c53783497
commit 12a2d4cf5f
5 changed files with 51 additions and 2 deletions
+6
View File
@@ -17,6 +17,12 @@ class TestTidalResource(unittest.TestCase):
("playlist/12345678", "playlist", "12345678"),
("https://tidal.com/browse/artist/12345678", "artist", "12345678"),
("artist/12345678", "artist", "12345678"),
(
"https://tidal.com/browse/mix/f93b015796bf93b015796b",
"mix",
"f93b015796bf93b015796b",
),
("mix/f93b015796bf93b015796b", "mix", "f93b015796bf93b015796b"),
]
for resource, expected_type, expected_id in positive_cases:
+19
View File
@@ -27,6 +27,7 @@ from tiddl.models.api import (
Video,
VideoStream,
Lyrics,
MixItems,
)
from tiddl.models.constants import TrackQuality
@@ -53,6 +54,7 @@ class Limits:
ALBUM_ITEMS = 10
ALBUM_ITEMS_MAX = 100
PLAYLIST = 50
MIX_ITEMS = 100
class TidalApi:
@@ -175,6 +177,23 @@ class TidalApi:
expire_after=3600,
)
def getMix(
self,
mix_id: str | int,
limit=LIMITS.MIX_ITEMS,
offset=0,
):
return self.fetch(
MixItems,
f"mixes/{mix_id}/items",
{
"countryCode": self.country_code,
"limit": limit,
"offset": offset,
},
expire_after=3600,
)
def getFavorites(self):
return self.fetch(
Favorites,
+10
View File
@@ -405,6 +405,16 @@ def DownloadCommand(
downloadAlbum(album)
case "mix":
mix = api.getMix(resource.id)
for mix_item in mix.items:
filename = formatResource(
TEMPLATE or ctx.obj.config.template.track, mix_item.item
)
submitItem(mix_item.item, filename)
case "artist":
artist = api.getArtist(resource.id)
logging.info(f"Artist {artist.name!r}")
+7
View File
@@ -102,6 +102,13 @@ class PlaylistItems(Items):
items: List[Union[PlaylistTrackItem, PlaylistVideoItem]]
class MixItems(Items):
class MixItem(BaseModel):
item: Track
type: ItemType = "track"
items: List[MixItem]
class Favorites(BaseModel):
PLAYLIST: List[str]
ALBUM: List[str]
+9 -2
View File
@@ -14,7 +14,7 @@ from typing import Literal, Union, get_args
from tiddl.models.constants import TrackQuality, QUALITY_TO_ARG
from tiddl.models.resource import Track, Video
ResourceTypeLiteral = Literal["track", "video", "album", "playlist", "artist"]
ResourceTypeLiteral = Literal["track", "video", "album", "playlist", "artist", "mix"]
class TidalResource(BaseModel):
@@ -41,7 +41,14 @@ class TidalResource(BaseModel):
if resource_type not in get_args(ResourceTypeLiteral):
raise ValueError(f"Invalid resource type: {resource_type}")
if not resource_id.isdigit() and resource_type != "playlist":
digit_resource_types: list[ResourceTypeLiteral] = [
"track",
"album",
"video",
"artist",
]
if resource_type in digit_resource_types and not resource_id.isdigit():
raise ValueError(f"Invalid resource id: {resource_id}")
return cls(type=resource_type, id=resource_id) # type: ignore