docs: comprehensive documentation overhaul
Rewrite README.md and all setup guides to reflect the current native GraphQL WebSocket architecture (replacing stale headless Chrome/WebSocket interception descriptions). Add new docs/IRC.md with complete IRC command reference, vote syntax, and ticker symbol table. Archive pre-edit docs to docs/archive/setup-backup-2026-05-10/ and move historical development notes from docs/ root into docs/archive/. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,203 +1,226 @@
|
||||
# Jackbox Game Picker API Integration
|
||||
|
||||
This document describes how the Kosmi/IRC relay integrates with the Jackbox Game Picker API for live voting and game notifications.
|
||||
This document describes how the Kosmi/IRC relay integrates with the Jackbox Game Picker API for live voting, game announcements, and room code display.
|
||||
|
||||
## Features
|
||||
## Overview
|
||||
|
||||
### 1. Vote Detection
|
||||
The relay automatically detects when users vote on games using the `thisgame++` or `thisgame--` syntax in either Kosmi or IRC chat.
|
||||
When enabled, the relay:
|
||||
|
||||
**How it works:**
|
||||
- Users type `thisgame++` to upvote the current game
|
||||
- Users type `thisgame--` to downvote the current game
|
||||
- Votes are case-insensitive
|
||||
- The relay filters out relayed messages (messages with `[irc]` or `[kosmi]` prefix) to prevent duplicate votes
|
||||
- Only votes from actual users in each chat are sent to the API
|
||||
|
||||
### 2. Game Notifications
|
||||
When a new game is added to the Jackbox session via the API, the relay receives a webhook notification and broadcasts it to both Kosmi and IRC chats.
|
||||
|
||||
**Example notification:**
|
||||
```
|
||||
🎮 Coming up next: Fibbage 4!
|
||||
```
|
||||
1. **Detects votes** in chat (`thisgame++`/`thisgame--` and ticker-symbol votes) and submits them to the API
|
||||
2. **Receives game events** via WebSocket (or webhook fallback) and announces them to all bridges
|
||||
3. **Responds to `!votes`** with the current game's vote tally
|
||||
4. **Optionally generates room code images** and uploads them to Kosmi
|
||||
|
||||
## Configuration
|
||||
|
||||
Add the following section to your `matterbridge.toml`:
|
||||
Add the `[jackbox]` section to `matterbridge.toml`:
|
||||
|
||||
```toml
|
||||
[jackbox]
|
||||
# Enable Jackbox integration for vote detection and game notifications
|
||||
# Enable Jackbox integration
|
||||
Enabled=true
|
||||
|
||||
# Jackbox API URL
|
||||
APIURL="http://localhost:5000"
|
||||
APIURL="https://your-jackbox-api.example.com"
|
||||
|
||||
# Admin password for API authentication
|
||||
AdminPassword="your_admin_password_here"
|
||||
# Admin password for API authentication (exchanged for JWT)
|
||||
AdminPassword="your_admin_password"
|
||||
|
||||
# Webhook server port (for receiving game notifications)
|
||||
# Use WebSocket for real-time game notifications (recommended, default: true)
|
||||
# Set to false to use webhook HTTP server instead
|
||||
UseWebSocket=true
|
||||
|
||||
# --- Webhook settings (only if UseWebSocket=false) ---
|
||||
# Port for the webhook HTTP server
|
||||
WebhookPort=3001
|
||||
# HMAC-SHA256 secret for webhook signature verification
|
||||
WebhookSecret="your_webhook_secret"
|
||||
|
||||
# Webhook secret for signature verification
|
||||
WebhookSecret="your_webhook_secret_here"
|
||||
# --- Room code image settings ---
|
||||
# Generate and upload a room code image to Kosmi chat
|
||||
EnableRoomCodeImage=true
|
||||
# Seconds to wait before sending the image announcement (default: 0)
|
||||
RoomCodeImageDelay=28
|
||||
# Seconds to wait before sending the plaintext room code follow-up (default: 29)
|
||||
RoomCodePlaintextDelay=22
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
### Configuration Reference
|
||||
|
||||
- **Enabled**: Set to `true` to enable the integration, `false` to disable
|
||||
- **APIURL**: The URL of your Jackbox Game Picker API (e.g., `http://localhost:5000`)
|
||||
- **AdminPassword**: Your API admin password (used to authenticate and get a JWT token)
|
||||
- **WebhookPort**: Port for the webhook server to listen on (default: 3001)
|
||||
- **WebhookSecret**: Shared secret for webhook signature verification (must match the secret configured in the API)
|
||||
| Key | Type | Default | Description |
|
||||
|-----|------|---------|-------------|
|
||||
| `Enabled` | bool | `false` | Master switch for the integration |
|
||||
| `APIURL` | string | | Base URL of the Jackbox Game Picker API |
|
||||
| `AdminPassword` | string | | Admin password, exchanged for a JWT via `POST /api/auth/login` |
|
||||
| `UseWebSocket` | bool | `true` | Use WebSocket transport for events (recommended) |
|
||||
| `WebhookPort` | int | `3001` | HTTP listen port for webhook server |
|
||||
| `WebhookSecret` | string | | HMAC secret for webhook signature verification |
|
||||
| `EnableRoomCodeImage` | bool | `false` | Generate/upload room code images |
|
||||
| `RoomCodeImageDelay` | int | `0` | Seconds before image announcement |
|
||||
| `RoomCodePlaintextDelay` | int | `29` | Seconds before plaintext room code |
|
||||
|
||||
## Setup Steps
|
||||
## Transport: WebSocket vs. Webhook
|
||||
|
||||
### 1. Configure the Relay
|
||||
### WebSocket (Recommended)
|
||||
|
||||
Edit `matterbridge.toml` and add the Jackbox configuration section with your API URL, admin password, and webhook secret.
|
||||
When `UseWebSocket=true`, the relay connects to `wss://<APIURL>/api/sessions/live` and authenticates with its JWT. Events are received in real-time with automatic reconnection.
|
||||
|
||||
### 2. Register the Webhook
|
||||
Handled events:
|
||||
- `session.started` -- announces game night start
|
||||
- `game.added` -- announces next game with room code
|
||||
- `session.ended` -- announces game night end
|
||||
|
||||
After starting the relay, register the webhook with the Jackbox API:
|
||||
No additional setup is required beyond the config above.
|
||||
|
||||
### Webhook (Fallback)
|
||||
|
||||
When `UseWebSocket=false`, the relay starts an HTTP server on `WebhookPort` and listens for `POST /webhook/jackbox` requests from the API.
|
||||
|
||||
You must register the webhook with the API:
|
||||
|
||||
```bash
|
||||
# Get JWT token
|
||||
curl -X POST "http://localhost:5000/api/auth/login" \
|
||||
TOKEN=$(curl -s -X POST "$API_URL/api/auth/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"apiKey": "your_admin_password"}'
|
||||
-d '{"key": "your_admin_password"}' | jq -r .token)
|
||||
|
||||
# Register webhook (use the JWT token from above)
|
||||
curl -X POST "http://localhost:5000/api/webhooks" \
|
||||
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
||||
# Register webhook
|
||||
curl -X POST "$API_URL/api/webhooks" \
|
||||
-H "Authorization: Bearer $TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"name": "Kosmi/IRC Relay",
|
||||
"url": "http://your-relay-host:3001/webhook/jackbox",
|
||||
"secret": "your_webhook_secret_here",
|
||||
"secret": "your_webhook_secret",
|
||||
"events": ["game.added"]
|
||||
}'
|
||||
```
|
||||
|
||||
**Important:** Replace `your-relay-host` with the actual hostname or IP address where your relay is running. If the API and relay are on the same machine, you can use `localhost`.
|
||||
Webhook requests include an `X-Webhook-Signature` header with an HMAC-SHA256 signature for verification.
|
||||
|
||||
### 3. Test the Integration
|
||||
## Vote Detection
|
||||
|
||||
#### Test Vote Detection
|
||||
The relay automatically detects vote patterns in non-relayed messages from both IRC and Kosmi.
|
||||
|
||||
1. Start an active session in the Jackbox API with some games played
|
||||
2. Send a message in Kosmi or IRC: `thisgame++`
|
||||
3. Check the relay logs for: `Detected vote from <username>: up`
|
||||
4. Verify the vote was recorded in the API
|
||||
### Supported Syntax
|
||||
|
||||
#### Test Game Notifications
|
||||
| Pattern | Effect |
|
||||
|---------|--------|
|
||||
| `thisgame++` | Upvote currently playing game |
|
||||
| `thisgame--` | Downvote currently playing game |
|
||||
| `SYMBOL++` | Upvote game by ticker symbol |
|
||||
| `SYMBOL--` | Downvote game by ticker symbol |
|
||||
|
||||
1. Add a game to the active session via the Jackbox API
|
||||
2. Both Kosmi and IRC chats should receive a notification: `🎮 Coming up next: <game title>!`
|
||||
- All patterns are case-insensitive
|
||||
- `thisgame` votes can appear anywhere in the message
|
||||
- Ticker symbols are 2-4 alphanumeric characters that map to specific games (see [IRC.md](../IRC.md) for the full ticker table)
|
||||
- Messages prefixed with `[irc]` or `[kosmi]` are treated as relayed and skip vote detection
|
||||
|
||||
Votes are submitted to `POST /api/votes/live` with the voter's username, vote type, timestamp, and optional ticker symbol.
|
||||
|
||||
### Deduplication
|
||||
|
||||
The API rejects duplicate votes from the same user within 1 second.
|
||||
|
||||
## IRC/Kosmi Commands
|
||||
|
||||
### `!votes`
|
||||
|
||||
Available in both IRC and Kosmi chat. Queries the current game's vote tally and broadcasts the result to all bridges:
|
||||
|
||||
```
|
||||
🗳️ Fibbage 4 • Today: 5👍 2👎 (Score: 3) • All-time: 46👍 3👎 (Score: 43)
|
||||
```
|
||||
|
||||
Requires an active session with a game currently "playing".
|
||||
|
||||
### Reconnect Commands (IRC only)
|
||||
|
||||
| Command | Effect |
|
||||
|---------|--------|
|
||||
| `!jreconnect` | Reconnect the Jackbox WebSocket |
|
||||
| `!kreconnect` | Reconnect the Kosmi bridge |
|
||||
| `!reconnect` | Reconnect all non-IRC services |
|
||||
|
||||
## Room Code Images
|
||||
|
||||
When `EnableRoomCodeImage=true` and a `game.added` event includes a room code, the relay:
|
||||
|
||||
1. Generates an image of the room code
|
||||
2. Uploads it to the Kosmi CDN (`img.kosmi.io`)
|
||||
3. Sends the image + announcement message after `RoomCodeImageDelay` seconds
|
||||
4. Sends a plaintext room code follow-up after `RoomCodePlaintextDelay` seconds
|
||||
|
||||
If image generation or upload fails, the relay falls back to plaintext-only announcement.
|
||||
|
||||
## Mute Control
|
||||
|
||||
Jackbox announcements (game start, game added, session end) can be suppressed without stopping the relay:
|
||||
|
||||
- Start muted: `./matterbridge -conf matterbridge.toml -muted`
|
||||
- Toggle at runtime: `kill -SIGUSR1 <pid>` or `docker kill -s SIGUSR1 <container>`
|
||||
|
||||
When muted:
|
||||
- Announcements are suppressed
|
||||
- Vote detection still works (votes are still sent to the API)
|
||||
- Normal IRC/Kosmi message relay is unaffected
|
||||
- `!votes` still works
|
||||
|
||||
See [MUTE_CONTROL.md](MUTE_CONTROL.md) for full details.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Vote Flow
|
||||
|
||||
1. User sends a message containing `thisgame++` or `thisgame--` in Kosmi or IRC
|
||||
2. The bridge detects the vote pattern (case-insensitive)
|
||||
3. The bridge checks if the message is relayed (has `[irc]` or `[kosmi]` prefix)
|
||||
4. If not relayed, the bridge extracts the username and vote type
|
||||
5. The bridge sends the vote to the Jackbox API via HTTP POST to `/api/votes/live`
|
||||
6. The API records the vote and associates it with the current game based on timestamp
|
||||
1. User sends a message containing `thisgame++` (or similar) in IRC or Kosmi
|
||||
2. The bridge detects the vote pattern (skipping relayed messages)
|
||||
3. The bridge submits `POST /api/votes/live` with username, vote type, and timestamp
|
||||
4. The API records the vote against the currently playing game
|
||||
|
||||
### Notification Flow
|
||||
### Event Flow (WebSocket)
|
||||
|
||||
1. A game is added to an active session in the Jackbox API
|
||||
2. The API sends a webhook POST request to `http://your-relay-host:3001/webhook/jackbox`
|
||||
3. The webhook includes an HMAC-SHA256 signature in the `X-Webhook-Signature` header
|
||||
4. The relay verifies the signature using the configured webhook secret
|
||||
5. If valid, the relay parses the `game.added` event
|
||||
6. The relay broadcasts the game announcement to all connected bridges (Kosmi and IRC)
|
||||
1. The relay authenticates with the Jackbox API and opens a WebSocket
|
||||
2. When a session starts, the relay subscribes to that session's events
|
||||
3. `game.added` events trigger game announcements broadcast to all bridges
|
||||
4. `session.ended` triggers the end-of-night message
|
||||
|
||||
## Security
|
||||
### Authentication
|
||||
|
||||
### Webhook Signature Verification
|
||||
|
||||
All incoming webhooks are verified using HMAC-SHA256 signatures to ensure they come from the legitimate Jackbox API.
|
||||
|
||||
**How it works:**
|
||||
1. The API computes `HMAC-SHA256(webhook_secret, request_body)`
|
||||
2. The signature is sent in the `X-Webhook-Signature` header as `sha256=<hex_signature>`
|
||||
3. The relay computes the expected signature using the same method
|
||||
4. The relay uses timing-safe comparison to verify the signatures match
|
||||
5. If verification fails, the webhook is rejected with a 401 Unauthorized response
|
||||
|
||||
### JWT Authentication
|
||||
|
||||
The relay authenticates with the Jackbox API using the admin password to obtain a JWT token. This token is:
|
||||
- Cached to avoid re-authentication on every vote
|
||||
- Automatically refreshed if it expires (detected via 401 response)
|
||||
- Valid for 24 hours (configurable in the API)
|
||||
The relay authenticates with `POST /api/auth/login` using the `AdminPassword` to get a JWT. The token is cached in memory and refreshed automatically on 401 responses.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Votes Not Being Recorded
|
||||
|
||||
**Possible causes:**
|
||||
- No active session in the Jackbox API
|
||||
- Vote timestamp doesn't match any played game
|
||||
- Duplicate vote within 1 second
|
||||
- Authentication failure
|
||||
- Verify an active session exists with games played
|
||||
- Check that the vote timestamp matches a played game's timeframe
|
||||
- Look for `"Detected vote from"` in debug logs
|
||||
- Look for `"Failed to send vote"` errors
|
||||
- Confirm the message isn't prefixed with `[irc]`/`[kosmi]` (relayed messages skip vote detection)
|
||||
|
||||
**Check:**
|
||||
1. Relay logs for vote detection: `grep "Detected vote" logs/matterbridge.log`
|
||||
2. Relay logs for API errors: `grep "Failed to send vote" logs/matterbridge.log`
|
||||
3. API logs for incoming vote requests
|
||||
### Announcements Not Appearing
|
||||
|
||||
### Webhooks Not Being Received
|
||||
- Verify `Enabled=true` in config
|
||||
- Check `APIURL` is accessible and `AdminPassword` is correct
|
||||
- Look for `"Jackbox WebSocket connected"` in logs (if using WebSocket)
|
||||
- If using webhooks, verify the webhook is registered and the port is accessible
|
||||
- Check mute state: look for `"MUTED"` in logs
|
||||
|
||||
**Possible causes:**
|
||||
- Webhook URL is not accessible from the API server
|
||||
- Webhook not registered in the API
|
||||
- Signature verification failing
|
||||
- Firewall blocking the webhook port
|
||||
### WebSocket Disconnects
|
||||
|
||||
**Check:**
|
||||
1. Verify webhook is registered: `GET /api/webhooks` (with JWT token)
|
||||
2. Test webhook manually: `POST /api/webhooks/test/:id` (with JWT token)
|
||||
3. Check webhook logs in API: `GET /api/webhooks/:id/logs` (with JWT token)
|
||||
4. Verify webhook server is listening: `curl http://localhost:3001/health`
|
||||
5. Check relay logs for signature verification errors
|
||||
- The relay auto-reconnects with exponential backoff
|
||||
- Use `!jreconnect` from IRC to force an immediate reconnection
|
||||
- Check API server availability
|
||||
|
||||
### Authentication Failures
|
||||
|
||||
**Possible causes:**
|
||||
- Incorrect admin password in configuration
|
||||
- API is not running or not accessible
|
||||
|
||||
**Check:**
|
||||
1. Verify API URL is correct and accessible
|
||||
2. Test authentication manually:
|
||||
```bash
|
||||
curl -X POST "http://localhost:5000/api/auth/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"apiKey": "your_admin_password"}'
|
||||
```
|
||||
3. Check relay logs for authentication errors
|
||||
|
||||
## Logs
|
||||
|
||||
The relay logs all Jackbox-related activity with the `jackbox` prefix:
|
||||
|
||||
```
|
||||
[jackbox] Initializing Jackbox integration...
|
||||
[jackbox] Successfully authenticated with Jackbox API
|
||||
[jackbox] Starting Jackbox webhook server on port 3001
|
||||
[kosmi] Detected vote from Anonymous Llama: up
|
||||
[jackbox] Vote recorded for Fibbage 4: Anonymous Llama - 5👍 2👎
|
||||
[jackbox] Broadcasting Jackbox message: 🎮 Coming up next: Quiplash 3!
|
||||
```bash
|
||||
# Test authentication manually
|
||||
curl -X POST "$API_URL/api/auth/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"key": "your_admin_password"}'
|
||||
```
|
||||
|
||||
## Disabling the Integration
|
||||
|
||||
To disable the Jackbox integration, set `Enabled=false` in the `[jackbox]` section of `matterbridge.toml` and restart the relay.
|
||||
|
||||
The relay will continue to function normally for Kosmi ↔ IRC message relay without any Jackbox features.
|
||||
## Disabling
|
||||
|
||||
Set `Enabled=false` in the `[jackbox]` section and restart. The relay continues to function normally for IRC/Kosmi message relay without any Jackbox features.
|
||||
|
||||
Reference in New Issue
Block a user