diff --git a/core/itunes_client.py b/core/itunes_client.py index 25f9c73a..0d34b6db 100644 --- a/core/itunes_client.py +++ b/core/itunes_client.py @@ -741,7 +741,9 @@ class iTunesClient: if cached and cached.get('items'): return cached - results = self._lookup(id=album_id, entity='song') + # #918: the iTunes Lookup API returns only 50 related entities unless `limit` is + # passed (max 200), so albums >50 tracks were truncated in the download window. + results = self._lookup(id=album_id, entity='song', limit=200) if not results: return None @@ -763,7 +765,7 @@ class iTunesClient: try: fb_results = self.session.get( self.LOOKUP_URL, - params={'id': album_id, 'entity': 'song', 'country': fallback}, + params={'id': album_id, 'entity': 'song', 'country': fallback, 'limit': 200}, # #918 timeout=15 ) if fb_results.status_code == 200: diff --git a/tests/test_itunes_album_tracks_limit.py b/tests/test_itunes_album_tracks_limit.py new file mode 100644 index 00000000..1fa36e40 --- /dev/null +++ b/tests/test_itunes_album_tracks_limit.py @@ -0,0 +1,46 @@ +"""iTunes album-track fetch must request the full album, not the 50-entity default (#918). + +The iTunes Lookup API returns only 50 related entities unless `limit` is passed (max 200), +so albums >50 tracks were truncated to the first 50 in the download window. get_album_tracks +must pass limit=200. +""" + +from __future__ import annotations + +from core import itunes_client as ic + + +class _Cache: + """Cache stub: always a miss; any write method is a no-op.""" + def get_entity(self, *a, **k): + return None + + def __getattr__(self, _name): + return lambda *a, **k: None + + +_RESULTS = [ + {'wrapperType': 'collection', 'collectionId': 123, 'collectionName': 'Big OST', + 'artistName': 'Composer', 'trackCount': 70, 'artworkUrl100': 'http://x/100x100bb.jpg'}, + {'wrapperType': 'track', 'kind': 'song', 'trackId': 1, 'trackName': 'Track 1', + 'trackNumber': 1, 'discNumber': 1, 'artistName': 'Composer', 'trackTimeMillis': 1000}, +] + + +def test_get_album_tracks_requests_limit_200(monkeypatch): + client = ic.iTunesClient(country='US') + captured = {} + + def fake_lookup(**params): + captured.update(params) + return _RESULTS + + monkeypatch.setattr(client, '_lookup', fake_lookup) + monkeypatch.setattr(ic, 'get_metadata_cache', lambda: _Cache()) + + result = client.get_album_tracks('123') + + assert captured.get('limit') == 200 # #918: full album, not the iTunes 50 default + assert captured.get('entity') == 'song' + assert captured.get('id') == '123' + assert result is not None