TG-GithubBot is a Telegram bot that connects Telegram chats to GitHub repositories. It can create GitHub webhooks, send GitHub activity notifications to Telegram, and let connected GitHub users reply to issues or pull requests directly from Telegram.
- GitHub event notifications in Telegram chats.
- GitHub OAuth login with encrypted token storage.
- Automatic repository webhook creation from Telegram.
- Repository discovery with inline Telegram buttons.
- Per-repository event settings.
- Telegram replies posted back as GitHub issue or pull request comments.
- Reply commands for issue and PR actions:
/close/reopen/approve
- Admin-only repository management in groups.
- MongoDB persistence for users, chats, linked repositories, and webhook IDs.
- Docker Compose deployment with MongoDB included.
This bot uses a flexible, platform-agnostic architecture:
- Telegram Commands: The bot can receive commands via Webhooks (recommended for production VPS) or Long Polling (recommended for Cloud Web Services like Render/Heroku or local development). Switch modes using the
USE_POLLINGenvironment variable. - GitHub Activity: Repository notifications are received via Webhooks for maximum performance.
- Security: All GitHub payloads are validated with a cryptographic signature (
GITHUB_WEBHOOK_SECRET).
The TELEGRAM_WEBHOOK_URL is the public base URL used for GitHub OAuth, GitHub Webhooks, and (optionally) Telegram Webhooks.
Important
When USE_POLLING=false (default), the bot automatically registers its webhook with Telegram at startup. If you switch from Webhook to Polling mode, you may need to manually delete the webhook via the Telegram API if updates stop arriving.
The bot supports a wide range of repository events. For a full technical list of compatible events, see the internal/github/format.go file. Common events include:
- Push / Commit Activity
- Pull Requests (Open, Close, Review, Approve)
- Issues (Open, Close, Comment)
- Workflow Runs (CI/CD Success/Failure)
- Discussions and Releases
- Go 1.26.3 or newer for manual builds.
- Docker and Docker Compose for recommended deployment.
- A Telegram bot token from @BotFather.
- A GitHub OAuth App.
- A public HTTPS URL for the bot.
- MongoDB. Docker Compose starts MongoDB automatically.
- Open @BotFather in Telegram.
- Run
/newbot. - Choose a bot name and username.
- Copy the bot token.
- Use that token as
TELEGRAM_TOKEN.
Optional but recommended BotFather settings:
/setcommands
start - Start the bot
help - Show help
connect - Connect GitHub account
addrepo - Link a repository
removerepo - Unlink a repository
repos - List linked repositories
settings - Configure repository events
privacy - Show privacy policy
logout - Disconnect GitHub account
reload - Refresh admin cache
close - Close an issue or PR
reopen - Reopen an issue or PR
approve - Approve a PR
Create an OAuth App in GitHub:
GitHub -> Settings -> Developer settings -> OAuth Apps -> New OAuth App
Use these values:
Application name: TG-GithubBot
Homepage URL: https://your-domain.com
Authorization callback URL: https://your-domain.com/oauth/callback
After creating the OAuth App, copy:
- Client ID
- Client Secret
Use them as:
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...The bot requests these OAuth scopes:
| Scope | Rationale |
|---|---|
repo |
Full control of private/public repos. Required to create/delete repository webhooks and perform PR actions (Merge/Approve). |
admin:repo_hook |
Required to programmatically manage the webhooks that send notifications to Telegram. |
read:user |
Used to identify the GitHub user and link their account to their Telegram ID. |
Copy the sample file:
cp sample.env .envOn Windows PowerShell:
Copy-Item sample.env .envEdit .env:
# Telegram bot token from BotFather
TELEGRAM_TOKEN=123456:ABC-DEF...
# Public base URL with no trailing slash
TELEGRAM_WEBHOOK_URL=https://your-domain.com
# GitHub OAuth App credentials
GITHUB_CLIENT_ID=Iv1...
GITHUB_CLIENT_SECRET=...
GITHUB_WEBHOOK_SECRET=...
# HTTP server port (Use 10000 for Render, 8080 for Standard/Docker)
PORT=8080
# (Optional) Set to true for Polling (Best for Cloud/Local). Default: false (Webhooks)
USE_POLLING=false
# MongoDB connection string
MONGODB_URI=mongodb://localhost:27017
# MongoDB database name
DATABASE_NAME=github_bot
# Stable 32-byte hex key for encrypting stored tokens
ENCRYPTION_KEY=...Caution
Security Warning: GITHUB_WEBHOOK_SECRET must be a strong, random string. If left as default, unauthorized parties could inject fake GitHub activity into your Telegram chats.
Generate secure secrets:
openssl rand -hex 32Use one generated value for ENCRYPTION_KEY. Use another generated value for GITHUB_WEBHOOK_SECRET.
PowerShell alternative for ENCRYPTION_KEY:
-join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Minimum 0 -Maximum 256) })Important:
ENCRYPTION_KEYmust stay stable. If you change it, stored OAuth tokens and webhook chat tokens can no longer be decrypted.TELEGRAM_WEBHOOK_URLmust be reachable by GitHub over HTTPS.- Do not commit
.env.
Telegram Bot API 9.4 supports custom emoji icons and visual button styles. Button styles are enabled automatically by the bot. Custom emoji icons are optional and can be configured with Telegram custom emoji IDs.
If these variables are not set, the bot still works and uses styled text buttons without custom emoji icons.
TG_BUTTON_ICON_ADD=
TG_BUTTON_ICON_ALL=
TG_BUTTON_ICON_BACK=
TG_BUTTON_ICON_CANCEL=
TG_BUTTON_ICON_CHOOSE=
TG_BUTTON_ICON_CONFIRM=
TG_BUTTON_ICON_CONNECT=
TG_BUTTON_ICON_GITHUB=
TG_BUTTON_ICON_NEXT=
TG_BUTTON_ICON_PREVIOUS=
TG_BUTTON_ICON_PUSH=
TG_BUTTON_ICON_SETTINGS=
TG_BUTTON_ICON_STOP=Use only the raw custom emoji ID as the value. Do not paste the emoji character itself.
Docker Compose is the recommended deployment path.
-
Clone the repository:
git clone https://github.com/bisug/TG-GithubBot.git cd TG-GithubBot -
Create and edit
.env:cp sample.env .env nano .env
-
Start the bot and MongoDB:
docker compose up -d --build
-
Check logs:
docker compose logs -f bot
-
Confirm the health page:
http://your-server-ip:8080
For production, put a reverse proxy such as Caddy, Nginx, Traefik, Cloudflare Tunnel, or a platform HTTPS proxy in front of port 8080.
Install Caddy on your server and point your domain DNS record to the server.
Example Caddyfile:
your-domain.com {
reverse_proxy 127.0.0.1:8080
}Then set:
TELEGRAM_WEBHOOK_URL=https://your-domain.comRestart the bot after changing .env:
docker compose up -d --buildFor local testing, expose port 8080 with a tunnel.
Using ngrok:
docker compose up -d --build
ngrok http 8080Set TELEGRAM_WEBHOOK_URL to the HTTPS ngrok URL:
TELEGRAM_WEBHOOK_URL=https://example.ngrok-free.appUpdate the GitHub OAuth App callback URL to:
https://example.ngrok-free.app/oauth/callback
Restart the bot:
docker compose up -d --buildYou need a running MongoDB instance first.
Example .env for local MongoDB:
MONGODB_URI=mongodb://localhost:27017
DATABASE_NAME=github_bot
PORT=8080Install dependencies and run:
go mod download
go run ./cmd/botBuild a binary:
go build -o bot ./cmd/bot
./botOn Windows PowerShell:
go build -o bot.exe ./cmd/bot
.\bot.exe-
Start a private chat with your bot.
-
Send:
/start -
Connect your GitHub account in private chat:
/connect -
Add the bot to a group if you want group notifications.
-
In the target chat, link a repository:
/addrepo owner/repoOr browse your repositories:
/addrepo -
Configure event settings:
/settings
Existing linked repositories keep their current GitHub webhook event settings. To move an old linked repo to wildcard event delivery, either use /settings and choose "Send me everything", or remove and re-add the repository.
/start - Start the bot
/help - Show help
/connect - Connect GitHub account in private chat
/addrepo [owner/repo] - Link a repository to the current chat
/removerepo [owner/repo] - Unlink a repository from the current chat
/repos - List linked repositories
/settings - Configure linked repository events
/privacy - Show privacy policy
/logout - Clear your stored GitHub token
/reload - Refresh group admin cache
/close - Close an issue or PR when replying to a bot notification
/reopen - Reopen an issue or PR when replying to a bot notification
/approve - Approve a PR when replying to a bot notification
/connectmust be used in private chat.- In groups, only Telegram admins with the "Change Group Info" permission can add/remove repositories or change settings.
- The GitHub user running
/addrepomust have permission to create repository webhooks. - Reply actions use the GitHub token of the Telegram user who sends the reply or command.
- OAuth tokens are encrypted with AES-GCM (256-bit) before being stored in MongoDB.
Pull the latest code and restart:
git pull
docker compose up -d --buildWatch logs:
docker compose logs -f github-botCloud platforms can host the bot as a Web Service. Because these platforms typically have ephemeral filesystems and may spin down during idle time, follow these universal steps for a stable deployment.
Cloud web services do not persist local files. You must use an external MongoDB database:
- MongoDB Atlas: Recommended (has a generous free tier).
- Railway/Heroku Add-ons: You can also use managed MongoDB add-ons provided by your platform.
Use the connection string as your MONGODB_URI.
Configure these variables in your platform's dashboard:
| Variable | Description |
|---|---|
PORT |
Set to 10000 (Render) or 8080 (Standard). Most platforms provide this automatically. |
USE_POLLING |
Set to true for maximum reliability on free tiers. |
TELEGRAM_TOKEN |
Your bot token from @BotFather. |
TELEGRAM_WEBHOOK_URL |
The public URL of your service (e.g., https://my-bot.herokapp.com). |
GITHUB_CLIENT_ID |
From your GitHub OAuth App. |
GITHUB_CLIENT_SECRET |
From your GitHub OAuth App. |
GITHUB_WEBHOOK_SECRET |
A random secret for payload validation. |
ENCRYPTION_KEY |
64 hex characters (32 bytes) for token security. |
MONGODB_URI |
Your external database connection string. |
On cloud platforms (especially free tiers), setting USE_POLLING=true is highly recommended. It bypasses complex networking issues and ensures the bot starts receiving commands the moment the container wakes up.
Update your GitHub OAuth App's Authorization callback URL to match your public service URL:
https://your-service-url.com/oauth/callback
- Stay Awake: Free tiers may sleep. Accessing the public URL or receiving a GitHub event will wake the bot.
- Stable Encryption: Never change your
ENCRYPTION_KEYafter deployment, or you will lose access to stored GitHub tokens. - Webhook Paths: GitHub webhooks will be created automatically at
https://your-service.com/webhook/<token>.
MongoDB stores linked chats, repository webhook IDs, and encrypted OAuth tokens.
Back up the Docker volume:
docker run --rm \
-v tg-githubbot_mongo-data:/data/db \
-v "$PWD:/backup" \
alpine tar czf /backup/mongo-data-backup.tar.gz /data/dbKeep a copy of:
.env- MongoDB data
ENCRYPTION_KEY
Without the original ENCRYPTION_KEY, encrypted tokens cannot be recovered.
Check:
-
TELEGRAM_WEBHOOK_URLis correct. -
TELEGRAM_WEBHOOK_URLhas no path. Usehttps://your-domain.com, nothttps://your-domain.com/oauth/callback. -
The GitHub OAuth App callback URL is exactly:
https://your-domain.com/oauth/callback -
The public URL reaches the bot.
-
Your
ENCRYPTION_KEYdid not change between sending/connectand opening the GitHub callback. -
On Render free, open the Render service URL first if the service is asleep, then send
/connectagain.
If the browser shows Invalid or expired state, return to Telegram and run /connect again. OAuth links are intentionally short-lived.
Check:
- Your domain uses HTTPS.
- The reverse proxy points to port
8080. GITHUB_WEBHOOK_SECRETin.envmatches the secret configured on the GitHub webhook.- The bot logs show no signature validation errors.
The connected GitHub user must have admin rights on the repository because the bot creates repository webhooks.
Check the repository webhook in GitHub:
Repository -> Settings -> Webhooks
Confirm:
- Payload URL starts with
https://your-domain.com/webhook/. - Content type is
application/json. - Secret is set.
- The webhook is active.
- Recent deliveries show HTTP
200.
Telegram admin status is cached. Run:
/reload
Then retry the command.
Run tests:
go test ./... -count=1Format code:
gofmt -w ./cmd ./internalList packages:
go list ./...cmd/bot/main.go Application entry point
internal/config Environment loading
internal/db MongoDB access
internal/cache In-memory TTL cache
internal/bot/commands Telegram commands
internal/bot/callbacks Telegram inline callbacks
internal/bot/middleware Chat tracking middleware
internal/github OAuth, webhook parsing, event formatting
internal/models Shared data models
internal/utils Crypto and Telegram helpers
- Run behind HTTPS.
- Keep
.envprivate. - Keep
ENCRYPTION_KEYstable and backed up. - Use a persistent MongoDB volume.
- Monitor
docker compose logs. - Rotate GitHub OAuth secrets and webhook secrets if leaked.
- Use a dedicated GitHub OAuth App for this bot.
This project is licensed under the MIT License. See LICENSE.
Open an issue on GitHub with logs and reproduction steps.