feat: add public index page with censored playlist and live reveals
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
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import pytest
|
||||
from ntr_fetcher.websocket import AnnounceManager
|
||||
from ntr_fetcher.websocket import AnnounceManager, PublicManager
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -98,3 +98,61 @@ async def test_status_broadcast_includes_clients(manager):
|
||||
assert msg["subscribers"] == 1
|
||||
assert len(msg["clients"]) == 1
|
||||
assert msg["clients"][0]["client_id"] == "my-bot"
|
||||
|
||||
|
||||
# --- PublicManager tests ---
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def public_manager():
|
||||
return PublicManager()
|
||||
|
||||
|
||||
def test_public_no_clients_initially(public_manager):
|
||||
assert public_manager.client_count == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_public_add_remove_client(public_manager):
|
||||
class FakeWS:
|
||||
async def send_json(self, data):
|
||||
pass
|
||||
|
||||
ws = FakeWS()
|
||||
public_manager.add_client(ws)
|
||||
assert public_manager.client_count == 1
|
||||
|
||||
public_manager.remove_client(ws)
|
||||
assert public_manager.client_count == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_public_broadcast(public_manager):
|
||||
received = []
|
||||
|
||||
class FakeWS:
|
||||
async def send_json(self, data):
|
||||
received.append(data)
|
||||
|
||||
ws1 = FakeWS()
|
||||
ws2 = FakeWS()
|
||||
public_manager.add_client(ws1)
|
||||
public_manager.add_client(ws2)
|
||||
|
||||
await public_manager.broadcast({"type": "reveal", "position": 1})
|
||||
assert len(received) == 2
|
||||
assert all(m["type"] == "reveal" for m in received)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_public_broadcast_removes_dead_clients(public_manager):
|
||||
class DeadWS:
|
||||
async def send_json(self, data):
|
||||
raise Exception("closed")
|
||||
|
||||
ws = DeadWS()
|
||||
public_manager.add_client(ws)
|
||||
assert public_manager.client_count == 1
|
||||
|
||||
await public_manager.broadcast({"type": "reveal", "position": 1})
|
||||
assert public_manager.client_count == 0
|
||||
|
||||
Reference in New Issue
Block a user