disquip-bot
DisQuip Bot: Discord bot that plays audio clips from local files into voice channels on command.
In essence, this is a customizable soundboard. Commands for randomizing aspects of Civilization VI game setup are optionally included (assumes you have all the DLC).
Quick demo:
https://github.com/user-attachments/assets/316cd5e1-277f-41c8-894f-0e7120be4d61
(recorded prior to implementation of search and play-by-search capabilities)
The original, defunct Python implementation can be found here.
Table of Contents
Quick Start
- Clone the repository and navigate to it:
git clone https://github.com/blthayer/disquip-bot-rs.git; cd disquip-bot-rs. - Place the contents of your Discord bot's API token into a file called
tokenin this directory. - Create subdirectories in the
audiodirectory and populate them withmp3and/orwavfiles. - Compile and run locally:
./run.sh
Disclaimers
This is a self-hosted bot - You perform Discord configuration, collect your own audio files, and run this program on your own PC, server, Raspberry Pi, etc.
This is (working) beta software - It is not guaranteed to work everywhere or be 100% secure, stable, or "productionized."
While everything does seem to work just fine in my environment (no obvious memory leaks, no crashes after weeks of continuous runtime), testing is quite minimal, error handling is minimal/incomplete, logging is mostly missing, not all edge cases are covered, and security has not been assessed. No load or stress testing has been performed, and the bot has not been tested against multiple Discord servers simultaneously.
Use at your own risk! No warranty is implied or provided for this freely available software.
If you encounter any issues, please do file an issue or submit a pull request.
Usage Within Discord
TL;DR: Type !help into a Discord server's text channel that the bot is authorized
to read from and write to, and go from there!
This section covers interacting with the bot/app through Discord, and assumes the app is properly configured and the program is running. See Quick Start or Setup, Install, and Run sections of this document for more information on getting the bot running (launching the program).
All commands for the bot are prefixed with ! and are entered into a text channel
that the bot is able to read and respond to messages in. In order to play audio
files, you must be in a voice channel. The bot does not support slash commands.
This guide will not cover all commands in detail, as the !help contents should
stand on its own.
help
To get the available commands, type !help, which will give output similar to
the following:
Commands:
!list List quip categories or list quips for a given command. E.g., "!list" or "!list a1"
!search_exact Exact search for quips by file name. Aka "!se." E.g., "!se foo".
!search_fuzzy Fuzzy search for quips by file name. Aka "!sf." E.g., "!sf foo".
!lucky Play by search. Aka "!l." E.g., "!l foo". Uses fuzzy search by default.
!random Aka "!r" or "!rand." Play a random quip.
!disconnect Disconnect the bot from its current voice channel.
!dice Roll the dice! Aka "!d." Usage: "!dice <n sides> <n dice>" - n dice defaults to 1
!help Show help menu.
!civ_draft Draw random leaders: "!civ_draft n_players n_leaders."
!civ_list_modes List game modes. Useful in conjunction with "!civ_draw_modes"
!civ_draw_modes Draw random game modes. See also "!civ_list_modes"
!civ_draw_map Draw a single random map.
!civ_draw_settings Draw random game settings to jump-start Civilization VI game setup.
Type "!<category> <number>" (e.g., "a1 1") to play a quip!
Type "!list" to discover available quip categories.
Type "!list <category>" to get available quip numbers for the given category.
Type "!help <command>" for more info on a command.
It is then possible to get additional for commands via !help <command>. For
example, !help list:
!list
List quip categories or list quips for a given command. E.g., "!list" or "!list a1"
Parameters:
cat (optional)
list
The !list command lists available quip categories (which can then be used as
commands), which are defined by the installed audio files.
Example (truncated) output:
Quip categories:
a1
a2
a3
...
halo
lotr
misc
...
sw
For inspiration, my personal setup here includes the taunts from the Age of Empires
games in the a1-a3 categories, clips from the Halo games in halo, Lord of the Rings
movie audio clips in lotr, miscellaneous quips in misc, and of course clips from
Star Wars in sw.
To list out quips available for a given category, do !list <category>. For example,
in my setup !list a3 yields the following taunts from Age of Empires 3:
1: "001 Yes.mp3"
2: "002 No.mp3"
3: "003 I Need Food.mp3"
4: "004 I Need Wood.mp3"
5: "005 I Need Coin.mp3"
...
To play the taunt that says "No," you would then type !a3 2 into the text channel.
Searching for quips
TL;DR: !se foo or !sf foo.
There are two different search methods: exact (!search_exact, aka !se) and
fuzzy (!search_fuzzy, aka !sf). More details can be found via
!help search_exact and !help search_fuzzy.
Playing a quip
TL;DR: !a3 2
See list first.
You must be in a voice channel for this to work. Simply type !<category> <number>
into the text channel you use for bot interactions, where <category> maps to a
directory of audio files, and the number is the counting number associated with the
file. See Audio Files for more information.
random
TL;DR: !r
Plays a globally random quip, or a random quip from a specified category
(!r <category>). This is a lot of fun and great for... discovering... quips
available to the bot.
lucky
TL;DR: !l foo
Play by search, in this case, the quip whose name best matches the
string foo. More details can be found via !help lucky
Setup, Install, and Run
TL;DR:
- Set up Discord application, add to your server, download token, save to file
with
600permissions. - Create a directory containing subdirectories of
.mp3and.wavaudio files. - Run:
disquip-bot /path/to/audio /path/to/token - Use: see Usage Within Discord
Installation methods:
- Download a pre-built binary from a release
- Download and
apt installa pre-packaged.debfrom a release - Build binary or
.debfrom source yourself (recommend checking out a tag)
Known working Linux systems:
- Pop!_OS 22.04 LTS, x86_64 architecture - local build
- Raspberry Pi OS (Debian 13, a.k.a. "Trixie") April 2026 release, aarch64 architecture (Raspberry Pi 4 Model B Rev 1.5) - local build
- JetPack 6 (based on Ubuntu 22), aarch64 architecture (NVIDIA Jetson, Orin Nano) - cross-compilation
The bot very likely functions on other operating systems, but has not been tested on any besides those listed here. Please submit a PR to add your setup and any additional directions required. All directions here assume a Debian-based Linux distribution (e.g. Ubuntu, Pop!_OS, etc.).
NOTE: Pre-built release binaries and recipes in the justfile use the
--all-features flag for cargo, meaning that the civ (Civilization VI)
feature is included. This feature does not add extra dependencies and is quite
lightweight. If you still wish to have a build without the civ features, build
from source yourself without the --all-features flag set (the civ features is
not enabled by default via Cargo.toml).
Discord App Configuration
This assumes a Discord App has already been created through Discord, the procedure for which is outside the scope of this document.
The following directions describe how to obtain an API token and how to configure gateway intents.
- Log into the Discord developer portal.
- Under the "Bot" tab, click "Reset Token."
- Copy the contents of the token into a file called
tokenat the top-level of this repository (don't worry, it's ignored bygit). - Back in the developer portal under the "Bot" tab, in the "Privileged Gateway Intents" sections toggle "Message Content Intent" on.
- Save changes.
Ensure the bot is added/authenticated with the Discord server you intend to use ( directions outside the scope of this document).
Audio Files
DisQuip Bot is a "bring your own audio files" project - for legal and copyright reasons, no audio files are distributed with the bot or this repository. Don't let that discourage you - there are plenty of audio files available on the internet.
- Create subdirectories in the repository's top-level
audiodirectory. - Populate the subdirectories with audio files (
.mp3or.wav).
Tips:
- Do NOT use directory names that correspond to already built-in commands or
their aliases. See the help section of this document or use the
!helpcommand to get a listing of built-in commands and their aliases. As an obvious example, don't create a directory namedhelp. - Keep the directory names short as they'll be directly used as commands later.
For instance, instead of a directory named
batman, you may wish to name itbmfor short. - Use descriptive file names, as the file names are how users will discover
quips. For instance, if one of your files contains the Governator saying
"I'll be back," consider naming the file
I'll be back.mp3(and maybe placing it in a directory calledtm, short for Terminator). - Keep the clips short! Your friends will be quite annoyed if you play clips that last more than a few seconds.
- For additional audio file format support, add to the
featureslist of the symphonia dependency inCargo.tomland then runcargo update symphonia. - After collecting all your audio files, consider normalizing them so the volume range is similar. The previous Python version of the bot leveraged ffmpeg-normalize for this purpose.
Prerequisites (Building From Source)
To build from source, the following tools are required:
- Rust toolchain. Tested with the latest version
(
rustcversion1.95.0), should work on older (but recent) versions as well. gcc: Easiest path is tosudo apt update; sudo apt install build-essentialcmake: Simplysudo apt update; sudo apt install cmakeon a Debian-based Linux system (e.g., Debian, Ubuntu, Pop!_OS, Mint, etc.). Tested with versions3.22.1and3.31.6.
Build from Source, Run Locally
For your convenience, simply run ./run.sh. The script (and the program)
take two positional arguments: The path to your audio files and the path
to the file containing your Discord token. Example:
Pre-built Binaries
A limited set of pre-built binaries are provided for each release.
Run the binary with no arguments or --help to get help. Example:
Example:
crates.io
apt / systemd (.deb files)
If you'd like to install disquip-bot with apt and run as a daemon (service)
managed by systemd with automatic program (re)start, follow the directions here.
This is especially useful if you have an always-on server like a Raspberry Pi.
Reasonable precautions have been taken to protect your system - namely, the service
is run as an unpriveleged dynamic user and the filesystem is mounted read-only. See
systemd/disquip-bot.service for more details.
A limited set of pre-built .deb packages are provided for each
release. Download the .deb
approporate for your target machine.
If there is not an appropriate .deb for your OS/architecture, it's relatively easy
to create one for yourself. See the Development section for
prerequisites to build from source. There are several deb* recipes in the justfile
- choose the one that best matches your use case. For building directly on the target,
use the
deb-localrecipe, e.g.just deb-local.
Prior to installation, we need to set up the Discord token and audio files. For the token:
# Use your favorite editor to put the token in the file.
# Avoid printing the token to the shell console so it doesn't
# wind up in shell history.
The program will look for audio files in /usr/share/disquip-bot/audio. You can
directly place the audio file tree here (recommended), or use a symbolic link.
Direct placement:
Alternatively, using a symbolic link:
NOTE: permissions can be tricky with the symbolic link approach. The service is run
as a dynamic, unpriveleged user. This user must be able to read and execute (to list
files) in the audio directory, which will not work in your user's home directory,
except maybe in ~/Public.
Finally, we're ready to install the program, which is as simple as:
where name-of-deb.deb is appropriately replaced with the file you either downloaded
or built locally.
Working with the Service
Check service health:
Inspect the logs:
Prevent the service from running on boot:
Manually start the service:
Manually stop the service:
Manually restart the service:
Uninstalling
Additionally, consider deleting the audio files/directory at /usr/share/disquip-bot
Upgrading
Simply install a newer .deb via apt.
Development
Prerequisites
- Rust toolchain
cmake:sudo apt update; sudo apt install cmake- (Optional) just:
cargo install --locked just - (Optional) just-lsp:
cargo install --locked just-lsp - (Optional) cargo-deb:
cargo install --locked cargo-deb
If you choose not to install and use just, you can manually copy + run recipes from
the justfile, which will be referenced throughout.
Cross-compiling (aarch64-unknown-linux-gnu)
Cross-compiling can be a bit of a headache. If possible, consider building directly
on your target instead. In the justfile, recipes that end in -cross signify
they are intended for cross-compilation, while those that end in -local signify
they should be run on the target.
# One time installs:
sudo apt update
sudo apt install -y gcc-aarch64-linux-gnu
rustup target add aarch64-unknown-linux-gnu
# Build:
just build-aarch64-cross
# See also build-rpi4bi-local and build-jetson-cross