Commit Graph

4 Commits

Author SHA1 Message Date
andrew e5d9c7f043 0.6: Spotify OAuth connect flow, AzuraCast base URL, fingerprint/buy-url fixes
- Add "Connect Spotify" OAuth flow (/connect/spotify) so newly created Spotify
  apps can read playlists: Spotify now requires a user token for playlist
  reads, which client-credentials alone can no longer provide. The stored
  refresh token is rendered as spotify-refresh into each playlist's sldl
  .conf -- sldl's own docs confirm supplying it skips its interactive login
  flow, which is what was causing multi-hour hangs on a stuck sync.
  Grandfathered apps keep working unchanged if no account is connected.
- Fix the connect flow's redirect_uri: request.url_for() reflected the raw
  connection scheme (http) rather than what the reverse proxy actually
  served over, which Spotify's exact-match redirect_uri check rejected.
  Force https rather than trust the unproxied scheme.
- Add an AzuraCast base URL credential field alongside the API key, with a
  keyfile fallback so the scheduled enrich-buy-url.py job can actually reach
  AzuraCast (previously it had no way to receive a base URL at all when run
  from the scheduler, so the reprocess call was silently always skipped).
- Fix build-fingerprint-index.py exiting non-zero on any single fingerprint
  failure instead of only when nothing was written.
- Guard enrich-buy-url.py's AzuraCast reprocess against an empty
  --azuracast-base (raised ValueError since PD2 removed the hardcoded base).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 11:16:55 -06:00
andrew 543f10e662 R7: extract the M3U regeneration into a shared sourced helper
run-playlist.sh and import-track.sh had the same beets->#EXTM3U block, but
import-track.sh wrote the file non-atomically. Move it to pipeline/lib/m3u.sh
as regen_m3u <name> <out>, sourced by both. The helper always writes atomically
(temp + rename), so a reader like Navidrome never sees a partial file and a
stray wrong-owner leftover .m3u8 is replaced without a chown. Returns 0 always
(empty result is a warning), so it's safe as a standalone call under set -e.

Verified: tests/test_m3u.py (atomic write with tracks, no file when empty; 44
tests green) plus a live regen against the real library (techno -> 229 tracks,
no temp leftover).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-10 16:16:09 -06:00
andrew 69804a9eb2 Fix M3U write permission failure; add recently-downloaded section to dashboard
Playlist M3U regen now writes to a temp file and renames it into place,
so a stray wrong-owner leftover file (root:root, from pre-migration
host-cron runs) can't block nightly writes the way it did last night.
Dashboard now lists tracks added to the beets library in the last 24h
with playlist and format, sourced from a new beets_service.recently_added().
2026-07-09 08:35:46 -06:00
andrew 68cb007e4c Stage 0: migrate pipeline scripts from /opt/sldl, scaffold repo
Moves all ~30 pipeline scripts, configs, and the vendored sldl binary into
this repo (source /opt/sldl left untouched). Removes all docker exec/docker
compose dependencies now that beets and sldl run in-process/as a subprocess
of this container instead of via soulbeet/on-demand sldl containers.
Replaces hardcoded host paths, Navidrome credentials, and Spotify credential
sourcing with env-var-driven paths and shared credential loaders. Adds
Dockerfile, entrypoint.sh, requirements.txt, docker-compose.snippet.yml, and
the initial app DB schema.
2026-07-08 13:10:55 -06:00