disquip-bot 0.9.3

A Discord bot to play audio files (quips) on command
disquip-bot-0.9.3 is not a library.
Visit the last successful build: disquip-bot-0.9.4

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

  1. Quick Start
  2. Disclaimers
  3. Usage Within Discord
  4. Setup, Install, and Run

Quick Start

  1. Clone the repository and navigate to it: git clone https://github.com/blthayer/disquip-bot-rs.git; cd disquip-bot-rs.
  2. Place the contents of your Discord bot's API token into a file called token in this directory.
  3. Create subdirectories in the audio directory and populate them with mp3 and/or wav files.
  4. 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:

  1. Set up Discord application, add to your server, download token, save to file with 600 permissions.
  2. Create a directory containing subdirectories of .mp3 and .wav audio files.
  3. Run: disquip-bot /path/to/audio /path/to/token
  4. Use: see Usage Within Discord

Installation methods:

  1. Download a pre-built binary from a release
  2. Download and apt install a pre-packaged .deb from a release
  3. Build binary or .deb from 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.

  1. Log into the Discord developer portal.
  2. Under the "Bot" tab, click "Reset Token."
  3. Copy the contents of the token into a file called token at the top-level of this repository (don't worry, it's ignored by git).
  4. Back in the developer portal under the "Bot" tab, in the "Privileged Gateway Intents" sections toggle "Message Content Intent" on.
  5. 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.

  1. Create subdirectories in the repository's top-level audio directory.
  2. Populate the subdirectories with audio files (.mp3 or .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 !help command to get a listing of built-in commands and their aliases. As an obvious example, don't create a directory named help.
  • 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 it bm for 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 called tm, 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 features list of the symphonia dependency in Cargo.toml and then run cargo 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 (rustc version 1.95.0), should work on older (but recent) versions as well.
  • gcc: Easiest path is to sudo apt update; sudo apt install build-essential
  • cmake: Simply sudo apt update; sudo apt install cmake on a Debian-based Linux system (e.g., Debian, Ubuntu, Pop!_OS, Mint, etc.). Tested with versions 3.22.1 and 3.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:

./run.sh audio token

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:

./disquip-bot audio token

crates.io

cargo install --locked disquip-bot
disquip-bot audio token

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-local recipe, e.g. just deb-local.

Prior to installation, we need to set up the Discord token and audio files. For the token:

sudo mkdir /etc/disquip-bot
sudo touch /etc/disquip-bot/token
sudo chmod 600 /etc/disquip-bot/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.
sudo nano /etc/disquip-bot/token

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:

sudo mkdir -p /usr/share/disquip-bot/audio
sudo cp -r /path/to/my/audio/* /usr/share/disquip-bot/audio/

Alternatively, using a symbolic link:

sudo mkdir /usr/share/disquip-bot
sudo ln -s /path/to/my/audio /usr/share/disquip-bot/audio

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:

sudo apt install ./name-of-deb.deb

where name-of-deb.deb is appropriately replaced with the file you either downloaded or built locally.

Working with the Service

Check service health:

sudo systemctl status disquip-bot

Inspect the logs:

sudo journalctl -u disquip-bot

Prevent the service from running on boot:

sudo systemctl disable disquip-bot

Manually start the service:

sudo systemctl start disquip-bot

Manually stop the service:

sudo systemctl stop disquip-bot

Manually restart the service:

sudo systemctl restart disquip-bot

Uninstalling

sudo systemctl stop disquip-bot
sudo apt remove --purge disquip-bot
sudo rm -r /etc/disquip-bot/token

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