Discord bot for BurbSec that lets trusted members submit IRL meetup photos to the burbsec.github.io site via GitHub PR.
- A user with an allowed role replies to a Discord message containing photo(s)
- They mention the bot with a location:
@pixbot northwest - pixbot downloads the image(s), resizes to ≤ 3840×2160 if needed, and converts to WebP
- A pull request is opened on
BurbSec/burbsec.github.ioadding the file(s) tostatic/images/irl/<location>/ - The bot reacts to the user's message with 👍
| Command | Description |
|---|---|
@pixbot <location> |
Reply to a message with images to submit them |
/help |
Show usage instructions and valid locations |
Both require the moderators or Meetup Hosts role.
- Python 3.10+
- A Discord bot token with the Message Content intent enabled
- GitHub credentials — GitHub App (recommended) or a fine-grained PAT
pip install -r requirements.txtThe bot reads the following environment variables. Set them however suits your environment — /etc/environment, a .env file (see .env.example), a secrets manager, or any other method.
Required:
PIXBOT_DISCORD_TOKENGITHUB_APP_ID+GITHUB_APP_PRIVATE_KEY_PATHorGITHUB_TOKEN(see below)
A GitHub App is preferred over a PAT: it isn't tied to any individual user account, and its tokens are short-lived and auto-rotated.
- Go to GitHub → Settings → Developer settings → GitHub Apps → New GitHub App
- Name it (e.g.
pixbot), set the homepage URL to anything - Disable the webhook (uncheck Active)
- Under Repository permissions, set:
- Contents → Read and write
- Pull requests → Read and write
- Click Create GitHub App, then note the App ID
- Scroll to Private keys → Generate a private key — save the downloaded
.pemfile - Click Install App → install it on the
BurbSecorg, scoped toburbsec.github.ioonly - Set:
GITHUB_APP_ID=123456 GITHUB_APP_PRIVATE_KEY_PATH=/path/to/pixbot.private-key.pem
- Go to GitHub → Settings → Developer settings → Personal access tokens → Fine-grained tokens
- Set Resource owner to
BurbSec, restrict to theburbsec.github.iorepository - Permissions: Contents (read/write), Pull requests (read/write), Metadata (read)
- Set:
GITHUB_TOKEN=your_token_here
If both are set, App auth takes precedence.
python bot.pyAll tunables are in config.py:
| Variable | Default | Description |
|---|---|---|
ALLOWED_ROLES |
['moderators', 'Meetup Hosts'] |
Discord role names that can use the bot |
GITHUB_REPO |
BurbSec/burbsec.github.io |
Target repository |
IMAGES_BASE_PATH |
static/images/irl |
Base path for images in the repo |
GITHUB_BASE_BRANCH |
main |
Branch PRs are opened against |
FALLBACK_LOCATIONS |
(list) | Used if GitHub is unreachable at startup |
Valid locations are fetched live from the repo on each submission. The fallback list is only used if the GitHub API is unavailable.
When creating the bot in the Discord Developer Portal:
- Under Bot → Privileged Gateway Intents, enable Message Content Intent
- Under OAuth2 → URL Generator, grant the
botandapplications.commandsscopes - Required bot permissions:
Read Messages/View Channels,Send Messages,Read Message History,Add Reactions
- Accepts any image format Discord supports (JPEG, PNG, GIF, HEIC, etc.)
- Images larger than 3840×2160 are scaled down proportionally using Lanczos resampling
- All images are saved as WebP at quality 90
- Multiple images in a single message are bundled into one PR on one branch
Branches follow the pattern pixbot/<location>-YYYYMMDD-HHMMSS (UTC), e.g. pixbot/northwest-20260221-183042.