Public-facing page at / shows the current show's playlist with tracks
obscured until the admin marks them as announced. Tracks reveal in
real-time via a new unauthenticated /ws/public WebSocket. Server-side
censorship on /public/playlist strips track details from unannounced
items and sanitizes announced tracks to only expose frontend-needed
fields (no raw_json, track_id, etc). Past episodes are browsable with
fully revealed but sanitized tracklists.
Also fixes RuntimeError on backfill shutdown by closing the httpx
client on the same event loop that created it.
Made-with: Cursor
Add a persistent "announced" checkbox after each track's Announce button.
The state is stored in a new `announced` column on `show_tracks` and is
auto-set when the Announce button is pressed. The checkbox is also freely
togglable, and announced tracks have their Announce button disabled.
Also fixes .env leakage in test_config.py (pass _env_file=None) and adds
tests for the new DB method, API endpoint, and announce side-effect.
Made-with: Cursor
The dashboard's own WS connection was being counted as a bot subscriber,
causing "1 bot connected" with no bots actually present. Now WS clients
send a role ("bot" or "viewer") in the subscribe message. Only bots count
toward the subscriber total. Bot plugins also send a configurable client_id
so the dashboard shows which specific bots are connected.
Made-with: Cursor
- Login/logout/dashboard with HMAC-signed session cookies
- POST /admin/announce with session or bearer auth
- WS /ws/announce for subscribe/broadcast
- Static stubs: login.html, dashboard.html
Made-with: Cursor