From e6ed545880f0fbddaf1e8c836b09538fcb5bad21 Mon Sep 17 00:00:00 2001 From: salvacybersec Date: Mon, 6 Apr 2026 17:18:58 +0300 Subject: [PATCH] docs(17): telegram bot + scheduler context --- .../17-telegram-scheduler/17-CONTEXT.md | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 .planning/phases/17-telegram-scheduler/17-CONTEXT.md diff --git a/.planning/phases/17-telegram-scheduler/17-CONTEXT.md b/.planning/phases/17-telegram-scheduler/17-CONTEXT.md new file mode 100644 index 0000000..46f27fc --- /dev/null +++ b/.planning/phases/17-telegram-scheduler/17-CONTEXT.md @@ -0,0 +1,116 @@ +# Phase 17: Telegram Bot & Scheduled Scanning - Context + +**Gathered:** 2026-04-06 +**Status:** Ready for planning +**Mode:** Auto-generated + + +## Phase Boundary + +Two capabilities: +1. **Telegram Bot** — Long-polling bot using telego v1.8.0. Commands: /scan, /verify, /recon, /status, /stats, /providers, /help, /key, /subscribe. Runs via `keyhunter serve --telegram`. Private chat only. Keys always masked except `/key ` which sends full detail. +2. **Scheduled Scanning** — Cron-based recurring scans using gocron v2.19.1. Stored in SQLite. CLI: `keyhunter schedule add/list/remove`. Jobs persist across restarts. New findings trigger Telegram notification to subscribers. + + + + +## Implementation Decisions + +### Telegram Bot (TELE-01..07) +- **Library**: `github.com/mymmrac/telego` v1.8.0 (already in go.mod from Phase 1 dep planning) +- **Package**: `pkg/bot/` + - `bot.go` — Bot struct, Start/Stop, command registration + - `handlers.go` — command handlers for /scan, /verify, /recon, /status, /stats, /providers, /help, /key + - `subscribe.go` — /subscribe handler + subscriber storage (SQLite table) + - `notify.go` — notification dispatcher (send findings to all subscribers) +- **Long polling**: Use `telego.WithLongPolling` option +- **Auth**: Bot token from config `telegram.token`; restrict to allowed chat IDs from `telegram.allowed_chats` (array, empty = allow all) +- **Message formatting**: Use Telegram MarkdownV2 for rich output +- **Key masking**: ALL output masks keys. `/key ` sends full key only to the requesting user's DM (never group chat) +- **Command routing**: Register each command handler via `bot.Handle("/scan", scanHandler)` etc. + +### Scheduled Scanning (SCHED-01..03) +- **Library**: `github.com/go-co-op/gocron/v2` v2.19.1 (already in go.mod) +- **Package**: `pkg/scheduler/` + - `scheduler.go` — Scheduler struct wrapping gocron with SQLite persistence + - `jobs.go` — Job struct + CRUD in SQLite `scheduled_jobs` table +- **Storage**: `scheduled_jobs` table: id, name, cron_expr, scan_command, notify_telegram, created_at, last_run, next_run, enabled +- **Persistence**: On startup, load all enabled jobs from DB and register with gocron +- **Notification**: On job completion with new findings, call `pkg/bot/notify.go` to push to subscribers +- **CLI commands**: Replace `schedule` stub in cmd/stubs.go with: + - `keyhunter schedule add --name=X --cron="..." --scan= [--notify=telegram]` + - `keyhunter schedule list` + - `keyhunter schedule remove ` + - `keyhunter schedule run ` (manual trigger) + +### Integration: serve command +- `keyhunter serve [--telegram] [--port=8080]` +- If `--telegram`: start bot in goroutine, start scheduler, block until signal +- If no `--telegram`: start scheduler + web server only (Phase 18) +- Replace `serve` stub in cmd/stubs.go + +### New SQLite Tables +```sql +CREATE TABLE IF NOT EXISTS subscribers ( + chat_id INTEGER PRIMARY KEY, + username TEXT, + subscribed_at DATETIME DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS scheduled_jobs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT UNIQUE NOT NULL, + cron_expr TEXT NOT NULL, + scan_command TEXT NOT NULL, + notify_telegram BOOLEAN DEFAULT FALSE, + enabled BOOLEAN DEFAULT TRUE, + last_run DATETIME, + next_run DATETIME, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP +); +``` + +### Dependencies +- `github.com/mymmrac/telego` — already indirect in go.mod, promote to direct +- `github.com/go-co-op/gocron/v2` — already indirect, promote to direct + + + + +## Existing Code Insights + +### Reusable Assets +- pkg/engine/ — engine.Scan() for bot /scan command +- pkg/verify/ — verifier for bot /verify command +- pkg/recon/ — Engine.SweepAll() for bot /recon command +- pkg/storage/ — DB for findings, settings +- pkg/output/ — formatters for bot message rendering +- cmd/stubs.go — serve, schedule stubs to replace +- cmd/scan.go — openDBWithKey() helper to reuse + +### Key Integration Points +- Bot handlers call the same packages as CLI commands +- Scheduler wraps the same scan logic but triggered by cron +- Notification bridges scheduler → bot subscribers + + + + +## Specific Ideas + +- /status should show: total findings, last scan time, active scheduled jobs, bot uptime +- /stats should show: findings by provider, top 10 providers, findings last 24h +- Bot should rate-limit commands per user (1 scan per 60s) +- Schedule jobs should log last_run and next_run for monitoring + + + + +## Deferred Ideas + +- Webhook notifications (Slack, Discord) — separate from Telegram +- Inline query mode for Telegram — out of scope +- Multi-bot instances — out of scope +- Job output history (keep last N results) — defer to v2 + +