Chess on the ATmosphere
checkmate.blue
chess
1import { createWriteStream } from 'fs';
2import { join, dirname } from 'path';
3import { fileURLToPath } from 'url';
4import { mkdir } from 'fs/promises';
5
6const JETSTREAM_URL = 'wss://jetstream2.us-east.bsky.network/subscribe';
7const COLLECTION = 'blue.checkmate.game';
8
9const __dirname = dirname(fileURLToPath(import.meta.url));
10const logDir = join(__dirname, '..', 'data');
11const logFile = join(logDir, 'players.log');
12
13await mkdir(logDir, { recursive: true });
14const stream = createWriteStream(logFile, { flags: 'a' });
15
16let cursor: number | null = null;
17let reconnectAttempts = 0;
18
19function connect() {
20 const url = new URL(JETSTREAM_URL);
21 url.searchParams.set('wantedCollections', COLLECTION);
22 if (cursor) url.searchParams.set('cursor', String(cursor));
23
24 console.log(`[firehose] connecting...${cursor ? ` (cursor: ${cursor})` : ''}`);
25 const ws = new WebSocket(url.toString());
26
27 ws.onopen = () => {
28 console.log('[firehose] connected');
29 reconnectAttempts = 0;
30 };
31
32 ws.onmessage = (event) => {
33 const data = JSON.parse(String(event.data));
34 if (data.time_us) cursor = data.time_us;
35 if (data.kind !== 'commit') return;
36 if (data.commit.collection !== COLLECTION) return;
37
38 stream.write(data.did + '\n');
39 };
40
41 ws.onclose = (event: CloseEvent) => {
42 console.log(`[firehose] disconnected: ${event.code} ${event.reason}`);
43 const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30_000);
44 reconnectAttempts++;
45 console.log(`[firehose] reconnecting in ${delay}ms...`);
46 setTimeout(connect, delay);
47 };
48
49 ws.onerror = () => {
50 ws.close();
51 };
52}
53
54console.log(`[firehose] logging DIDs to ${logFile}`);
55connect();