Telegram notifications for GitHub issues — the moment they're opened, closed, or reopened. Works with any public repository.
- 🔔 Universal tracking — works with any public GitHub repository, no admin access required
- ✨ AI summaries — every notification includes a 1-2 sentence Gemini-powered summary of the issue
- 🔁 Full issue lifecycle — alerts for
opened,closed, andreopenedevents - 🏷️ Keyword filtering — subscribe only to issues matching specific terms in title, body, or labels
- 🔍 Repository search — find and track by name or
owner/repowith inline one-tap tracking - 🗂️ Easy management — list and untrack repositories via commands or inline buttons on every notification
- 👑 Admin tools — AI-polished broadcast messages and system stats
IssueNotified runs as a single FastAPI + python-telegram-bot process. All Telegram updates arrive via webhook managed in the FastAPI lifespan context. GitHub issue tracking is done exclusively via polling.
┌─────────────────────────────────────────────┐
Telegram ───▶ │ POST /telegram │
│ Verifies X-Telegram-Bot-Api-Secret-Token │
│ → PTB Application.process_update() │
│ │
JobQueue ───▶ │ poll_repositories() │
│ Runs every 5 min via PTB JobQueue │
│ → Fetches GitHub Events API per repo │
│ ├─ Deduplicate via tracked_issues DB │
│ ├─ AI summary (Gemini) │
│ └─ Fan out to all subscribers │
│ │
Monitoring ─▶ │ GET /health │
└─────────────────────────────────────────────┘
Every 5 minutes the PTB JobQueue fires poll_repositories, which fetches the latest issue events for every tracked repository from the GitHub Events API. New events are deduplicated, enriched with an AI summary, and dispatched to all subscribers who match the keyword filter for that repo.
Issue events are stored in the tracked_issues table before notifications are dispatched. This means a mid-send crash cannot re-notify on restart, and duplicate poll cycles are silently ignored.
src/ai.py holds a singleton AIClient that calls the Gemini REST API directly over aiohttp. It includes automatic retry with exponential backoff and a 15s timeout. If the key is absent or all retries fail, notifications fall back to a 280-character description excerpt with no user-visible error.
A sliding-window limiter in src/ratelimit.py governs GitHub API calls (5,000 req/hour) and the Telegram webhook endpoint (60 req/min per IP).
IssueNotified/
├── src/
│ ├── main.py # Entry point — configures logging, starts uvicorn
│ ├── webhook.py # FastAPI app: lifespan, middleware, /telegram route
│ ├── config.py # All env-var config, validated at import time
│ ├── poller.py # Background polling engine (PTB JobQueue)
│ ├── notifier.py # Shared notification helpers (format, filter, markup)
│ ├── github.py # Async GitHub API client and issue event parser
│ ├── ai.py # Gemini AI client with retry/backoff
│ ├── database.py # SQLite layer (WAL mode, FK enforcement, RLock)
│ ├── ratelimit.py # Async sliding-window rate limiter
│ ├── validators.py # Input validation helpers
│ ├── error.py # Global PTB error handler
│ └── callbacks/ # One module per bot command
│ ├── start.py # /start
│ ├── help.py # /help
│ ├── track.py # /track (conversation handler)
│ ├── untrack.py # /untrack (inline buttons)
│ ├── list.py # /list
│ ├── search.py # /search + inline one-tap tracking
│ ├── stop.py # /stop (account deletion)
│ ├── feedback.py # /feedback
│ ├── stats.py # /stats (admin only)
│ └── broadcast.py # /broadcast (admin, AI-polished)
├── tests/ # pytest suite — 41 tests
├── data/ # SQLite database (auto-created, gitignored)
├── .env.example
├── requirements.txt
├── README.md
└── SECURITY.md
- Python 3.12+
- Telegram bot token from @BotFather
- GitHub Personal Access Token — classic PAT with
reposcope - Google Gemini API key — optional, free tier at Google AI Studio
- A publicly reachable HTTPS URL (ngrok for local dev, Azure / Heroku for production)
git clone https://github.com/robelasefa/IssueNotified.git
cd IssueNotified
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtcp .env.example .env| Variable | Required | Description |
|---|---|---|
BOT_TOKEN |
✅ | Production bot token from @BotFather |
DEV_BOT_TOKEN |
— | Separate token used when DEBUG=true |
GITHUB_TOKEN |
✅ | GitHub PAT with repo scope |
GEMINI_API_KEY |
— | Enables AI issue summaries |
ADMIN_USER_ID |
— | Your Telegram user ID — unlocks /stats and /broadcast |
WEBHOOK_BASE_URL |
✅ | Public HTTPS root URL, no trailing slash |
WEBHOOK_SECRET |
✅ prod | Secret token for verifying Telegram webhook requests |
PORT |
— | Server port (default: 8443; Azure sets this automatically) |
DEBUG |
— | true → use DEV_BOT_TOKEN + verbose logging |
MAX_REPOS_PER_USER |
— | Per-user repository cap (default: 5) |
Never commit
.env. It is already excluded by.gitignore. SeeSECURITY.mdfor vulnerability reporting guidance.
# Expose a public HTTPS URL for the Telegram webhook
ngrok http 8443
# Copy the https://... URL into WEBHOOK_BASE_URL in .env
python src/main.pyaz webapp config appsettings set --name <app> --resource-group <rg> \
--settings BOT_TOKEN=... GITHUB_TOKEN=... GEMINI_API_KEY=... \
WEBHOOK_BASE_URL=https://<app>.azurewebsites.net \
WEBHOOK_SECRET=... ADMIN_USER_ID=...WEBSITE_INSTANCE_ID is detected automatically — the database persists to /home/data/ rather than the local data/ directory.
| Command | Description |
|---|---|
/start |
Register and receive a welcome message |
/track |
Start tracking a repository |
/untrack |
Stop tracking a repository |
/list |
View all your tracked repositories |
/search <query> |
Search GitHub by name or owner/repo |
/feedback |
Send feedback to the developer |
/stop |
Delete your account and all tracked data |
/help |
Show the command reference |
| Command | Description |
|---|---|
/stats |
Users, repositories, and tracked-issue counts |
/broadcast <message> |
AI-polished announcement sent to all users |
Any public GitHub repository can be tracked — no ownership or admin access required. Simply send the owner/repo name and the bot handles the rest.
Filter per-repository so you're only notified when an issue's title, body, or labels match at least one of your terms:
/track
> torvalds/linux
> memory leak,regression,critical
🔔 NEW ISSUE • facebook/react
#42 — Application crashes on startup with out of memory error
🕐 2026-05-20 01:45 PM UTC (6 minutes ago)
🏷️ `bug` `docker` 👤 @contributor
✨ AI Summary:
The application fails to launch with a Java heap OutOfMemoryError inside Docker.
Increase container memory allocation or tune JVM heap settings.
Every notification includes a 🌐 View on GitHub link and a 🔕 Stop Tracking inline button.
# Windows
venv\Scripts\python -m pytest
# Linux/macOS
source venv/bin/activate && pytest41 tests covering the AI client, database layer, GitHub client, notification formatter, validators, and webhook routes.
| Symptom | Resolution |
|---|---|
| Bot not responding | Confirm the correct token is active (DEBUG=true uses DEV_BOT_TOKEN) |
| No AI summary | Check GEMINI_API_KEY is set; inspect logs for Gemini API error |
| GitHub API 403 | Token may be expired or missing repo scope |
| Notifications not arriving | Check logs for GitHub API errors; confirm the repo is public and GITHUB_TOKEN is valid |
| No notifications after tracking | The poller runs every 5 minutes — wait for the next cycle and check logs |
| Database errors on Azure | Confirm /home/data/ is writable; WEBSITE_INSTANCE_ID must be set by the platform |
Small fixes — open a PR directly. Larger changes — open an issue first to align on approach.
If you find IssueNotified useful, a ⭐ on GitHub helps others discover it.
- Bug reports & feature requests → GitHub Issues
- Direct feedback →
/feedbackin the bot