feat: add now-playing API for teal.fm/Piper integration (#416)
* feat: add now-playing API for teal.fm/Piper integration
exposes real-time playback state for external scrobbler services.
backend:
- NowPlayingService with TTL cache (5 min expiry) for ephemeral state
- POST /now-playing/ - frontend reports playback state
- DELETE /now-playing/ - clear state on stop
- GET /now-playing/by-handle/{handle} - public endpoint for Piper
- GET /now-playing/by-did/{did} - alternative by DID
- returns 204 when nothing playing (matches Spotify pattern)
- response format compatible with Piper's expectations
frontend:
- now-playing.svelte.ts service with throttling/debouncing
- reports every 10s during playback, debounced for seeks
- integrated into Player.svelte effects
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use cookie-based auth check in now-playing service
auth is cookie-based (HttpOnly), not localStorage. the localStorage.getItem('session_id')
check was leftover dead code that always failed, preventing now-playing from reporting.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: use latest state in debounced now-playing reports
when pause events were debounced, the scheduled report used stale values
captured at schedule time instead of the latest state. now stores pending
state separately so the timer always fires with current values.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
authored by
zzstoatzz.io