Contributing to Bot

The purpose of this guide is to get you a running local version of the Python bot. This page will focus on the quickest steps one can take, with mentions of alternatives afterwards.

Clone The Repository

First things first, to run the bot's code and make changes to it, you need a local version of it (on your computer).


You will need to create a fork of the project, and clone the fork. Once this is done, you will have completed the first step towards having a running version of the bot.

Working on the Repository Directly

If you are a member of the organisation (a member of this list, or in our particular case, server staff), you can clone the project repository without creating a fork, and work on a feature branch instead.


Set Up a Test Server

The Python bot is tightly coupled with the Python Discord server, so to have a functional version of the bot you need a server with channels it can use. It's possible to set the bot to use a single channel for all cogs, but that will cause extreme spam and will be difficult to work with.

You can start your own server and set up channels as you see fit, but for your convenience we have a template for a development server you can use: https://discord.new/zmHtscpYN9E3. Keep in mind that this is not a mirror of the Python server, but a reduced version for testing purposes. A lot of the channels in the Python server were merged.


Set Up a Bot Account

You will need your own bot account on Discord to test your changes to the bot. See here for help with setting up a bot account. Once you have a bot account, invite it to the test server you created in the previous section.

Privileged Intents

It is necessary to explicitly request that your Discord bot receives certain gateway events. The Python bot requires the Server Member Intent to function. In order to enable it, visit the Developer Portal (from where you copied your bot's login token) and scroll down to the Privileged Gateway Intents section. The Presence Intent is not necessary and can be left disabled.

If your bot fails to start with a PrivilegedIntentsRequired exception, this indicates that the required intent was not enabled.


Configure the Bot

You now have both the bot's code and a server to run it on. It's time you to connect the two by changing the bot's configurations.

config.yml

Entering the directory of the cloned code, you will find a file named config-default.yml. This file contains the various configurations we use to make the bot run on the Python Discord server, such as channel and role IDs, and the emojis it works with. It also contains configurations such as how long it takes for a help channel to time out, and how many messages a user needs to voice-verify.

To run the bot in your test server, you will need to override some of those configurations. Create and open a new file in the directory called config.yml. Alternatively, copy the config-default.yml file and rename the copy to config.yml. The bot will first look at the items in config.yml, and will fall back to config-default.yml only if necessary. Note that you don't have to specify all items in config.yml, just the ones you want to override such as channel IDs.

See here for help with obtaining Discord IDs.


If you don't wish to use the provided config.yml above, these are the main sections in config-default.yml that need overriding:

  • guild.id
  • guild.categories
  • guild.channels
  • guild.roles
  • guild.webhooks
  • style.emojis

Additionally:

  • At this stage, set bot.redis.use_fakeredis to true. If you're looking for instructions for working with Redis, see Working with Redis.
  • Set urls.site_api to !JOIN [*DOMAIN, "/api"].
  • Set urls.site_schema and urls.site_api_schema to "http://".

We understand this is tedious and are working on a better solution for setting up test servers.


.env

The second file you need to create is the one containing the environment variables, and needs to be named .env. Inside, add the line BOT_TOKEN=YourDiscordBotTokenHere. See here for help with obtaining the bot token.

The .env file will be ignored by commits.


Run it!

With Docker

You are now almost ready to run the Python bot. The simplest way to do so is with Docker.


In your config.yml file:

  • Set urls.site to "web:8000".
  • If you wish to work with snekbox set urls.snekbox_eval_api to "http://snekbox:8060/eval".

Assuming you have Docker installed and running, enter the cloned repo in the command line and type docker-compose up.

After pulling the images and building the containers, your bot will start. Enter your server and type !help (or whatever prefix you chose instead of !).

Your bot is now running, but this method makes debugging with an IDE a fairly involved process. For additional running methods, continue reading the following sections.

With the Bot Running Locally

The advantage of this method is that you can run the bot's code in your preferred editor, with debugger and all, while keeping all the setup of the bot's various dependencies inside Docker.

  • Append the following line to your .env file: BOT_API_KEY=badbot13m0n8f570f942013fc818f234916ca531.
  • In your config.yml file, set urls.site to "localhost:8000". If you wish to keep using web:8000, then COMPOSE_PROJECT_NAME has to be set.
  • To work with snekbox, set urls.snekbox_eval_api to "http://localhost:8060/eval"

You will need to start the services separately, but if you got the previous section with Docker working, that's pretty simple:

  • docker-compose up web to start the site container. This is required.
  • docker-compose up snekbox to start the snekbox container. You only need this if you're planning on working on the snekbox cog.
  • docker-compose up redis to start the Redis container. You only need this if you're not using fakeredis. For more info refer to Working with Redis.

You can start several services together: docker-compose up web snekbox redis.

Setting Up a Development Environment

The bot's code is Python code like any other. To run it locally, you will need the right version of Python with the necessary packages installed:

  1. Make sure you have Python 3.9 installed. It helps if it is your system's default Python version.
  2. Install Poetry.
  3. Install the dependencies.

With at least the site running in Docker already (see the previous section on how to start services separately), you can now start the bot locally through the command line, or through your preferred IDE.


With More Things Running Locally

You can run additional services on the host, but this guide won't go over how to install and start them in this way. If possible, prefer to start the services through Docker to replicate the production environment as much as possible.

The site, however, is a mandatory service for the bot. Refer to the previous section and the site contributing guide to learn how to start it on the host, in which case you will need to change urls.site in config.yml to wherever the site is being hosted.


Development Tips

Now that you have everything setup, it is finally time to make changes to the bot!

Working with Git

If you have not yet read the contributing guidelines, now is a good time. Contributions that do not adhere to the guidelines may be rejected.

Notably, version control of our projects is done using Git and Github. It can be intimidating at first, so feel free to ask for any help in the server.

Click here to see the basic Git workflow when contributing to one of our projects.

Running tests

This section of the README in the tests repository will explain how to run tests. The whole document explains how unittesting works, and how it fits in the context of our project.

Make sure to run tests before pushing code.

Even if you run the bot through Docker, you might want to setup a development environment in order to run the tests locally.

Lint before you push

As mentioned in the contributing guidelines, you should make sure your code passes linting for each commit you make.

For ease of development, you can install the pre-commit hook with poetry run task precommit, which will check your code every time you try to commit it. For that purpose, even if you run the bot through Docker, you might want to setup a development environment, as otherwise the hook installation will fail.

Reloading parts of the bot

If you make changes to an extension, you might not need to restart the entire bot for the changes to take effect. The command !ext reload <extension_name> re-imports the files associated with the extension. Invoke !ext list for a full list of the available extensions. In this bot in particular, cogs are defined inside extensions.

Note that if you changed code that is not associated with a particular extension, such as utilities, converters, and constants, you will need to restart the bot.

Adding new statistics

Details on how to add new statistics can be found on the statistic infrastructure page. We are always open to more statistics so add as many as you can!


Optional: Working with Redis

In Configure the Bot you were asked to set bot.redis.use_fakeredis to true. If you do not need to work on features that rely on Redis, this is enough. Fakeredis will give the illusion that features relying on Redis are saving information properly, but restarting the bot or the specific cog will wipe that information.

If you are working on a feature that relies on Redis, you will need to enable Redis to make sure persistency is achieved for the feature across restarts. The first step towards that is going to config.yml and setting bot.redis.use_fakeredis to false.

If you're using the Docker image provided in the project's Docker Compose, open your config.yml file. If you're running the bot in Docker, set bot.redis.host to redis, and if you're running it on the host set it to localhost. Set bot.redis.password to null.

Starting Redis Using Other Methods

You can run your own instance of Redis, but in that case you will need to correctly set bot.redis.host and bot.redis.port, and the bot.redis.password value in config-default.yml should not be overridden. Then, enter the .env file, and set REDIS_PASSWORD to whatever password you set.


Optional: Working with Metricity

Metricity is our home-grown bot for collecting metrics on activity within the server, such as what users are present, and IDs of the messages they've sent. Certain features in the Python bot rely on querying the Metricity database for information such as the number of messages a user has sent, most notably the voice verification system.

If you wish to work on a feature that relies on Metricity, for your convenience we've made the process of using it relatively painless with Docker: Enter the .env file you've written for the Python bot, and append the line USE_METRICITY=true. Note that if you don't need Metricity, there's no reason to have it enabled as it is just unnecessary overhead.

To make the Metricity bot work with your test server, you will need to override its configurations similarly to the Python bot. You can see the various configurations in the Metricity repo, but the bare minimum is the guild ID setting. In your local version of the Python bot repo, create a file called metricity-config.toml and insert the following lines:

[bot]
guild_id = replace_with_your_guild_id

To properly replicate production behavior, set the staff_role_id, staff_categories, and ignore_categories fields as well.

Now, docker-compose up will also start Metricity.

If you want to run the bot locally, you can run docker-compose up metricity instead.


Issues?

If you have any issues with setting up the bot, come discuss it with us on the #dev-contrib channel on our server.

If you find any bugs in the bot or would like to request a feature, feel free to open an issue on the repository.


Appendix: Full ENV File Options

The following is a list of all available environment variables used by the bot:

Variable Required Description
BOT_TOKEN Always Your Discord bot account's token (see Set Up a Bot Account).
BOT_API_KEY When running bot without Docker Used to authenticate with the site's API. When using Docker to run the bot, this is automatically set. By default, the site will always have the API key shown in the example below.
BOT_SENTRY_DSN When connecting the bot to sentry The DSN of the sentry monitor.
BOT_TRACE_LOGGERS When you wish to see specific or all trace logs Comma separated list that specifies which loggers emit trace logs through the listed names. If the ! prefix is used, all of the loggers except the listed ones are set to the trace level. If * is used, the root logger is set to the trace level.
BOT_DEBUG In production true or false, depending on whether to enable debug mode, affecting the behavior of certain features. true by default.
REDIS_PASSWORD When not using FakeRedis The password to connect to the Redis database (see Optional: Working with Redis).
USE_METRICITY When using Metricity true or false, depending on whether to enable metrics collection using Metricity (see Optional: Working with Metricity). false by default.
GITHUB_API_KEY When you wish to interact with GitHub The API key to interact with GitHub, for example to download files for the branding manager.
METABASE_USERNAME When you wish to interact with Metabase The username for a Metabase admin account.
METABASE_PASSWORD When you wish to interact with Metabase The password for a Metabase admin account.

Have fun!