soulsync/core/discovery
Broque Thomas 718eb0cb10 Add iTunes / Apple Music link import tab on Sync page
New iTunes Link tab between Deezer Link and YouTube. Accepts album,
track, and playlist URLs from music.apple.com / iTunes. Pulls the
tracklist, runs it through the same discovery -> sync -> download
pipeline as the other link tabs.

Apple Music playlists go through amp-api with a Bearer JWT scraped
from the SPA. The legacy meta-tag and inline `"token":"..."` paths
are gone in the current music.apple.com SPA, so the extractor now
walks the page's `<script src>` list (prioritising index/chunk/main
bundles), fetches up to 8 JS bundles, regex-matches JWT-shaped
strings, and base64-decodes each payload to confirm it carries
Apple media-api claims (`root_https_origin`, or `iss + iat + exp`)
before trusting it. Filters out analytics / error-reporter JWTs that
also ship in the bundle.

Tokens are cached at module scope for 6h behind a threading.Lock so
the three-worker discovery executor doesn't thunder-herd Apple on
cold start, and amp-api calls go through a single helper that on
401 invalidates the cache, refetches the page, force-refreshes the
token, and retries the request once. The playlist fetcher memoises
the page HTML for the cache-miss path so we don't refetch it for
every paginated `/tracks` page.

spotify_public discovery worker accepts the new platform shape so
iTunes Link reuses the same matching code path as Deezer Link and
Spotify-public. UI bits live in the sync-services.js iTunes Link
tab, with platform plumbing through wishlist-tools.js for the
multi-source state map.
2026-05-25 22:32:18 -07:00
..
__init__.py PR5a: lift _run_sync_task to core/discovery/sync.py 2026-04-28 11:20:47 -07:00
beatport.py PR5f: lift _run_beatport_discovery_worker to core/discovery/beatport.py 2026-04-28 15:36:15 -07:00
deezer.py PR5d: lift _run_deezer_discovery_worker to core/discovery/deezer.py 2026-04-28 12:45:18 -07:00
hero.py Add MusicBrainz as a metadata source 2026-05-18 18:47:13 -07:00
listenbrainz.py PR5g: lift _run_listenbrainz_discovery_worker to core/discovery/listenbrainz.py 2026-04-28 16:09:02 -07:00
playlist.py Surface silent exceptions in watchlist + discovery + reorganize — 18 sites 2026-05-07 09:52:20 -07:00
qobuz.py Add Qobuz playlist sync to Sync page (#677) 2026-05-23 23:27:36 -07:00
quality_scanner.py Surface silent exceptions across remaining modules — ~70 sites 2026-05-07 10:28:58 -07:00
scoring.py Lift discovery scoring + tidal-track search to core/discovery/scoring.py 2026-04-30 09:08:47 -07:00
spotify_public.py Add iTunes / Apple Music link import tab on Sync page 2026-05-25 22:32:18 -07:00
sync.py Token leak round 2: artist endpoint + playlist sync + URL-encoded redaction 2026-05-15 09:33:15 -07:00
tidal.py Lift _run_tidal_discovery_worker to core/discovery/tidal.py 2026-04-28 23:02:24 -07:00
youtube.py fix: cast duration_ms to int before :02d format in discovery workers 2026-04-28 12:07:54 -07:00