#discord-bot #clip #audio #postgresql #channel #voice #phrase

bin+lib btfm

A Discord bot that plays audio clips based on voice chat

18 releases (10 breaking)

0.21.1 Mar 31, 2023
0.20.0 Feb 17, 2023
0.19.0 Aug 9, 2022
0.17.0 Mar 20, 2022
0.3.0 May 9, 2020

#537 in Web programming

32 downloads per month

GPL-2.0-or-later

99KB
2K SLoC

btfm

CI Security

I don't know how, But They Found Me (BTFM).

btfm is a Discord bot that listens on a voice channel for key phrases, and plays audio clips into the channel in response.

Setup

Discord Registration

You'll need to register a bot with Discord. Go to the Developer application page and create an application.

PostgreSQL

BTFM uses a PostgreSQL database to store audio clip metadata. Install PostgreSQL and create a database. For example:

sudo apt install postgresql postgresql-contrib
sudo systemctl restart postgresql.service
sudo -u postgres createuser btfm
sudo -u postgres createdb btfm
sudo -u postgres psql -c "ALTER USER btfm PASSWORD 'password';"
sudo -u postgres psql -c "ALTER DATABASE btfm OWNER to btfm;"

The btfm-server service will create the database schema when it connects. Any migrations required will also be run automatically on updates.

Configuration

Create a user for the bot:

$ sudo useradd --home-dir=/var/lib/btfm --create-home btfm

An example configuration file:

# The directory where audio clips and other data is stored.
# The server will create two directories in the data directory: "clips" contains
# the uploaded audio clips and "tts_cache" stores any text-to-speech audio it creates.
# The "tts_cache" directory can be safely removed if it grows too large.
data_directory = "/var/lib/btfm/"
# The database created in the prior step; substitute the password as necessary.
database_url = 'postgres://btfm:password@localhost/btfm'
# This is the Discord API token you got during the Discord registration step.
discord_token = 'your discord token here'
# The channel to join when someone enters; this is available by enabling "Developer Mode"
# in the Discord client in the advanced settings, then right-clicking a voice channel and
# copying the ID.
channel_id = 0
# The server ID to join; this is available by enabling "Developer Mode" in the Discord
# client in the advanced settings, then right-clicking a server and copying the ID.
guild_id = 0
# The optional channel to log events to; when a clip is matched the bot will post a message
# in this text channel.
log_channel_id = 0
# Adjust the frequency of playing clips; the odds of a clip being played is
# 1 - e^(-x/rate_adjuster) where "x" is the number of seconds since the last clip was played.
rate_adjuster = 100
# The bot will play a random clip at the interval provided (in seconds)
random_clip_interval = 900
# If set, this is the URL for a mimic3 HTTP API used to convert text-to-speech so the bot can
# talk back.
mimic_endpoint = "http://localhost:8888/api/"

[whisper]
# The path to the OpenAI Whisper model to use for transcription.
model = "/var/lib/btfm/whisper/base.en.pt"

[http_api]
# Where the HTTP API used for management listens.
url = "127.0.0.1:8080"
# The username required to authenticate with the management API
user = "admin"
# The password required to authenticate with the management API
password = "admin"

# To enable TLS for the HTTP API, set the following two keys. If
# TLS should not be used, ensure these keys don't exist.
#
# If set, tls_key must also be set and the HTTP API will use TLS
tls_certificate = "/var/lib/btfm/fullchain.pem"
# If set, tls_certificate must also be set and the HTTP API will use TLS
tls_key = "/var/lib/btfm/privkey.pem"

You can place this, for example, in /var/lib/btfm/btfm.toml.

Python Environment

The Whisper Python API is used to perform transcription, so you need to set up a Python environment and install Whisper. The recommended approach is as follows (assuming you're using Fedora Linux):

sudo dnf install python3-pip
sudo -u btfm bash -c \
    'python3 -m venv --upgrade-deps $HOME/.whisper && \
    $HOME/.whisper/bin/pip install openai-whisper'

Next, test the installation and download the model to use (replace the model as necessary and be sure to adjust the configured model in btfm.toml to match):

sudo -u btfm bash -c '$HOME/.whisper/bin/whisper --model base.en --model_dir $HOME/whisper/ <an audio file>

systemd

An example systemd unit to run BTFM:

[Unit]
Description=BTFM Discord bot
After=network.target

[Service]
Type=simple
User=btfm
Group=btfm
Environment="PATH=/var/lib/btfm/.whisper/bin:/usr/bin:/usr/local/bin/"
Environment="BTFM_CONFIG=/var/lib/btfm/btfm.toml"
Environment="RUST_LOG=warn,btfm=info"
ExecStart=/usr/local/bin/btfm-server run
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

Building

If building from source, install make, autotools, libopus headers, gstreamer headers, libsodium headers, and the openssl headers.

Usage

Add clips and phrases with the btfm clip sub-commands:

btfm clip add --phrase "they found me" "I don't know how, but they found me..." run-for-it-marty.mp3

See btfm clip --help for available sub-commands and options.

Start the bot with btfm-server run. See the systemd unit above for details.

See btfm-server run --help for command line arguments and documentation. To obtain the guild and channel ID, go to your Discord User Settings -> Appearance, and enable Developer Mode. You can then right-click on the server for and select "Copy ID" for the guild ID, and then right-click the voice channel you want the bot to watch and "Copy ID" that as well.

Development environment

If you are so inclined, there is a Dockerfile and some helper scripts in the devel/ folder that you may find to be handy for development. The scripts assume you have podman installed. You can use build.sh to build a development container, and you can use cargo.sh to run Rust's cargo tool inside the container. You can probably guess what test.sh does, if you are somebody's kid and are smart.

Dependencies

~70MB
~1.5M SLoC