Shockwave

Before you start

Runtime

Python 3.10+ (tested on 3.12), plus discord.py, numpy, Pillow, and pytest/pytest-xdist (runs the test suite on every startup before connecting to Discord).

A bot application

Created in the Discord Developer Portal, with a bot token and one privileged intent enabled.

Setup

01

Clone the repo

git clone https://github.com/ShockwaveBot/Shockwave.git
cd Shockwave

Everything below assumes you're working from inside this folder; it's what "the project root" means in the later steps.

02

Create the bot application

In the Developer Portal, create an application, add a Bot user, and copy its token. Under Privileged Gateway Intents, turn on Server Members Intent. Shockwave needs it to see who's in a voice channel.

03

Invite it to your server

In the Developer Portal, go to OAuth2 → URL Generator. Under Scopes, check bot and applications.commands; the second is what makes slash commands like /make-teams show up at all. A Bot Permissions panel then appears; check the six permissions in the table below (why each one's needed is broken down there too). Discord builds the invite URL for you as you check boxes. It looks like this, with your own client ID in place of the placeholder:

https://discord.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&permissions=17861648&scope=bot%20applications.commands

Paste it into your browser, choose your server from the dropdown, and hit Authorize.

Invite permissions, and why each one's needed

Shockwave asks for six permissions, nothing broader than what its commands actually do.

PermissionNeeded forWhy
View Channels All commands The bot has to see a voice channel to know who's in it.
Connect /make-teams Discord only exposes voice channel membership to accounts that could join the channel.
Move Members Start button, Cancel Game button Both work by moving players between voice channels directly.
Manage Channels /set channels, Start button Creates the two team voice channels automatically if they don't already exist.
Send Messages Every command Posts confirmations, team embeds, and error messages back into the channel.
Attach Files /tournament print-bracket and tournament matches The bracket is posted as an actual image, not text. Needs this to upload it.

Finish setup

04

Install dependencies

# from the project root
pip install -r requirements.txt

This pulls in discord.py, numpy, and Pillow (used to draw the tournament bracket as an image), the only non-stdlib dependencies the bot needs.

05

Add your token

Create a file named token.txt next to bot.py, containing nothing but the bot token on its own line. Keep this file out of version control.

Optionally, add a second line with your own Discord user ID. This is what turns on developer DM alerts and the "Developer" trading-card title for your account. Leave it out and the bot runs exactly the same, just without either.

06

Run it

python bot.py

Shockwave stores per-server state in SQLite at data/guildData/serverInfo/main.db, creating that folder and the database itself on first run - nothing to set up by hand. No server ID to configure either: on startup, and again every time the bot joins a new server, it publishes its commands straight to whichever guild(s) it's actually in. Slash commands should show up within a few seconds of the bot coming online.


Verify it worked

Bot shows up in the member list

Shockwave should appear online in your server's member sidebar right after authorizing.

Slash commands autocomplete

Type / in any channel and Shockwave's commands should appear in the picker.

A welcome message posts on its own

Shockwave posts a one-time message pointing at /setup and /help, in your server's main channel if one's set, otherwise the first text channel it can post in. Turn it off for future joins with /set welcome-message enabled:false.

Commands not showing up? Shockwave publishes its commands to every server it's in automatically, on startup and again the moment it joins a new one, so there's nothing to configure per-server. Give it a few seconds after authorizing, then try typing / again. Still nothing? The bot's own instance may simply be offline. Check with whoever runs it.

Where things live

WhatLocation
Bot token./token.txt
Server databasedata/guildData/serverInfo/main.db
Database backupsdata/guildData/backups/

Backups and restoring

Shockwave snapshots main.db into data/guildData/backups/ once a day (right on startup, then every 24 hours after), keeping the last 7 days automatically. Nothing to configure. It just runs.

To revert to one, stop the bot first (copying over a database file a running process still has open risks corrupting it), then run the included restore script from the project root:

python restore_backup.py

It lists every backup newest-first with its timestamp and size, and restores whichever one you pick, by number or filename. Before overwriting anything, it saves the current live database as its own backup first, so restoring the wrong one, or restoring at all, is itself undoable the same way. Start the bot back up once it's done.

Restoring affects every server the bot is in. main.db is one shared database across every guild Shockwave serves. There's no way to restore just one server's data without rolling back the rest along with it.

Developer DM alerts

If token.txt's second line is set (see step 05 above), the bot DMs that account whenever anything warning-level or worse gets logged (a database backup failing, an unhandled command error, a startup self-test failure) instead of it sitting unnoticed in shockwave.log until someone happens to check. Leave the line out and this simply never fires. Everything else about the bot works the same either way.

There's no slash command for this. A slash command is visible to every member of every server the bot is in, whether or not they can actually run it, and there's no way to hide one from Discord's own command picker short of registering it to a private server. Instead, DM the bot directly:

DM the botEffect
alerts offStops the DMs, without restarting the bot.
alerts onTurns them back on.
alerts statusReplies with whether they're currently on or off.

Only DMs from the account on token.txt's second line do anything. Everyone else's DMs to the bot are ignored. This is also an in-memory setting: it resets to on every time the bot restarts.


Common issues

"no such table: servers" on first run.
This means the database file existed (even empty) before the table-creation check ran. Delete data/guildData/serverInfo/main.db and restart. It'll be recreated correctly.
Upgrading an existing database for betting/economy.
You don't need to delete main.db to pick up the betting feature. On startup the bot checks for the columns and tables it needs (economy, wagers, and a few new columns on servers) and adds whatever's missing, leaving your existing team/tournament data alone.
A command silently does nothing when a required member/role is left blank.
Discord's slash-command UI allows submitting without filling every optional-looking field. Commands that need a specific player (like /wager against) check for this and reply with what's missing instead of failing silently.