Reorganize project: move docs to docs/ and test scripts to tests/
Moved 9 documentation .md files from root into docs/. Moved 4 test scripts from root into tests/. Updated cross-references in README.md and docs to reflect new paths. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -333,7 +333,7 @@ The system will:
|
|||||||
|
|
||||||
## Bot Integration
|
## 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
|
- Live voting API usage
|
||||||
- **WebSocket integration (recommended)** for real-time game notifications
|
- **WebSocket integration (recommended)** for real-time game notifications
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ This guide explains how to integrate your bot with the Jackbox Game Picker API f
|
|||||||
- [Webhook Integration](#webhook-integration)
|
- [Webhook Integration](#webhook-integration)
|
||||||
3. [Webhook Management](#webhook-management)
|
3. [Webhook Management](#webhook-management)
|
||||||
4. [Testing](#testing)
|
4. [Testing](#testing)
|
||||||
|
5. [Available Events](#available-events)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -219,11 +220,64 @@ All messages are JSON-formatted.
|
|||||||
"pack_name": "The Jackbox Party Pack 9",
|
"pack_name": "The Jackbox Party Pack 9",
|
||||||
"min_players": 2,
|
"min_players": 2,
|
||||||
"max_players": 8,
|
"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
|
// Heartbeat response
|
||||||
{
|
{
|
||||||
"type": "pong"
|
"type": "pong"
|
||||||
@@ -319,9 +373,14 @@ class JackboxWebSocketClient {
|
|||||||
|
|
||||||
handleGameAdded(data) {
|
handleGameAdded(data) {
|
||||||
const { game } = 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);
|
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",
|
"pack_name": "The Jackbox Party Pack 9",
|
||||||
"min_players": 2,
|
"min_players": 2,
|
||||||
"max_players": 8,
|
"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
|
### Webhook Headers
|
||||||
|
|
||||||
The API sends the following headers with each webhook:
|
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') {
|
if (req.body.event === 'game.added') {
|
||||||
const game = req.body.data.game;
|
const game = req.body.data.game;
|
||||||
|
|
||||||
// Send message to Kosmi chat
|
// Build announcement with room code if available
|
||||||
sendKosmiMessage(`🎮 Coming up next: ${game.title}!`);
|
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
|
// Always respond with 200 OK
|
||||||
@@ -616,11 +684,22 @@ curl -X GET "http://localhost:5000/api/webhooks/1/logs" \
|
|||||||
|
|
||||||
## Available Events
|
## 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`).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ curl -X POST http://localhost:5000/api/auth/login \
|
|||||||
-d '{"key":"YOUR_ADMIN_KEY"}'
|
-d '{"key":"YOUR_ADMIN_KEY"}'
|
||||||
|
|
||||||
# Run the test script
|
# 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
|
# In another terminal, close the session
|
||||||
curl -X POST http://localhost:5000/api/sessions/17/close \
|
curl -X POST http://localhost:5000/api/sessions/17/close \
|
||||||
@@ -154,12 +154,12 @@ asyncio.run(listen_for_session_end())
|
|||||||
A test script is provided to verify the `session.ended` event:
|
A test script is provided to verify the `session.ended` event:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node test-session-end-websocket.js <session_id> <jwt_token>
|
node ../tests/test-session-end-websocket.js <session_id> <jwt_token>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
```bash
|
```bash
|
||||||
node test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
node ../tests/test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||||
```
|
```
|
||||||
|
|
||||||
### Manual Testing Steps
|
### Manual Testing Steps
|
||||||
@@ -172,7 +172,7 @@ node test-session-end-websocket.js 17 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
|||||||
|
|
||||||
2. **Run the test script in another terminal:**
|
2. **Run the test script in another terminal:**
|
||||||
```bash
|
```bash
|
||||||
node test-session-end-websocket.js 17 <your-jwt-token>
|
node ../tests/test-session-end-websocket.js 17 <your-jwt-token>
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Close the session in the Picker UI** or via API:
|
3. **Close the session in the Picker UI** or via API:
|
||||||
@@ -172,7 +172,7 @@ asyncio.run(listen_for_session_start())
|
|||||||
|
|
||||||
2. **Connect a WebSocket client** (use the test script or your own):
|
2. **Connect a WebSocket client** (use the test script or your own):
|
||||||
```bash
|
```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:
|
3. **Create a new session** in the Picker UI or via API:
|
||||||
Reference in New Issue
Block a user