diff --git a/data/published_messages.txt b/data/published_messages.txt index 75059a8..c3f9a00 100644 --- a/data/published_messages.txt +++ b/data/published_messages.txt @@ -34,3 +34,13 @@ message-1f762ea6-bc6c-4d60-a264-c7342db1eb4a message-12fa40e5-46bf-49aa-a9ff-3ebb41b18bb3 message-4d2cae90-5700-44b9-bd02-299225dfbace message-4d2cae90-5700-44b9-bd02-299225dfbace +message-87d28f17-fd1a-409a-b041-fde81a6c3a71 +message-fc0bdf65-5fc1-4b4f-bcb2-95f9effe6f69 +message-c444717f-cdd7-4b89-8540-8c0d5f12de84 +message-c444717f-cdd7-4b89-8540-8c0d5f12de84 +message-6faf13a3-8132-4a3f-aaff-1918e48d57af +message-bf56e47f-467b-4873-8723-dec71152007a +message-267f01b7-6b2b-441c-b569-c63f531dd76f +message-aa23e074-66cd-4811-858a-a0e52e5e94b0 +message-1d731b79-6f43-426f-9b3a-47af7a0b11e1 +message-1d731b79-6f43-426f-9b3a-47af7a0b11e1 diff --git a/docs/livestream.html b/docs/livestream.html index 409c0ba..de52ce0 100644 --- a/docs/livestream.html +++ b/docs/livestream.html @@ -156,6 +156,7 @@ }; let recordCount = 0; + const seenUris = new Set(); function formatTime(dateStr) { const date = new Date(dateStr); @@ -201,39 +202,54 @@ document.getElementById('count').textContent = recordCount; } - // Track seen record URIs to avoid duplicates - const seenUris = new Set(); + let ws = null; - async function poll() { + function connect() { const statusEl = document.getElementById('status'); - statusEl.textContent = 'Polling for updates...'; - statusEl.className = 'status connected'; + statusEl.textContent = 'Connecting to Jetstream...'; + statusEl.className = 'status connecting'; - const pds = 'https://comind.network'; + // Connect to Jetstream filtered by DID only + // Filter collections client-side + ws = new WebSocket(`wss://jetstream2.us-east.bsky.network/subscribe?wantedDids=${DID}`); - for (const [collection, type] of Object.entries(COLLECTIONS)) { + ws.onopen = () => { + statusEl.textContent = 'Connected - Live'; + statusEl.className = 'status connected'; + }; + + ws.onmessage = (event) => { try { - const resp = await fetch( - `${pds}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=${collection}&limit=10` - ); - const data = await resp.json(); + const data = JSON.parse(event.data); - if (data.records) { - // Process newest first - for (const r of data.records) { - if (!seenUris.has(r.uri)) { - seenUris.add(r.uri); - addRecord(type, r.value); - } + if (data.kind === 'commit' && data.commit) { + const collection = data.commit.collection; + const type = COLLECTIONS[collection]; + + // Build URI for dedup + const uri = `at://${data.did}/${collection}/${data.commit.rkey}`; + + if (type && data.commit.record && !seenUris.has(uri)) { + seenUris.add(uri); + addRecord(type, data.commit.record); } } } catch (e) { - console.error(`Failed to poll ${collection}:`, e); + console.error('Parse error:', e); } - } + }; + + ws.onerror = (error) => { + console.error('WebSocket error:', error); + statusEl.textContent = 'Connection error - retrying...'; + statusEl.className = 'status'; + }; - // Poll every 5 seconds - setTimeout(poll, 5000); + ws.onclose = () => { + statusEl.textContent = 'Disconnected - Reconnecting...'; + statusEl.className = 'status'; + setTimeout(connect, 3000); + }; } // Load recent records on startup @@ -260,12 +276,8 @@ } } - // Start with initial load, then poll - loadRecent().then(() => { - document.getElementById('status').textContent = 'Live - Polling every 5s'; - document.getElementById('status').className = 'status connected'; - setTimeout(poll, 5000); - }); + // Load recent records, then connect to Jetstream + loadRecent().then(() => connect());