A Discord bot for personal friend group. If you don't know me personally, consider how freaking weird it'd be to ask for the access token. Feel free to steal the code though.
View the wiki for a short description on what the Duck does.
https://user-images.githubusercontent.com/3149083/135654217-244d7457-9db9-4c30-a98a-785b25453fd8.mp4
Before running DuckBot, you want to create a virtualenv to develop in. DuckBot runs on python3.10
, so prefer to use that.
python3.10 -m venv --clear --prompt duckbot venv
. venv/bin/activate
pip install --upgrade pip setuptools wheel
SETUPTOOLS_ENABLE_FEATURES="legacy-editable" pip install --editable .[dev]
The dev
extras will also install development dependencies, like pytest
. The installation commands should be run whenever you merge from upstream.
pytest # runs tests, lint and format checks
format # reformats the entire code base
You can also collect code coverage locally using:
pytest --cov=duckbot --cov-branch --cov-report term-missing:skip-covered
Coverage is collected in the github actions. View the Codecov configuration to see the minimum required coverage. Discord.py decorators make it difficult to cover methods directly, so don't aim for 100% coverage.
Before running DuckBot, you need to have a duckbot/.env
file with the API tokens. It should look something like this:
duck@pond$ cat duckbot/.env
DISCORD_TOKEN=thesecrettoken
OPENWEATHER_TOKEN=thesecrettoken
BOT_GITHUB_TOKEN=somesecrettoken
WOLFRAM_ALPHA_TOKEN=broitssecret
OXFORD_DICTIONARY_ID=icanttellyou
OXFORD_DICTIONARY_KEY=itsasecret
ANTHROPIC_API_KEY=itsasecret
You only need the discord token. DuckBot will still function without the others, but features that use the tokens won't work. With your tokens available, you can jam them into your shell environment, so you can run DuckBot. You may want to put this into your bashrc for convenience.
export $(cat duckbot/.env | xargs)
Finally, there are two ways to run DuckBot. For a production-like environment, you should run using docker-compose. This will stand up the database alongside DuckBot.
docker-compose up --build
If your work doesn't need a full setup, you can just run python -m duckbot
for less wait time. Depending on what apt packages you have installed, some features may not work, see the Dockerfile for what packages you'd need. For testing simple new commands though, this works fine enough.
Deployment scripts are written using CDK, the AWS Cloud Development Kit. The CDK dependencies can be installed alongside DuckBot.
SETUPTOOLS_ENABLE_FEATURES="legacy-editable" pip install --editable .[dev,cdk] # run from repository root
You'll then actually need CDK. It's a nodejs package, so you'll need that as well.
npm install -g aws-cdk
To add new secrets (like tokens), app.py
needs to be modified. Add a secret to the existing list of secrets there.
environment_name
: the name of the environment variable in the duckbot code base; also must match the GitHub secret name which houses the actual valueparameter_name
: the name of the AWS Systems Manager parameter, must start with /duckbot
Make sure you also update the docker-compose
file, and this readme to include information on how developers can get their own copy of the secrets.
CDK is just python code at the end of the day, we take advantage of that to make sure the deployment process actually creates the secrets that DuckBot would use in prod.
In app.py
, there's logic which creates the secrets via API calls, taking the value from the current environment. Those same secrets are passed to the stack, which are used to inject the secrets into the duckbot container.
Actually saving the secrets is disabled by default, but is enabled for the GitHub actions deploy step. Writing secrets can be enabled by passing --context write_secrets=true
to a cdk
command.
You'll need AWS credentials to use CDK. The following examples assume you have those credentials saved under a duckbot
AWS CLI profile. The cdk
commands need to be run from the .aws
directory.
You can also technically deploy using CDK, but should avoid that. Let the actions workflows do that.
Synthesize a Stack
cdk synth --profile duckbot
Synthesizing products cdk.out/duckbot.template.json
, the CloudFormation template that you can deploy. It also dumps the YML version out to the console.
Diff a Stack
cdk diff --profile duckbot
Produces a diff between the stack already deployed and what you have locally.