soulsync/core/exports
BoulderBadgeDad fb9d88ea6a #903: playlist export to ListenBrainz — pure cores (JSPF builder + MBID resolver)
Phase 1 of exporting mirrored playlists to ListenBrainz. Two pure, fully-tested seams,
zero runtime wiring yet (additive, no regression):

- core/exports/jspf_export.py: build_jspf(title, tracks) -> ({"playlist": {...}}, summary).
  LB's POST /1/playlist/create requires every track to carry a string identifier
  'https://musicbrainz.org/recording/<mbid>' (text-only tracks are rejected), so tracks
  without a valid recording-MBID UUID are dropped and counted in the coverage summary.
- core/exports/mbid_resolver.py: resolve_recording_mbid(artist, title, sources) — the
  cheapest-first waterfall (cache -> DB -> file tag -> MusicBrainz) as a pure function over
  injected (label, fn) sources. Short-circuits expensive lookups, treats a raising source
  as a miss (one flaky MB call can't fail the export), reports the resolving source label.

API spec confirmed against LB docs: POST /1/playlist/create, 'Authorization: Token <t>',
{"playlist": {"title", "track": [{"identifier": "<mb recording url>", title, creator, album}]}}.

13 tests.
2026-06-22 20:25:44 -07:00
..
__init__.py Watchlist: export the roster to JSON / CSV / text (corruption's request) 2026-06-11 22:48:58 -07:00
artist_export.py Library export: export the whole library roster too (corruption's request) 2026-06-11 22:59:21 -07:00
jspf_export.py #903: playlist export to ListenBrainz — pure cores (JSPF builder + MBID resolver) 2026-06-22 20:25:44 -07:00
mbid_resolver.py #903: playlist export to ListenBrainz — pure cores (JSPF builder + MBID resolver) 2026-06-22 20:25:44 -07:00