- Python 99.4%
- Dockerfile 0.6%
| .claude | ||
| bot | ||
| docs | ||
| .env.example | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| BotBuildPlan.md | ||
| CHANGELOG.md | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements-dev.txt | ||
| requirements.in | ||
| requirements.txt | ||
Archiving Repository
2026/03/20: This repository has been moved under the Quest Board repository, and is being archived. Further bot work will continue there under the /bot directory.
Quest Board Bot
A Discord bot companion for Quest Board, the TTRPG session scheduler. It replaces plain webhook notifications with rich interactive Discord messages, records emoji reactions as scheduling votes, and joins voice channels to record, transcribe, and summarise game sessions.
Status
| Version | Feature | Status |
|---|---|---|
| v0.1.0 | Scaffold & API client | ✅ Done |
| v0.2.0 | Quest Board additions | ✅ Done |
| v0.3.0 | Discord notifications | ✅ Done |
| v0.4.0 | Account linking | ✅ Done |
| v0.5.0 | Reaction voting | ✅ Done |
| v0.6.0 | Recording & transcription | ✅ Done |
| v0.7.0 | Polish & hardening | ✅ Done |
| v0.8.0 | Attendance RSVP | ✅ Done |
| v0.9.0 | /next, /recap, /note, /ask |
✅ Done (needs Quest Board v0.9.0+) |
Prerequisites
- Docker and Docker Compose
- A running Quest Board instance (v0.2.0+)
- A Discord application with a bot token (see Discord Developer Portal Setup below)
- Optional: A running Ollama instance for local LLM summarisation
Quick Start
# 1. Clone the repository
git clone https://github.com/10thTARDIS/Questboard-Bot.git
cd Questboard-Bot
# 2. Copy the example env file
cp .env.example .env
# 3. Fill in required values (see Configuration below)
$EDITOR .env
# 4. Start the bot
docker compose up -d
# Optional: also start the local Whisper transcription service
# (required for /record if WHISPER_MODE=local and no OpenAI key is set)
docker compose --profile whisper up -d
Configuration
All settings are documented in .env.example.
Required:
DISCORD_BOT_TOKEN— from Discord Developer Portal → Bot → TokenBOT_API_KEY— copy from Quest Board Admin → Bot Settings → Bot API Key
Optional overrides (can also be set in Quest Board Admin → Bot Settings):
WHISPER_MODE—local(default, uses bundled Whisper container) orapi(OpenAI)SUMMARISER_MODE—ollama(default) orapi(Anthropic/OpenAI)REDIS_URL— enables persistent message→session mapping across bot restarts
Discord Developer Portal Setup
- Go to discord.com/developers/applications → New Application
- Name it (e.g. "Quest Board Bot") and click Create
- Bot tab:
- Click Add Bot → Yes, do it!
- Under Privileged Gateway Intents, enable:
- ✅ Message Content Intent (required for message content access)
- Click Reset Token → copy the token to
DISCORD_BOT_TOKENin.env
- OAuth2 → URL Generator:
- Scopes:
bot+applications.commands - Bot permissions:
- Read Messages/View Channels — see channels and their content
- Send Messages — post notification embeds and recording status
- Send Messages in Threads — if your notification channel uses threads
- Embed Links — required for rich embeds to render
- Read Message History — required for reaction handling on older messages
- Add Reactions — seed 🇦🇧🇨🇩🇪 on proposed sessions and ✅❌ on confirmed sessions
- Connect — join voice channels to record sessions
- Use Voice Activity — receive audio streams from participants
- Copy the generated URL and open it in a browser to invite the bot to your server
- Scopes:
Quest Board Admin Setup
After starting the bot, configure it in Quest Board's admin panel:
-
Admin → Bot Settings:
- Copy the Bot API Key shown here into
BOT_API_KEYin the bot's.env - Set Bot URL to
http://<bot-host>:8080— the address Quest Board uses to reach the bot's HTTP server - Optionally configure Whisper and LLM endpoints (overrides
.envvalues)
- Copy the Bot API Key shown here into
-
Campaign Settings (per campaign):
- Guild ID — your Discord server's ID (right-click server icon → Copy Server ID, requires Developer Mode enabled in Discord Settings → Advanced)
- Notification Channel ID — the text channel where session embeds should appear (right-click channel → Copy Channel ID)
Once all three are set, Quest Board will route session notifications through the bot instead of plain webhooks.
Account Linking
Players connect their Discord identity to Quest Board so reactions are recorded as votes:
- Run
/linkin any server channel where the bot is present - Click the link in the DM the bot sends (expires in 10 minutes)
- Log in to Quest Board if prompted, then confirm
- The bot sends a confirmation DM — reactions now count as votes
Reaction Voting
Once linked, players vote on proposed session times by reacting to the session embed with the regional indicator emojis (🇦, 🇧, 🇨 …). Adding a reaction records a yes vote; removing it records a no vote.
Attendance RSVP
When a session is confirmed, the bot posts a confirmation embed with ✅ and ❌ reactions. Players react to indicate whether they'll attend — this writes directly to Quest Board's attendance records. Reactions require a linked account (see Account Linking above).
Session Commands
| Command | Description |
|---|---|
/next |
Show the next confirmed session with a countdown |
/recap <session_id> |
Show the stored summary and GM notes for a session |
/note <text> |
Add a private note to the next (or a specified) session |
/ask <question> |
Ask a natural-language question about campaign history |
/note and /ask require a linked account. /next, /recap, and /note
require Quest Board v0.9.0 backend endpoints. /ask additionally requires the
v0.10.0 history endpoint — see docs/questboard-improvements.md
for what needs to be added on the Quest Board side.
The session_id for /recap and /note is the UUID shown in the Quest Board
session URL.
Recording a Session
Recording requires a transcription backend. Choose one:
- Local Whisper (default) — start the bundled container with
docker compose --profile whisper up -d, or configure a URL in Quest Board Admin → Bot Settings - OpenAI API — set
WHISPER_MODE=apiandOPENAI_API_KEYin.env
Only the GM needs to run these commands:
/record start <session_id> — join your voice channel and begin recording
/record stop — stop, transcribe, summarise, and upload
The session_id is the UUID shown in the Quest Board session URL. The bot
auto-stops after MAX_RECORDING_HOURS (default: 6) if /record stop is
not run manually.
After stopping, the bot:
- Mixes all participants' audio to a single mono MP3
- Transcribes it (Whisper local or OpenAI API)
- Summarises it (Ollama or Anthropic/OpenAI)
- Uploads the transcript and summary to Quest Board
- Posts a summary embed in the text channel
Whisper model trade-offs
| Model | Speed | Accuracy | RAM |
|---|---|---|---|
base |
Fastest | Good for clear audio | ~1 GB |
small |
Moderate | Better with accents | ~2 GB |
medium |
Slow | Most accurate | ~5 GB |
Set via ASR_MODEL in docker-compose.yml (whisper service). base is the
default and works well for most home gaming groups.
Ollama model recommendations
| Model | Notes |
|---|---|
llama3 |
Good general-purpose default |
mistral |
Fast, good for shorter sessions |
mixtral |
Higher quality, needs 16 GB+ VRAM |
Set via OLLAMA_MODEL in .env or Quest Board Admin → Bot Settings.
Development
pip install -r requirements.txt -r requirements-dev.txt
# Install pre-commit hooks (runs pip-audit + linters on commit)
pre-commit install
# Re-pin dependencies after editing requirements.in
pip-compile requirements.in --output-file requirements.txt
# Manual security audit
pip-audit -r requirements.txt
# Run tests
pytest
Architecture
See BotBuildPlan.md for the full design specification.
Quest Board Backend
│ Celery task fires on session event
│ POST /notify → Bot HTTP server (:8080)
▼
questboard-bot
├── cogs/notifications.py ← rich embeds + seed reactions + attendance RSVP
├── cogs/voting.py ← reaction add/remove → votes & attendance API
├── cogs/linking.py ← /link /unlink slash commands
├── cogs/recording.py ← /record start|stop + voice pipeline
└── cogs/sessions.py ← /next /recap /note /ask slash commands
│
▼
services/transcription.py ← Whisper (local container or OpenAI API)
services/summarisation.py ← Ollama, Anthropic, or OpenAI
services/qa.py ← campaign Q&A using session summaries as context
│
▼
Quest Board API (BOT_API_KEY auth via X-Bot-Key header)
Troubleshooting
Bot connects but no notifications appear
- Confirm Bot URL is set in Quest Board Admin → Bot Settings and points to the bot's host/port
- Confirm the campaign has
Guild IDandNotification Channel IDset - Check
BOT_API_KEYin.envmatches the key in Quest Board Admin → Bot Settings - Check
docker compose logs botfor any401 Unauthorizedor connection errors
Reactions aren't being recorded as votes
- The user must run
/linkfirst — the bot will DM them a prompt if they react unlinked - Confirm
REDIS_URLis set if you want vote mappings to survive bot restarts
/record start says "You need to be in a voice channel"
- The GM running the command must already be connected to a voice channel in the server
Whisper transcription times out or returns empty
- Check
docker compose logs whisper— the container may still be loading the model - Try a smaller
ASR_MODEL(e.g.base) if RAM is limited - For long sessions, the 10-minute transcription timeout may need increasing in
bot/services/transcription.py(_TIMEOUT)
Ollama summarisation fails
- Confirm Ollama is running and the model is pulled:
ollama pull llama3 - Check
OLLAMA_URLpoints to the correct host
/next, /recap, or /note returns "Could not reach Quest Board"
- These commands require Quest Board backend endpoints added in v0.9.0
(
GET /api/bot/guilds/{guild_id}/next-session,GET /api/bot/sessions/{id}/summary,POST /api/bot/sessions/{id}/notes) — check the improvements backlog indocs/questboard-improvements.mdfor implementation details
/ask returns "No session recordings found"
/asksearches sessions that have a stored summary; summaries are only created when a session is recorded with/record startand the transcript is uploaded — run at least one recorded session first/askalso requires theGET /api/bot/guilds/{guild_id}/sessions/historyQuest Board endpoint (v0.10.0) to be deployed
/note says account isn't linked
- Run
/linkfirst to connect your Discord account to Quest Board
License
MIT — see LICENSE.