A Discord bot to streamline running D&D 5e.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Andrew Zhu 83be95b186
Merge pull request #1820 from avrae/2022w26
2 days ago
.github build: remove repo submodule update step 6 days ago
aliasing Fix repr and change message id to constant 3 weeks ago
cogs5e chore: unnecessary async PlayerCombatant.from_character 1 week ago
cogsmisc Update DM tutorial to account for new monster naming scheme 3 weeks ago
ddb Merge pull request #1770 from avrae/zhu/ieffect-rewrite 2 months ago
docs Merge branch 'master' into jokeen/2022w25 1 week ago
gamedata chore(style): use black --preview 1 month ago
res add new token borders to token command 2 years ago
scripts run black pre-commit on repo 4 months ago
tests docs: test fixtures 6 days ago
ui chore(style): use black --preview 1 month ago
utils chore: misc list_get optimization 2 weeks ago
.bandit some more CI skips 4 years ago
.dockerignore 🔧 Add dockerignore 3 years ago
.gitattributes [ci skip] Add gitattributes to repository (#1328) 2 years ago
.gitignore tweak(.gitignore): ignore more cache directories 4 months ago
.pre-commit-config.yaml add pre-commit install file 4 months ago
.pylintrc add some linting config 4 years ago
.readthedocs.yml docs: build using python 3.10 2 months ago
CODE_OF_CONDUCT.md Create CODE_OF_CONDUCT.md 4 years ago
Dockerfile chore: bump python to 3.10 4 months ago
Dockerfile.ci chore: bump python to 3.10 4 months ago
LICENSE Add GNU GPLv3 license 4 years ago
README-docker.md docs: update readmes 5 months ago
README.md feat: cadv/cdis passive ieffect 2 months ago
SECURITY.md docs: update email 3 weeks ago
SUPPORTERS.md update SUPPORTERS 3 years ago
codecov.yml build: codecov informational only 1 week ago
dbot.py chore(style): use black --preview 1 month ago
docker-compose.ci.yml build: add docker tests back for contrib 12 months ago
docker-compose.yml fix(dev): mongo-express env vars in docker-compose 5 months ago
pyproject.toml build: include --preview arg for black config 1 month ago
requirements.txt deps: automation-common@4.1.1 2 weeks ago

README.md

Avrae Discord Bot

Avrae Website

Build Status

Avrae is a Discord bot designed to help you and your friends play D&D online.

You can join the Avrae Development Discord here, and invite Avrae to your own Discord server here!

Key Features

Advanced Dice Roller

With a custom dice parser, Avrae is one of the most advanced dice rollers on Discord, capable of supporting pretty much every type of roll needed to play D&D. Advantage, disadvantage, and crits are built in, you can keep, drop, or reroll dice as needed, dice can explode, and dice can be bounded.

Want to use the dice roller in your own code? Check out the code!

Character Sheet Integration

Avrae can read character sheets from D&D Beyond, Dicecloud, or a Google Sheet, automatically generating macros to roll attacks, ability checks, and saving throws. A player can then simply use a command to make a check, save, attack, or cast, and all necessary rolls will be resolved automatically.

Initiative Tracking

The initiative tracker is a fast way to track combat in a text channel. It supports automatic combatant sorting, HP, AC, resistance, and status effect tracking, and integration with the character sheet manager and 5e content to further streamline combat.

Moddability

Have a feature in mind that isn't already in Avrae? Avrae provides a fully-featured modding API to write your own commands, and a place to share them with the community!

Check out the docs and the Alias Workshop!

Contributing

There are a few options to run Avrae locally. Docker is easier to get started with with less managment of dependencies, but slower and more resource-intensive.

Check out README-docker.md.

Building Manually

Dependencies

Services/OS

Support Files

You'll need to create a Google Drive Service Account. You can find instructions on how to do this here.

Follow steps 1-7 in the For Bots: Using Service Account portion. Rename the JSON avrae-google.json and put it in the project root.

Python Packages

We recommend using a Virtual Environment for Avrae development to prevent package installs from polluting the global Python install. You can create and active a virtual environment by running:

$ python3 --version  # to ensure that you are creating a venv from the right python version
$ python3 -m venv venv
$ source venv/bin/activate
# if the venv was set up correctly, you should see (venv) before your username in the terminal
# run these commands to check the installed version and path
(venv) $ python --version
Python 3.X.X
(venv) $ pip --version
pip X.Y.Z from (project root)/venv/lib/python3.X/site-packages/pip (python 3.X)

To install the dependencies, run:

(venv) $ pip install -r requirements.txt

Optional - You can install the avrae-automation-common and draconic dependencies from your local filesystem rather than pip+git, to make working on depended libraries in parallel easier:

(venv) $ pip install /path/to/automation-common -e
(venv) $ pip install /path/to/draconic -e

Any changes to the library will immediately be picked up in avrae without requiring a reinstall of the library.

Environment Variables

Name Description Used For Set By (dev) Set By (prod) Required?
DISCORD_BOT_TOKEN The bot token used to authenticate to the Discord API. See "Discord Bot Token", below. Connecting to the Discord API you AWS Secrets Manager via Terraform yes
TESTING Whether the bot is running in a dev environment. See "Testing Env Var", below. Also set if test arg supplied in CLI. Enabling certain debug logs you N/A no
ENVIRONMENT The environment the bot is running in. Defaults to development if TESTING is set, or production otherwise. Logs (e.g. Sentry) set to development Terraform yes
GIT_COMMIT_SHA The commit SHA of the running deploy. Cluster coordination key N/A Docker via GH Actions prod only
NUM_CLUSTERS The number of clusters (ECS tasks) Avrae is running across. Defaults to 1. Cluster coordination N/A Terraform prod only
NUM_SHARDS An explicit override for the number of shards to run across all shards. Defaults to dynamic value from Discord. Cluster coordination N/A Terraform (nightly/stg) no
RELOAD_INTERVAL An interval to automatically reload gamedata at, in seconds. Defaults to 0. This should be set to 0. Loading gamedata N/A N/A no
ECS_CONTAINER_METADATA_URI https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-metadata-endpoint-v3-fargate.html Cluster coordination N/A AWS Fargate prod only
DISCORD_OWNER_USER_ID The Discord user ID of the bot administrator. Admin command checks you Terraform yes
MONSTER_TOKEN_ENDPOINT The base URL that monster token paths defined in monster gamedata are relative to. !token N/A Terraform prod only
DRACONIC_SIGNATURE_SECRET The secret used to sign signatures in the Draconic API's signature() function. Defaults to secret. Aliasing optional AWS Secrets Manager via Terraform prod only
MONGO_URL The connection URL used to connect to MongoDB. Defaults to mongodb://localhost:27017. Connecting to database you AWS Secrets Manager via Terraform yes
MONGODB_DB_NAME The name of the database in Mongo to use. Defaults to avrae. Connecting to database optional Terraform no
REDIS_URL The connection URL used to connect to Redis. Defaults to redis://localhost:6379/0. Connecting to database you Terraform yes
REDIS_DB_NUM The database number to use in Redis. Defaults to 0. Connecting to database optional Terraform no
DEFAULT_PREFIX The default command prefix. Defaults to !. Running commands optional Terraform no
SENTRY_DSN The Sentry DSN used to send exceptions to Sentry. If not set, no errors are sent to Sentry. Monitoring optional AWS Secrets Manager via Terraform prod only
DD_SERVICE The name of the service, used for DataDog. If not set, disables DataDog tracing and profiling. Monitoring optional Terraform prod only
NO_DICECLOUD If set, disables all Dicecloud connections in the running bot. Defaults to true if DICECLOUD_USER is not set. CI optional N/A no
DICECLOUD_USER The Dicecloud username of the bot account. Sheet Import you Terraform yes
DICECLOUD_PASS The Dicecloud password of the bot account. Sheet Import you AWS Secrets Manager via Terraform yes
DICECLOUD_TOKEN The Dicecloud API key of the bot account. Sheet Import you AWS Secrets Manager via Terraform yes
GOOGLE_SERVICE_ACCOUNT The contents of the Google Drive Service Account JSON key file. Defaults to a file named avrae-google.json if not set. Sheet Import you AWS Secrets Manager via Terraform yes
DDB_AUTH_SECRET The secret used to sign JWT claims to exchange Discord user info for a STT via the Auth Service. Entitlements 1Password AWS Secrets Manager via Terraform DDB team only
DDB_AUTH_WATERDEEP_SECRET The secret used to verify JWTs returned from the Auth Service. Entitlements 1Password AWS Secrets Manager via Terraform DDB team only
DDB_AUTH_AUDIENCE Override a verification for the aud claim of an Auth Service JWT. Defaults to avrae.io. Entitlements N/A N/A no
DDB_AUTH_ISSUER Override a verification for the iss claim of an Auth Service JWT. Defaults to dndbeyond.com. Entitlements N/A N/A no
DDB_AUTH_EXPIRY_SECONDS Override a JWT's lifetime for the Discord -> STT exchange. Defaults to 5 minutes (300). Entitlements N/A N/A no
DDB_AUTH_SERVICE_URL The base URL for requests to the DDB Auth Service. If not set, all entitlements code is disabled. Entitlements 1Password Terraform DDB team only
DYNAMO_REGION The AWS region to search for resources in. This controls more than Dynamo. Defaults to us-east-1. Entitlements 1Password Terraform DDB team only
DYNAMO_ENTITLEMENTS_TABLE The name of the DynamoDB table to query for entitlements data. Defaults to entitlements-live. Entitlements 1Password Terraform DDB team only
AWS_ACCESS_KEY_ID The AWS Access Key ID to connect to AWS resources. Entitlements 1Password AWS Fargate DDB team only
AWS_SECRET_ACCESS_KEY The AWS Secret Access Key to connect to AWS resources. Entitlements 1Password AWS Fargate DDB team only
NLP_KINESIS_DELIVERY_STREAM The name of the AWK Kinesis Firehose delivery stream used to ingest NLP events. UPenn NLP N/A Terraform no
CHARACTER_COMPUTATION_ENDPOINT The API endpoint used to call the Character Computation lambda. Sheet Import you Terraform DDB team only
DDB_WATERDEEP_URL The base URL for requests to the Waterdeep monoloth. Defaults to https://www.dndbeyond.com. Campaign Link 1Password Terraform no
DDB_GAMELOG_ENDPOINT The endpoint used to post Game Log events to the Game Log. Defaults to https://game-log-rest-live.dndbeyond.com/v1. Campaign Link 1Password Terraform no
DDB_CHARACTER_SERVICE_URL The base URL for requests to the Character Service. Defaults to https://character-service.dndbeyond.com/character/v5. Campaign Link 1Password Terraform no
DDB_SCDS_SERVICE_URL The base URL for requests to the Simple Character Data Store. Defaults to https://character-service-scds.dndbeyond.com/v1. Campaign Link 1Password Terraform no
LAUNCHDARKLY_SDK_KEY The LaunchDarkly SDK Key. Feature Flags 1Password AWS Secrets Manager via Terraform DDB team only
DBL_TOKEN The Discord Bot List API token. Updating server count N/A AWS Secrets Manager via Terraform no

Discord Bot Token

To create a Discord bot user, go to the Discord Developer Portal.

  • New Application, give it a cool name, Create.
  • Bot > Add Bot.
  • (Optional but recommended): Switch off Public Bot so only you can add this bot to servers.
  • Scroll down to Privileged Gateway Intents, and enable the switches to the right of Server Members Intent and Message Content Intent.
  • Click to Reveal Token, this is your DISCORD_BOT_TOKEN.

Testing Env Var

The TESTING env var, if present, enables/disables the following:

  • Dicecloud Client: Meteor debug logs enabled
  • cogs.publicity: Discord Bot List update disabled
  • config: ENVIRONMENT set to development by default if not manually set
  • Discord Application Commands: enables command sync debug logs and command testing guilds

Running

(venv) $ python dbot.py test
VSCode launch.json Template
  {
    "version": "0.2.0",
    "configurations": [
      {
        "name": "Run Avrae",
        "type": "python",
        "request": "launch",
        "program": "dbot.py",
        "console": "integratedTerminal",
        "env": {
          "DISCORD_BOT_TOKEN":" ",
          "DISCORD_OWNER_USER_ID": " ",
          "DICECLOUD_USER": " ",
          "DICECLOUD_PASS": " ",
          "DICECLOUD_TOKEN": " ",
          "MONGO_URL": " ",
          "REDIS_URL": " ",
          "ENVIRONMENT": " ",
          "DDB_AUTH_SECRET": " ",
          "DYNAMO_REGION": " ",
          "DYNAMO_ENTITLEMENTS_TABLE": " ",
          "DDB_AUTH_SERVICE_URL": " ",
          "AWS_ACCESS_KEY_ID": " ",
          "AWS_SECRET_ACCESS_KEY": " ",
          "DDB_AUTH_WATERDEEP_SECRET": " ",
          "CHARACTER_COMPUTATION_ENDPOINT": " ",
          "DDB_WATERDEEP_URL": " ",
          "DDB_GAMELOG_ENDPOINT": " ",
          "DDB_CHARACTER_SERVICE_URL": " ",
          "DDB_SCDS_SERVICE_URL": " ",
          "LAUNCHDARKLY_SDK_KEY": " "
        }
      }
    ]
  }

Testing

This repo contains a pytest test suite that mocks a number of interactions between Avrae and the Discord API, and runs end-to-end tests between user input, bot output, and database state.

These tests can be found in tests/.

Dependencies

(venv) $ pip install -r tests/requirements.txt

Running

Tests can either be run using Docker Compose, or manually.

Docker

docker-compose -f docker-compose.ci.yml -p avrae up -d --build
docker logs -f avrae_tests_1

Once tests complete, it is recommended to clean up the containers with docker-compose down.

Manually

(venv) $ TESTING=1 pytest tests/

In either case, you should set NO_DICECLOUD=1.

Docs

Avrae uses Sphinx to generate documentation for the Aliasing API and Automation Engine. The source for this documentation can be found in docs/.

By default, each push to master will trigger a new build of the docs at https://avrae.readthedocs.io/en/latest/.

You can also build the docs manually:

# install dependencies
(venv) $ cd docs
(venv) $ pip install -r requirements.txt
# build and open browser
(venv) $ make preview
# build
(venv) $ make html

Committing, Formatting, and Linting

Avrae uses Black to format and lint its Python code. Black is automatically run on every commit via pre-commit hook, and takes its configuration options from the pyproject.toml file.

The pre-commit hook is installed by by running pre-commit install from the repo root. The hook's configuration is governed by the .pre-commit-config.yaml file.

Dependencies

In order to run pre-commit or black, they must be installed. These dependencies are contained within the test/requirements.txt file, and can be installed like so:

(venv) $ pip install -r test/requirements.txt