Ongoing operations: adding guilds, running migrations, deploying updates, and handling common tasks.
Each guild gets its own isolated D1 database. To onboard a new guild:
npx wrangler d1 create when2play-<guild-name>Or use the helper script (validates the guild ID format and prints next steps):
scripts/add-guild.sh <guild-name> <guild-id>Wrangler auto-adds an entry to the d1_databases array in wrangler.jsonc, but it needs manual fixes (see step 2).
wrangler.jsoncis gitignored (it contains guild-specific IDs). Edit your local copy directly.
Wrangler generates the binding name from the database name and omits migrations_dir. You must fix both:
- Change
bindingfrom"when2play_<name>"to"DB_<guild_id>"(the Worker looks up databases by guild snowflake at runtime). - Add
"migrations_dir": "migrations"(required forwrangler d1 migrations apply). database_nameanddatabase_idare fine as-is.
The corrected entry should look like:
npx wrangler d1 migrations apply when2play-<guild-name> --remotemake deployIn the new guild's Discord channel, run /setchannel (requires ADMINISTRATOR).
If the bot hasn't been invited to the new guild yet, use the OAuth2 URL from the Discord Developer Portal (same URL used during initial setup).
The bot automatically detects new guilds on startup and begins polling for them. If the bot is already running, it will pick up the new guild on its next client.guilds.cache refresh (usually within seconds of being invited).
npx wrangler d1 migrations apply when2play-<guild-name> --remotescripts/migrate-all.shThis iterates all when2play D1 databases and applies pending migrations. All guild databases share the same migrations/ directory since they use identical schemas.
- Run
scripts/migrate-all.shto bring all databases to the latest schema - Run
make deployto deploy the updated Worker
This ensures the Worker never runs against an outdated schema.
# If new migrations exist:
make migrate-remote
# or: scripts/migrate-all.sh (for all guilds)
# Deploy:
make deployBoth the bot and server share one secret: BOT_API_KEY.
- Generate a new key:
openssl rand -hex 32 - Set the new key on the Worker:
npx wrangler secret put BOT_API_KEY - Update
BOT_API_KEYin the bot's.envfile - Restart the bot
All guilds use the new key immediately (single key, not per-guild).
On startup, the bot fetches settings from D1 (GET /api/settings/bot) for each guild in client.guilds.cache and resumes polling. Channel configuration is stored in D1, so no local state is lost on restart.
When the bot is removed from a guild:
- The guild disappears from
client.guilds.cache, so polling stops automatically - The D1 database and Worker binding can remain (data preserved) or be cleaned up manually
If the Worker URL changes (e.g., switching to a custom domain):
- Update
WHEN2PLAY_API_URLin the bot's.envfile - Restart the bot
Error polling gather pings: TypeError: fetch failed
[cause]: ConnectTimeoutError (attempted addresses: 172.67.x.x:443, timeout: 10000ms)
This is a transient network issue on the bot's host, not a bug. The bot recovers automatically on the next poll cycle (15 seconds). If it happens frequently, check:
- Whether the host's network has intermittent connectivity
- Whether a firewall is blocking outbound HTTPS
- Whether the
WHEN2PLAY_API_URLis correct and the Worker is deployed
Either DISCORD_TOKEN or WHEN2PLAY_API_URL is missing from .env. Check that the file exists and is being loaded (--env-file=.env).
Commands are registered on bot startup via registerCommands(). This requires the bot to connect successfully at least once. If commands still don't appear after a minute, check the console for errors during startup.
The Worker returned an error from POST /api/auth/token. Common causes:
BOT_API_KEYin.envdoesn't match the secret set in the Worker (npx wrangler secret put BOT_API_KEY)- The Worker is not deployed or is unhealthy (
curl $WHEN2PLAY_API_URL/api/health)
| What | Command |
|---|---|
| Install | npm install |
| Dev server | make dev |
| Build frontend | make build |
| Run tests | make test |
| Deploy | make deploy |
| Apply remote migrations | make migrate-remote |
| Apply local migrations | make migrate-local |
| Set bot secret | npx wrangler secret put BOT_API_KEY |
| Stream logs | make logs |
| Simulate auth | make simulate |
| Seed data | make seed |
| Query remote D1 | npx wrangler d1 execute when2play-<guild-name> --remote --command "SELECT ..." |
{ "binding": "DB_<guild_id>", "database_name": "when2play-<guild-name>", "database_id": "<auto-filled by wrangler>", "migrations_dir": "migrations" }