fix: album track wrapping + try multiple Song() call patterns for tracks

- Album: wrap item.get('track') as {itemV2: ...} so _parse_track navigates trackUnion correctly
- Track: try get_song_info(url) then get_song_info(); log Song/Public methods on failure

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-13 01:15:43 +02:00
1 parent bbe4412f42
commit 5d0c5ec6eb
1 file changed
+24 -7
+24 -7
View File
@@ -64,10 +64,26 @@ def resolve(sp_type, sp_id):
url = f'https://open.spotify.com/{sp_type}/{sp_id}'
if sp_type == 'track':
# Song requires a client instance as first arg; Public() is the unauthenticated client
public = sp_mod.Public()
song = sp_mod.Song(public, url)
raw = song.get_song_info()
# Song(url) stores url as the client object, then get_song_info() or init
# tries to call url.login which fails. Try: Song(url) + get_song_info(url),
# then Song(url) + get_song_info(), log methods as last resort.
song = sp_mod.Song(url)
song_methods = [m for m in dir(song) if not m.startswith('_')]
eprint(f'[spotapi] Song methods: {song_methods}')
raw = None
for attempt in [
lambda: song.get_song_info(url),
lambda: song.get_song_info(),
]:
try:
raw = attempt()
break
except Exception as e:
eprint(f'[spotapi] track attempt failed: {type(e).__name__}: {e}')
if raw is None:
pub = sp_mod.Public()
eprint(f'[spotapi] Public methods: {[m for m in dir(pub) if not m.startswith("_")]}')
raise Exception('Song resolution: all attempts failed')
eprint(f'[spotapi] track raw type={type(raw).__name__} keys={list(raw.keys()) if isinstance(raw, dict) else "?"}')
if isinstance(raw, dict):
for k, v in raw.items():
@@ -113,10 +129,11 @@ def resolve(sp_type, sp_id):
art = cover_items[0].get('url', '') if cover_items else ''
# tracks
raw_tracks = (au.get('tracks') or {}).get('items') or []
# album track items look like {uid, track: {data: {trackUnion: {...}}}}
# album track items: {uid, track: {__typename, data: {trackUnion: {...}}}}
# wrap as {itemV2: track_obj} so _parse_track can navigate itemV2.data.trackUnion
def _alb_track(item):
inner = item.get('track') or item
return _parse_track(inner,
track_obj = item.get('track') or item
return _parse_track({'itemV2': track_obj},
default_album=name, default_art=art,
default_artist=artist)
tracks = [t for t in (_alb_track(i) for i in raw_tracks) if t]