Skip to content

Blockbot

Blockbot is a Discord bot, written in Python, that is maintained by the Redbrick Webgroup. This project uses hikari, an opinionated microframework, to interface with the Discord API. hikari-arc is the command handler and hikari-miru is the component handler of choice.

File Structure

All bot files are under src/.

  • bot.py
    • Contains the bot configuration and instantiation (e.g. loading the bot extensions).
  • extensions/
    • Contains extensions (files) that are loaded when the bot is started. Extensions are a way to split bot logic across multiple files, commonly used to group different features. Extensions can contain plugins, command, event listeners and other logic. Read more.
  • examples/
    • Contains example extensions with commands, components and more as reference for developers.
  • config.py
    • Configuration secrets and important constants (such as identifiers) are stored here. The secrets are loaded from environment variables, so you can set them in your shell or in a .env file.
  • database.py
    • Contains database configuration and models. Uses SQLAlchemy
  • hooks.py
    • Contains command hooks - functions which run before command invocation to determine whether or not the command should actually be run (e.g. permissions check).
  • utils.py
    • Utility functions are stored here, that can be reused across the codebase.

Installation

Tip

Docker Compose for local development is highly recommended. This is similar to how it is deployed on Redbrick.

Discord Developer Portal

As a prerequisite, you need to have an application registered on the Discord developer portal.

  1. Create a Discord application here.
  2. Go to "OAuth2 > URL Generator" on the left sidebar, select the bot and applications.commands scopes, and then select the bot permissions you need (for development, you can select Administrator).
  3. Go to the generated URL and invite the application to the desired server.

Bot Token

  1. Open the application on the Discord developer portal.
  2. Go to "Bot" on the left sidebar and click Reset Token.
  3. Copy the newly generated token.
  1. Fork, git clone and cd into the blockbot repository.

    Tip

    Read the contributing docs for more information on using Git and GitHub.

  2. Rename .env.sample to .env inside the repo folder and fill in the environment variables with your secrets. e.g.:

    Text Only
    TOKEN=<Discord bot token here>
    
  3. Run the bot: docker compose up --build bot
    This will also start the database.

Running from source (deprecated)

Blockbot uses uv to manage dependencies and run the project.

  1. Fork, git clone and cd into the blockbot repository.

    Tip

    Read the contributing docs for more information on using Git and GitHub.

  2. It is generally advised to work in a Python virtual environment:

    Bash
    uv venv
    source .venv/bin/activate
    
  3. Rename .env.sample to .env inside the repo folder and fill in the environment variables with your secrets. e.g.:

    Text Only
    TOKEN=<Discord bot token here>
    
  4. Run uv sync --frozen to install the required packages.

  5. Start the bot by running uv run -m src.

    Note

    Currently a valid database connection is required for the bot to start. Therefore we recommend running Blockbot with docker compose (the compose file includes a PostgreSQL service).

Contributing Tools

Blockbot adheres to various code styling and typing rules (listed under [tool.ruff.format] and [tool.ruff.lint] in pyproject.toml).
To make sure you're following these rules when developing Blockbot, we use nox.

nox is configured in a noxfile.py file, located here for Blockbot.

  1. Install nox

    Bash
    uv sync --group nox --frozen
    
  2. Run nox

    Bash
    uv run nox
    

    To run a specific session (e.g. format_fix):

    Bash
    uv run nox -s format_fix
    

  3. Fix any issues nox reports. This could be:

    • code style issues, most of which ruff (the code linter/formatter) will try to fix automatically
    • typing issues found by pyright. These will need to be fixed manually.

    Contact the webmaster if you need assistance fixing any issues!

Library Resources

Usage Guides

hikari

  • Getting Started - first steps of using hikari
  • Events - understanding receiving events from Discord with hikari

hikari-arc

hikari-miru

FAQ

What's the difference between hikari, hikari-arc and hikari-miru?

Why use a hikari.GatewayBot instead of a hikari.RESTBot?

TL;DR: RESTBots do not receive events required for some blockbot features (e.g. starboard), so GatewayBot must be used instead.

GatewayBots connect to Discord via a websocket, and Discord sends events (including interactions) through this websocket. RESTBots run a web server which Discord sends only interactions to (not events) via HTTP requests. These events are required for specific blockbot features, like starboard (which uses reaction create/remove events).

Further reading: https://arc.hypergonial.com/getting_started/#difference-between-gatewaybot-restbot

What's the difference between hikari.GatewayBot, arc.GatewayClient and miru.Client?

  • hikari.GatewayBot is the actual Discord bot. It:
    • manages the websocket connection to Discord
    • sends HTTP requests to the Discord REST API
    • caches information received in events sent by Discord
  • arc.GatewayClient adds additional functionality to hikari.GatewayBot for:
    • splitting the bot across multiple files using extensions
    • grouping commands using plugins
    • easily creating and managing commands and command groups
    • accessing objects globally (in any extension, plugin or command) using dependency injection (e.g. a database connection)
  • miru.Client adds additional functionality to hikari.GatewayBot for:

Do's and Don'ts

  • Always try to get data from the cache before fetching it from the API.

    Python
    # command example
    async def command(ctx: arc.GatewayContext) -> None:
        user = ctx.client.cache.get_user(123)
        if not user:
            user = await ctx.client.rest.fetch_user(123)