Introduction

This is a simple bot you can spin up and watch your stats for the Advent of Code competition. It uses the JSON API for private leaderboards.

Description

This bot is supposed to be fast, low-overhead (saves money on server hosting) and easy to use. It has one purpose, to help show stats for the AoC challenges in your Discord.

Configuration

This section explains the configuration options available in the auth.toml and log.toml files as well as environment variables as alternative source of settings.

  • Authentication configuration for required login information for both Advent of Code as we as Discord.
  • Logging configuration for terminal and file logging.
  • Environment Variables as overrides or alternative to the TOML files.

File location

The bot expects both auth.toml and log.toml to be located in a config folder in the current working directory. For example, let's say the current directory is /apps/aoc_bot, the structure would be as follows:

apps/
    aoc_bot/        <-- current directory
        config/
            auth.toml  <-- Authentication settings
            log.toml   <-- Logging settings

Authentication

Authentication is needed for the Advent of Code API to get leaderboard statistics as well as the Discord API to send messages as a bot. The configuration is located in config/auth.toml and this bot will look for it in the current working directory from where it was executed.

This section contains all information required to fetch leaderboard statistics from the Advent of Code website.

board_id

This is the board ID from the private leaderboard the bot should fetch information from. This can be found by opening a leaderboard from the AoC page. Once opened the ID is the digits at the end of the URL.

For example, if we would want the ID from the following leaderboard URL, the ID would be 12345:

https://adventofcode.com/2020/leaderboard/private/view/12345
                                                       └─┬─┘
                                                   leaderboard ID

The session cookie is the login cookie of a user that the AoC website uses to for its authentication on all pages. To extract it, log in on the website and open the storage inspector of your browser, locate the cookies area and look for an entry named session.

For example in Firefox this can be done by first opening Hamburger menu -> Web Developer -> Storage Inspector. Then expand the cookies entry, click on the single entry within it and double click on the cell in for the session entry labelled Value and lastly to copy it (CTRL+C).

event_year

This setting is to use the wanted AoC year, the API currently accepts the values 2015, 2016, 2017, 2018, 2019, 2020 and 2021. That is, every year from the first AoC event until today.

This section contains all authentication details needed to send send messages as a bot in Discord through the service's API.

bot_token

The only required setting is this bot token which allows to authenticate as a bot. It can be retrieved from the Discord Developer Portal as follows:

  • First navigate to the Discord Developer Portal and log in if you haven't yet.
  • Create a new application or use an existing one and open it.
  • In the navigation select the Bot area. Here you can find your bot token that you need for this setting.
  • To enable the application for a Discord Server, navigate to the OAuth2 section to generate a URL for the authorization process.
    • In Scopes select the bot scope.
    • In Bot Permissions select the Text Messages and Read Message History permission.
    • Copy the link from the Scopes section and open it in a tab.
    • Select the server where you want to install the application.

schedule

The bot allows to set a recurring automated leaderboard message without request from a user first. To enable it crate a sub-section [discord.schedule] in the config/auth.toml file and set both of the following fields.

interval

The interval describes how often the automated leaderboard should be sent, defined as a cron-job string. For example to send the leaderboard every 2 hours you can use 0 0 */2 * * * * as value.

This format basically defines the following time slots for each value, separated by spaces:

0 0 */2 * * * *
│ │  │  │ │ │ │
│ │  │  │ │ │ └─ year
│ │  │  │ │ └─ day of week
│ │  │  │ └─ month
│ │  │  └─ day of month
│ │  └─ hours
│ └─ minutes
└─ seconds

For further help and examples have a look at crontab guru, although the website has a simpler version without the seconds and year fields.

channel_id

The channel ID is the Discord channel where the leaderboard should be posted. In contrast to a user sent command, where the reply is sent in the same channel as the user's command, the channel is fixed as there is no way of determining the channel dynamically.

This ID can be found in Discord opening the context menu of a channel (right click) and selecting Copy ID to copy it into the clipboard.

To see this option the developer mode must be enabled in the settings under App Settings > Advanced > Developer Mode.

Examples

Below are some example configuration for reference. Please note that you still must replace the authentication related fields with real values to make the setup work.

Basic

This is a sample configuration without any optional settings.

[aoc]
board_id = "12345"
session_cookie = "001122aabbcc"
event_year = 2021

[discord]
bot_token = "abcdef"

Full

The following is a complete configuration file with all optional settings enabled.

[aoc]
board_id = "12345"
session_cookie = "001122aabbcc"
event_year = 2021

[discord]
bot_token = "abcdef"

[discord.schedule]
#          sec  min   hour   day of month   month   day of week   year
#          0    0     0      *             *       *             *
interval = "0 0 0 * * * *"
channel_id = 100

Logging

The bot logs several messages while it is running that can help to understand its current state and aid in debugging errors. This logging section controls where this information is written to and at what verbosity level.

In addition, logs can be written to different backend at the same time. Further details are written below for each supported backend.

To disable any of the backends, comment out or remove the whole section of a backend.

Filter levels

The filter defines the verbosity of error messages. For a production setup it's recommended to set it to warn for the terminal output and info for the file output. This default configuration can be found at the project's config/log.toml.

This setting is available to all log backends and the following values are accepted, ranked from least to most verbose:

  • error: most silent version, only log critical errors.
  • warn: log critical errors and warnings.
  • info: log informative messages, warnings and errors.
  • debug: write messages helpful for debugging purposes and all above type of messages.
  • trace: most verbose, logs very detailed information plus all the other levels.

terminal - Terminal output

This backend writes logs directly to the terminal where the bot is running. It has only one setting, the filter. Refer to the Filter levels area for possible values.

file - File output

This backend writes logs to a file instead of the terminal and has two settings, the filter and the path. Refer to the Filter levels area for possible values of the filter field.

path

This setting defines the path of a file that the backend will append logs to. If the file is missing it will be automatically created.

Examples

Terminal only

Only terminal output is enabled, with debug or worse logs, and no log file will be created.

[terminal]
filter = "debug"

File only

The terminal output will be completely silent and debug or worse logs will be logged to the file aocbot.log.

[file]
filter = "debug"
path = "aocbot.log"

Both

A combination of the above examples, logging only warnings and errors to the terminal and more detailed logs to the aocbot.log file.

[terminal]
filter = "warn"

[file]
filter = "debug"
path = "aocbot.log"

Environment variables

In addition (or as replacement) for configuration files, all possible settings can be done through environment variables. For details about each option, please refer to the appropriate section of the config files.

Available values

The following sections list the available environment variables with links to the respective config file settings.

Advent of Code

These are the AoC related settings from the auth.toml file.

Discord

These are the Discord related settings from the auth.toml file.

Please note: DISCORD_SCHEDULE_INTERVAL and DISCORD_SCHEDULE_CHANNEL_ID must both be set together. Setting only one won't have any effect.

Logging

These are the logging related settings from the log.toml file.

Please note: LOG_FILE_FILTER and LOG_FILE_PATH must both be set together. Setting only one won't have any effect.

Using an .env file

The application allows to set environment variables through a file call .env. This is a common approach that allows to configure applications through env vars without having to define them every time before execution.

Contents of the file are pairs of env var names and values, separated by an equal sign = and each entry separated by newlines \n. Comments can be added by prefixing values with a #. For example:

# .env file contents
AOC_BOARD_ID=12345
AOC_SESSION_COOKIE=00112233aabbccdd

environment variables are automatically loaded from this file if it can be found in the current working directory. Any already defined env var will not be overriden by this file.

Commands

The main feature of this bot is the !aoc command, but it supports some other commands as well. Some of them are related to AoC and some are just for fun or testing purposes.

!ping

The ping command allows to check how long the bot needs to interact with the Discord APIs. After receiving the user's command the bot will respond with a simple message initially and then update it immediately afterwards to measure the time it takes between sending 2 commands to Discord.

!aoc

The main command, giving a large overview of the current members in the configured leaderboard. It renders a list of all members, sorted by their star count together with several statistics.

!top3

This command renders a top 3 stair case with the first 3 members that have the highest star count. Currently the stair case is rendered as ASCII art.

!42

A fun command, for people who read or watched the The Hitchhiker's Guide to the Galaxy book/movie.

Docker

The easiest way to deploy this bot is through Docker. It allows to run it independent of the software installed on the system as Docker isolates its containers from the host. This project comes with a Dockerfile so you only need to build it and are good to go.

Building

Creating the image is straight forward and the same as for any typical Dockerfile. Just navigate to the root of the project and run the following command to build the image:

docker build -t aoc_bot .

This will create the image, tagged with the name aoc_bot. You can choose any name you like.

Running

The built image can be run either directly through Docker, Docker Compose or by other systems that integrate with Docker (for example Terraform, Ansible, Kubernetes, ...).

For example ,the following command runs the bot, assuming all settings are configured through the authentication and logging files.

docker run --rm -it \
  -v $PWD/config/auth.toml:/data/config/auth.toml:ro \
  -v $PWD/config/log.toml:/data/config/log.toml:ro \
  aoc_bot

The following version is an alternative using an .env file to configure the bot as described in the environment variables section.

docker run --rm -it --env-file .env aoc_bot

Docker compose

The project comes with a basic Docker Compose configuration that can be used to run this bot through Docker. It is an equivalent to the above commands but allows easier execution without having to remember all necessary command line options.

docker-compose up --build

It will build the image if it isn't available in the local storage and then execute the bot. Settings are loaded by mounting the config files as well as using the env var file to load environment files for configuration.