Self-hosting guide
Shockwave is a plain Python process, no external services required beyond Discord itself. This page covers setup, config, and the handful of gotchas that actually show up in practice.
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
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.
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.
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.
| Permission | Needed for | Why |
|---|---|---|
| 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
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.
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.
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.
/ again. Still nothing? The bot's own instance may simply be offline.
Check with whoever runs it.
Where things live
| What | Location |
|---|---|
| Bot token | ./token.txt |
| Server database | data/guildData/serverInfo/main.db |
| Database backups | data/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.
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 bot | Effect |
|---|---|
| alerts off | Stops the DMs, without restarting the bot. |
| alerts on | Turns them back on. |
| alerts status | Replies 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
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.
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.
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.