fix: parse spotapi playlist response structure (data.playlistV2.content.items)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-12 23:17:03 +02:00
1 parent 575ca385fd
commit 7b5928f809
1 file changed
+26 -15
+26 -15
View File
@@ -105,20 +105,32 @@ def resolve(sp_type, sp_id):
if not cls_name: if not cls_name:
raise Exception(f'spotapi has no playlist class (available: {available})') raise Exception(f'spotapi has no playlist class (available: {available})')
pl = getattr(sp_mod, cls_name)(url) pl = getattr(sp_mod, cls_name)(url)
pl_meta = pl.get_playlist_info(limit=1)
eprint(f'[spotapi] playlist first-page type={type(pl_meta).__name__}') def _pl_items(page):
"""Extract items list from partner API response: data.playlistV2.content.items"""
if isinstance(page, list): return page
d = page.get('data') or {}
pl2 = d.get('playlistV2') or {}
content = pl2.get('content') or {}
return content.get('items') or page.get('items') or page.get('tracks') or []
def _pl_meta(page):
"""Extract playlist metadata from partner API response"""
if not isinstance(page, dict): return {}, {}, []
d = page.get('data') or {}
pl2 = d.get('playlistV2') or {}
attrs = pl2.get('attributes') or pl2
owner_obj = pl2.get('ownerV2') or pl2.get('owner') or {}
owner_data = owner_obj.get('data') or owner_obj
imgs = (pl2.get('images') or {}).get('items') or []
return attrs, owner_data, imgs
tracks, skipped, offset = [], 0, 0 tracks, skipped, offset = [], 0, 0
first_page = None
while True: while True:
page = pl.get_playlist_info(limit=100, offset=offset) page = pl.get_playlist_info(limit=100, offset=offset)
if offset == 0: if first_page is None: first_page = page
eprint(f'[spotapi] page0 type={type(page).__name__} keys={list(page.keys()) if isinstance(page, dict) else "list"}') items = _pl_items(page)
if isinstance(page, dict):
for k, v in page.items():
eprint(f'[spotapi] page0[{k!r}] = {type(v).__name__} {repr(v)[:120]}')
elif isinstance(page, list) and page:
eprint(f'[spotapi] page0[0] = {repr(page[0])[:200]}')
items = page if isinstance(page, list) else (page.get('items') or page.get('tracks') or [])
if not items: break if not items: break
for item in items: for item in items:
typename = (item.get('itemV2') or {}).get('data', {}).get('__typename', '') typename = (item.get('itemV2') or {}).get('data', {}).get('__typename', '')
@@ -130,11 +142,10 @@ def resolve(sp_type, sp_id):
offset += len(items) offset += len(items)
time.sleep(0.3) time.sleep(0.3)
name = owner = art = '' attrs, owner_data, imgs = _pl_meta(first_page or {})
if isinstance(pl_meta, dict): name = attrs.get('name', '') or attrs.get('title', '')
name = pl_meta.get('name', '') owner = owner_data.get('name', '') or owner_data.get('displayName', '')
owner = pl_meta.get('owner', '') or pl_meta.get('owner_name', '') art = imgs[0].get('url', '') if imgs else ''
art = pl_meta.get('image', '') or pl_meta.get('cover', '')
eprint(f'[spotapi] playlist ok — {len(tracks)} tracks') eprint(f'[spotapi] playlist ok — {len(tracks)} tracks')
return {'type': 'playlist', 'name': name, 'artist': owner, return {'type': 'playlist', 'name': name, 'artist': owner,