diff --git a/README.md b/README.md index d1240bf..2dce02d 100644 --- a/README.md +++ b/README.md @@ -333,7 +333,7 @@ The system will: ## Bot Integration -For integrating external bots (e.g., for live voting and game notifications), see **[BOT_INTEGRATION.md](BOT_INTEGRATION.md)** for detailed documentation including: +For integrating external bots (e.g., for live voting and game notifications), see **[BOT_INTEGRATION.md](docs/BOT_INTEGRATION.md)** for detailed documentation including: - Live voting API usage - **WebSocket integration (recommended)** for real-time game notifications diff --git a/API_QUICK_REFERENCE.md b/docs/API_QUICK_REFERENCE.md similarity index 100% rename from API_QUICK_REFERENCE.md rename to docs/API_QUICK_REFERENCE.md diff --git a/BOT_INTEGRATION.md b/docs/BOT_INTEGRATION.md similarity index 82% rename from BOT_INTEGRATION.md rename to docs/BOT_INTEGRATION.md index 349a165..aa324a5 100644 --- a/BOT_INTEGRATION.md +++ b/docs/BOT_INTEGRATION.md @@ -10,6 +10,7 @@ This guide explains how to integrate your bot with the Jackbox Game Picker API f - [Webhook Integration](#webhook-integration) 3. [Webhook Management](#webhook-management) 4. [Testing](#testing) +5. [Available Events](#available-events) --- @@ -219,11 +220,64 @@ All messages are JSON-formatted. "pack_name": "The Jackbox Party Pack 9", "min_players": 2, "max_players": 8, - "manually_added": false + "manually_added": false, + "room_code": "JYET" } } } +// Session started event (broadcast to all authenticated clients) +{ + "type": "session.started", + "timestamp": "2025-11-01T20:00:00Z", + "data": { + "session": { + "id": 123, + "is_active": true, + "created_at": "2025-11-01T20:00:00Z", + "notes": "Friday game night" + } + } +} + +// Session ended event (broadcast to session subscribers) +{ + "type": "session.ended", + "timestamp": "2025-11-01T23:00:00Z", + "data": { + "session": { + "id": 123, + "is_active": false, + "games_played": 8 + } + } +} + +// Game started event (broadcast to session subscribers) +// Fired when the Jackbox room becomes locked, meaning gameplay has begun +{ + "type": "game.started", + "timestamp": "2025-11-01T20:31:00Z", + "data": { + "sessionId": 123, + "gameId": 456, + "roomCode": "JYET", + "maxPlayers": 8 + } +} + +// Audience joined event (broadcast to session subscribers) +// Confirms the app successfully joined a Jackbox room as an audience member +{ + "type": "audience.joined", + "timestamp": "2025-11-01T20:31:05Z", + "data": { + "sessionId": 123, + "gameId": 456, + "roomCode": "JYET" + } +} + // Heartbeat response { "type": "pong" @@ -319,9 +373,14 @@ class JackboxWebSocketClient { handleGameAdded(data) { const { game } = data; - const announcement = `🎮 Coming up next: ${game.title}!`; - // Send to your chat platform + // Build announcement with room code if available + let announcement = `🎮 Coming up next: ${game.title}!`; + if (game.room_code) { + announcement += ` Join at jackbox.tv with code: ${game.room_code}`; + } + + // Send to your chat platform (e.g., Kosmi chat) this.broadcastToChat(announcement); } @@ -395,12 +454,15 @@ Triggered whenever a game is added to an active session (either via picker or ma "pack_name": "The Jackbox Party Pack 9", "min_players": 2, "max_players": 8, - "manually_added": false + "manually_added": false, + "room_code": "JYET" } } } ``` +> **Note:** `room_code` is the 4-character Jackbox room code (e.g. `"JYET"`). It will be `null` if no room code was provided when the game was added. + ### Webhook Headers The API sends the following headers with each webhook: @@ -481,10 +543,16 @@ app.post('/webhook/jackbox', (req, res) => { if (req.body.event === 'game.added') { const game = req.body.data.game; - // Send message to Kosmi chat - sendKosmiMessage(`🎮 Coming up next: ${game.title}!`); + // Build announcement with room code if available + let message = `🎮 Coming up next: ${game.title}!`; + if (game.room_code) { + message += ` Join at jackbox.tv with code: ${game.room_code}`; + } - console.log(`Announced game: ${game.title} from ${game.pack_name}`); + // Send message to Kosmi chat + sendKosmiMessage(message); + + console.log(`Announced game: ${game.title} from ${game.pack_name} (code: ${game.room_code || 'N/A'})`); } // Always respond with 200 OK @@ -616,11 +684,22 @@ curl -X GET "http://localhost:5000/api/webhooks/1/logs" \ ## Available Events -Currently supported webhook events: +### Webhook Events -- `game.added` - Triggered when a game is added to an active session +- `game.added` - Triggered when a game is added to an active session. Includes `room_code` (the 4-character Jackbox join code) if one was provided. -More events may be added in the future (e.g., `session.started`, `session.ended`, `vote.recorded`). +### WebSocket Events + +- `game.added` - Triggered when a game is added to an active session. Sent to clients subscribed to that session. Includes `room_code`. +- `session.started` - Triggered when a new session is created. Broadcast to **all** authenticated clients (no subscription required). +- `session.ended` - Triggered when a session is closed. Sent to clients subscribed to that session. +- `game.started` - Triggered when the Jackbox room becomes locked (gameplay has begun). Detected by polling the Jackbox REST API every 10 seconds. Sent to clients subscribed to that session. Includes `roomCode` and `maxPlayers`. +- `audience.joined` - Triggered when the app successfully joins a Jackbox room as an audience member. Sent to clients subscribed to that session. This confirms the room code is valid and the game is being monitored. +- `player-count.updated` - Triggered when the player count for a game is updated. Sent to clients subscribed to that session. + +> **Tip:** To receive `session.started` events, your bot only needs to authenticate — no subscription is needed. Once you receive a `session.started` event, subscribe to the new session ID to receive `game.added` and `session.ended` events for it. + +More events may be added in the future (e.g., `vote.recorded`). --- diff --git a/SESSION_END_QUICK_START.md b/docs/SESSION_END_QUICK_START.md similarity index 97% rename from SESSION_END_QUICK_START.md rename to docs/SESSION_END_QUICK_START.md index 897ce11..ebb191e 100644 --- a/SESSION_END_QUICK_START.md +++ b/docs/SESSION_END_QUICK_START.md @@ -62,7 +62,7 @@ curl -X POST http://localhost:5000/api/auth/login \ -d '{"key":"YOUR_ADMIN_KEY"}' # Run the test script -node test-session-end-websocket.js 17 YOUR_JWT_TOKEN +node ../tests/test-session-end-websocket.js 17 YOUR_JWT_TOKEN # In another terminal, close the session curl -X POST http://localhost:5000/api/sessions/17/close \ diff --git a/SESSION_END_WEBSOCKET.md b/docs/SESSION_END_WEBSOCKET.md similarity index 97% rename from SESSION_END_WEBSOCKET.md rename to docs/SESSION_END_WEBSOCKET.md index 48de1cd..8b8f964 100644 --- a/SESSION_END_WEBSOCKET.md +++ b/docs/SESSION_END_WEBSOCKET.md @@ -154,12 +154,12 @@ asyncio.run(listen_for_session_end()) A test script is provided to verify the `session.ended` event: ```bash -node test-session-end-websocket.js +node ../tests/test-session-end-websocket.js ``` **Example:** ```bash -node test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +node ../tests/test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` ### Manual Testing Steps @@ -172,7 +172,7 @@ node test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... 2. **Run the test script in another terminal:** ```bash - node test-session-end-websocket.js 17 + node ../tests/test-session-end-websocket.js 17 ``` 3. **Close the session in the Picker UI** or via API: diff --git a/SESSION_START_WEBSOCKET.md b/docs/SESSION_START_WEBSOCKET.md similarity index 99% rename from SESSION_START_WEBSOCKET.md rename to docs/SESSION_START_WEBSOCKET.md index 5112774..e61ea2a 100644 --- a/SESSION_START_WEBSOCKET.md +++ b/docs/SESSION_START_WEBSOCKET.md @@ -172,7 +172,7 @@ asyncio.run(listen_for_session_start()) 2. **Connect a WebSocket client** (use the test script or your own): ```bash - # You can modify test-session-end-websocket.js to listen for session.started + # You can modify ../tests/test-session-end-websocket.js to listen for session.started ``` 3. **Create a new session** in the Picker UI or via API: diff --git a/WEBSOCKET_FLOW_DIAGRAM.md b/docs/WEBSOCKET_FLOW_DIAGRAM.md similarity index 100% rename from WEBSOCKET_FLOW_DIAGRAM.md rename to docs/WEBSOCKET_FLOW_DIAGRAM.md diff --git a/WEBSOCKET_SUBSCRIPTION_GUIDE.md b/docs/WEBSOCKET_SUBSCRIPTION_GUIDE.md similarity index 100% rename from WEBSOCKET_SUBSCRIPTION_GUIDE.md rename to docs/WEBSOCKET_SUBSCRIPTION_GUIDE.md diff --git a/WEBSOCKET_TESTING.md b/docs/WEBSOCKET_TESTING.md similarity index 100% rename from WEBSOCKET_TESTING.md rename to docs/WEBSOCKET_TESTING.md diff --git a/todos.md b/docs/todos.md similarity index 100% rename from todos.md rename to docs/todos.md diff --git a/test-session-end-websocket.js b/tests/test-session-end-websocket.js similarity index 100% rename from test-session-end-websocket.js rename to tests/test-session-end-websocket.js diff --git a/test-webhook-simple.sh b/tests/test-webhook-simple.sh similarity index 100% rename from test-webhook-simple.sh rename to tests/test-webhook-simple.sh diff --git a/test-webhook.js b/tests/test-webhook.js similarity index 100% rename from test-webhook.js rename to tests/test-webhook.js diff --git a/test-webhook.sh b/tests/test-webhook.sh similarity index 100% rename from test-webhook.sh rename to tests/test-webhook.sh