Fetch all Qobuz favorite tracks for discovery
Remove the implicit 500-track cap from Qobuz Favorite Tracks so the Sync page discovers the same number of tracks shown on the playlist card. Keep an explicit limit parameter for callers that want a capped fetch. Add tests covering the default full-pagination behavior and explicit limit handling.
This commit is contained in:
parent
3c0b6c6204
commit
9769d8be19
2 changed files with 66 additions and 4 deletions
|
|
@ -887,11 +887,14 @@ class QobuzClient(DownloadSourcePlugin):
|
|||
logger.info(f"Retrieved Qobuz playlist '{normalized['name']}' with {len(tracks)} tracks")
|
||||
return normalized
|
||||
|
||||
def get_user_favorite_tracks(self, limit: int = 500) -> List[Dict[str, Any]]:
|
||||
def get_user_favorite_tracks(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
|
||||
"""Fetch the authenticated user's favorited tracks.
|
||||
|
||||
Mirrors ``TidalClient.get_collection_tracks`` — the Sync page's
|
||||
Favorite Tracks card pulls from here on click.
|
||||
Favorite Tracks card pulls from here on click. By default this
|
||||
fetches the full favorites collection so the card count and the
|
||||
discovered track list cannot silently diverge. Pass ``limit`` for
|
||||
explicit capped callers.
|
||||
"""
|
||||
if not self.is_authenticated():
|
||||
logger.warning("Qobuz not authenticated — cannot list favorite tracks")
|
||||
|
|
@ -899,8 +902,11 @@ class QobuzClient(DownloadSourcePlugin):
|
|||
|
||||
tracks: List[Dict[str, Any]] = []
|
||||
offset = 0
|
||||
while len(tracks) < limit:
|
||||
page_size = min(self._PLAYLIST_PAGE_SIZE, limit - len(tracks))
|
||||
while True:
|
||||
page_size = self._PLAYLIST_PAGE_SIZE if limit is None else min(self._PLAYLIST_PAGE_SIZE, limit - len(tracks))
|
||||
if page_size <= 0:
|
||||
break
|
||||
|
||||
data = self._api_request('favorite/getUserFavorites', {
|
||||
'type': 'tracks',
|
||||
'limit': page_size,
|
||||
|
|
@ -924,6 +930,8 @@ class QobuzClient(DownloadSourcePlugin):
|
|||
offset += len(items)
|
||||
if offset >= total or len(items) < page_size:
|
||||
break
|
||||
if limit is not None and len(tracks) >= limit:
|
||||
break
|
||||
|
||||
logger.info(f"Retrieved {len(tracks)} Qobuz favorite tracks")
|
||||
return tracks
|
||||
|
|
|
|||
|
|
@ -331,6 +331,60 @@ def test_get_user_favorite_tracks_paginates(authed_client):
|
|||
assert tracks[-1]['name'] == 'F129'
|
||||
|
||||
|
||||
def test_get_user_favorite_tracks_fetches_all_by_default(authed_client):
|
||||
def make_items(start, count):
|
||||
return [
|
||||
{'id': start + i, 'title': f'F{start + i}', 'duration': 200,
|
||||
'performer': {'name': 'Fav Artist'},
|
||||
'album': {'title': 'Fav Album', 'image': {}}}
|
||||
for i in range(count)
|
||||
]
|
||||
|
||||
offsets: List[int] = []
|
||||
|
||||
def responder(endpoint, params=None):
|
||||
assert endpoint == 'favorite/getUserFavorites'
|
||||
offsets.append(params['offset'])
|
||||
start = params['offset']
|
||||
remaining = max(0, 625 - start)
|
||||
return {'tracks': {'items': make_items(start, min(params['limit'], remaining)), 'total': 625}}
|
||||
|
||||
_install_api_responder(authed_client, responder)
|
||||
tracks = authed_client.get_user_favorite_tracks()
|
||||
|
||||
assert len(tracks) == 625
|
||||
assert offsets == [0, 100, 200, 300, 400, 500, 600]
|
||||
assert tracks[-1]['name'] == 'F624'
|
||||
|
||||
|
||||
def test_get_user_favorite_tracks_honors_explicit_limit(authed_client):
|
||||
def make_items(start, count):
|
||||
return [
|
||||
{'id': start + i, 'title': f'F{start + i}', 'duration': 200,
|
||||
'performer': {'name': 'Fav Artist'},
|
||||
'album': {'title': 'Fav Album', 'image': {}}}
|
||||
for i in range(count)
|
||||
]
|
||||
|
||||
requests: List[Dict[str, Any]] = []
|
||||
|
||||
def responder(endpoint, params=None):
|
||||
assert endpoint == 'favorite/getUserFavorites'
|
||||
requests.append(dict(params))
|
||||
start = params['offset']
|
||||
return {'tracks': {'items': make_items(start, params['limit']), 'total': 625}}
|
||||
|
||||
_install_api_responder(authed_client, responder)
|
||||
tracks = authed_client.get_user_favorite_tracks(limit=150)
|
||||
|
||||
assert len(tracks) == 150
|
||||
assert requests == [
|
||||
{'type': 'tracks', 'limit': 100, 'offset': 0},
|
||||
{'type': 'tracks', 'limit': 50, 'offset': 100},
|
||||
]
|
||||
assert tracks[-1]['name'] == 'F149'
|
||||
|
||||
|
||||
def test_get_user_favorite_tracks_count_uses_cheap_call(authed_client):
|
||||
captured: Dict[str, Any] = {}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue