A Discord bot that creates GitHub issues from Discord messages, either via emoji reactions or the right-click Apps context menu. Built for the Zaparoo project but configurable for any GitHub repository.
- Reaction flow: React to any message with emoji to create a GitHub issue from it
- Context menu: Right-click a message and use "Create Issue" to pick project and type from dropdowns
- Smart context: Gathers surrounding conversation for context, using Gemini to filter relevance
- Default project fallback: If you don't specify a project emoji, the issue is created in the default project
- Follow-up attachment: React with π to attach a later message to an already-created issue as a comment
- Support responses: Right-click context menu commands that post pre-written support replies
- File hosting: Saves attachments locally and embeds them in the issue body
- Role-based authorization: Only users with a specified role can trigger issue creation
- State persistence: Recently created issues are saved to disk so π follow-up survives restarts
React to a message with issue type emoji to create an issue on the default project:
User: "The app crashes when I tap a card"
You react: π
Bot creates: bug issue on default project, replies with link
To target a specific project, react with the project emoji first:
You react: π± (selects App project, bot shows β³)
You react: π (creates bug issue on App)
The project selection expires after 60 seconds.
Right-click any message -> Apps -> Create Issue to open a modal with project and issue type dropdowns.
React with π on any message to attach it as a comment to the most recently created issue in that channel (within the last 24 hours).
Right-click any message -> Apps to find pre-written support reply commands (e.g. "Request Troubleshooting"). These post an embed with links directly in the channel as a reply to the message.
Projects, issue types, and support responses are hardcoded in bot.py. Edit them directly:
PROJECTSβ emoji to(repo, name)mappingISSUE_TYPESβ emoji to label mappingSUPPORT_RESPONSESβ list of context menu support reply commands
Secrets and deployment-specific settings go in .env.
- Go to the Discord Developer Portal
- New Application -> name it -> Create
- Bot tab -> Reset Token -> copy the token
- Enable Privileged Gateway Intents: Message Content Intent
- OAuth2 -> URL Generator:
- Scopes:
bot,applications.commands - Bot Permissions:
Read Messages/View Channels,Send Messages,Add Reactions,Read Message History
- Scopes:
- Open the generated URL to invite the bot to your server
- Discord Settings -> Advanced -> enable Developer Mode
- Create a role for authorized users (Server Settings -> Roles)
- Right-click the role -> Copy Role ID
Option A: Personal access token
- GitHub Settings -> Fine-grained tokens
- Select the target repositories, grant Issues: Read and Write
- Set
GITHUB_TOKENin.env
Option B: GitHub App (issues created as the bot account)
- GitHub Settings -> Developer settings -> GitHub Apps -> New GitHub App
- Grant Issues: Read and Write, subscribe to no events
- Install the app on your repositories
- Set
GITHUB_APP_ID,GITHUB_APP_PRIVATE_KEY_PATH, andGITHUB_APP_INSTALLATION_IDin.env
- Go to Google AI Studio
- Create an API key and set
GEMINI_API_KEYin.env
Gemini is used to generate issue titles and filter relevant conversation context.
cp .env.example .env
# Fill in your tokens
uv run bot.py| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
Yes | Discord bot token |
GEMINI_API_KEY |
Yes | Google Gemini API key |
AUTHORIZED_ROLE_ID |
Yes | Discord role ID for authorized users |
GITHUB_TOKEN |
Yes* | GitHub personal access token |
GITHUB_APP_ID |
Yes* | GitHub App ID |
GITHUB_APP_PRIVATE_KEY_PATH |
Yes* | Path to GitHub App private key PEM file |
GITHUB_APP_INSTALLATION_ID |
Yes* | GitHub App installation ID |
IMAGES_DIR |
No | Directory to save attachments (default: ./images) |
IMAGES_URL |
No | Public base URL for saved attachments |
STATE_DIR |
No | Directory to persist bot state (default: ./state) |
* GitHub auth: set either GITHUB_TOKEN or all three GITHUB_APP_* variables.
The bot saves attachments (images, .txt, .log files) to IMAGES_DIR and embeds them in issue bodies using IMAGES_URL. You need to serve IMAGES_DIR via nginx or similar.
Example nginx config:
location /discord-files/ {
alias /opt/discord-issue-bot/images/;
add_header X-Content-Type-Options nosniff always;
default_type application/octet-stream;
types {
image/png png;
image/jpeg jpg jpeg;
image/gif gif;
image/webp webp;
text/plain txt log;
}
autoindex off;
}Set IMAGES_URL=https://your-domain.com/discord-files and IMAGES_DIR=/path/to/images.
A discord-issue-bot.service file is included. Adjust paths and user, then:
sudo cp discord-issue-bot.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now discord-issue-botAdd ReadWritePaths=/path/to/state to the service file if using STATE_DIR.
Example docker-compose.yml service:
discord-bot:
build: /opt/discord-issue-bot
restart: unless-stopped
env_file: /opt/discord-issue-bot/.env
volumes:
- /path/to/images:/app/images:rw
- /path/to/state:/app/state:rw
- /path/to/key.pem:/app/key.pem:roGNU General Public License v3.0. See LICENSE.