docs(17): create phase plan — Telegram bot + scheduled scanning
This commit is contained in:
165
.planning/phases/17-telegram-scheduler/17-01-PLAN.md
Normal file
165
.planning/phases/17-telegram-scheduler/17-01-PLAN.md
Normal file
@@ -0,0 +1,165 @@
|
||||
---
|
||||
phase: 17-telegram-scheduler
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- pkg/bot/bot.go
|
||||
- pkg/bot/bot_test.go
|
||||
- go.mod
|
||||
- go.sum
|
||||
autonomous: true
|
||||
requirements: [TELE-01]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Bot struct initializes with telego client given a valid token"
|
||||
- "Bot registers command handlers and starts long polling"
|
||||
- "Bot respects allowed_chats restriction (empty = allow all)"
|
||||
- "Bot gracefully shuts down on context cancellation"
|
||||
artifacts:
|
||||
- path: "pkg/bot/bot.go"
|
||||
provides: "Bot struct, New, Start, Stop, RegisterHandlers, auth middleware"
|
||||
exports: ["Bot", "New", "Config", "Start", "Stop"]
|
||||
- path: "pkg/bot/bot_test.go"
|
||||
provides: "Unit tests for Bot creation and auth filtering"
|
||||
key_links:
|
||||
- from: "pkg/bot/bot.go"
|
||||
to: "github.com/mymmrac/telego"
|
||||
via: "telego.NewBot + long polling"
|
||||
pattern: "telego\\.NewBot"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Create the pkg/bot/ package foundation: Bot struct wrapping telego v1.8.0, command registration, long-polling lifecycle, and chat ID authorization middleware.
|
||||
|
||||
Purpose: Establishes the Telegram bot infrastructure that all command handlers (Plan 17-03, 17-04) build on.
|
||||
Output: pkg/bot/bot.go with Bot struct, pkg/bot/bot_test.go with unit tests.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@$HOME/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@$HOME/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/17-telegram-scheduler/17-CONTEXT.md
|
||||
@cmd/stubs.go
|
||||
@pkg/storage/db.go
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add telego dependency and create Bot package skeleton</name>
|
||||
<files>go.mod, go.sum, pkg/bot/bot.go</files>
|
||||
<action>
|
||||
1. Run `go get github.com/mymmrac/telego@v1.8.0` to add telego as a direct dependency.
|
||||
|
||||
2. Create pkg/bot/bot.go with:
|
||||
|
||||
- `Config` struct:
|
||||
- `Token string` (Telegram bot token)
|
||||
- `AllowedChats []int64` (empty = allow all)
|
||||
- `DB *storage.DB` (for subscriber queries, finding lookups)
|
||||
- `ScanEngine *engine.Engine` (for /scan handler)
|
||||
- `ReconEngine *recon.Engine` (for /recon handler)
|
||||
- `ProviderRegistry *providers.Registry` (for /providers, /verify)
|
||||
- `EncKey []byte` (encryption key for finding decryption)
|
||||
|
||||
- `Bot` struct:
|
||||
- `cfg Config`
|
||||
- `bot *telego.Bot`
|
||||
- `updates <-chan telego.Update` (long polling channel)
|
||||
- `cancel context.CancelFunc` (for shutdown)
|
||||
|
||||
- `New(cfg Config) (*Bot, error)`:
|
||||
- Create telego.Bot via `telego.NewBot(cfg.Token)` (no options needed for long polling)
|
||||
- Return &Bot with config stored
|
||||
|
||||
- `Start(ctx context.Context) error`:
|
||||
- Create cancelable context from parent
|
||||
- Call `bot.SetMyCommands` to register command descriptions (scan, verify, recon, status, stats, providers, help, key, subscribe, unsubscribe)
|
||||
- Get updates via `bot.UpdatesViaLongPolling(nil)` which returns a channel
|
||||
- Loop over updates channel, dispatch to handler based on update.Message.Text command prefix
|
||||
- Check authorization via `isAllowed(chatID)` before dispatching any handler
|
||||
- On ctx.Done(), call `bot.StopLongPolling()` and return
|
||||
|
||||
- `Stop()`:
|
||||
- Call cancel function to trigger shutdown
|
||||
|
||||
- `isAllowed(chatID int64) bool`:
|
||||
- If cfg.AllowedChats is empty, return true
|
||||
- Otherwise check if chatID is in the list
|
||||
|
||||
- Handler stubs (will be implemented in Plan 17-03):
|
||||
- `handleScan(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleVerify(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleRecon(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleStatus(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleStats(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleProviders(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleHelp(bot *telego.Bot, msg telego.Message)`
|
||||
- `handleKey(bot *telego.Bot, msg telego.Message)`
|
||||
Each stub sends "Not yet implemented" reply via `bot.SendMessage`.
|
||||
|
||||
- Use telego's MarkdownV2 parse mode for all replies. Create helper:
|
||||
- `reply(bot *telego.Bot, chatID int64, text string) error` — sends MarkdownV2 message
|
||||
- `replyPlain(bot *telego.Bot, chatID int64, text string) error` — sends plain text (for error messages)
|
||||
|
||||
- Per-user rate limiting: `rateLimits map[int64]time.Time` with mutex. `checkRateLimit(userID int64, cooldown time.Duration) bool` returns false if user sent a command within cooldown window. Default cooldown 60s for /scan, /verify, /recon; 5s for others.
|
||||
|
||||
Import paths: github.com/mymmrac/telego, github.com/mymmrac/telego/telegoutil (for SendMessageParams construction).
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/salva/Documents/apikey && go build ./pkg/bot/...</automated>
|
||||
</verify>
|
||||
<done>pkg/bot/bot.go compiles with telego dependency. Bot struct, New, Start, Stop, isAllowed, and all handler stubs exist.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 2: Unit tests for Bot creation and auth filtering</name>
|
||||
<files>pkg/bot/bot_test.go</files>
|
||||
<behavior>
|
||||
- Test 1: New() with empty token returns error from telego
|
||||
- Test 2: isAllowed with empty AllowedChats returns true for any chatID
|
||||
- Test 3: isAllowed with AllowedChats=[100,200] returns true for 100, false for 999
|
||||
- Test 4: checkRateLimit returns true on first call, false on immediate second call, true after cooldown
|
||||
</behavior>
|
||||
<action>
|
||||
Create pkg/bot/bot_test.go:
|
||||
|
||||
- TestNew_EmptyToken: Verify New(Config{Token:""}) returns an error.
|
||||
- TestIsAllowed_EmptyList: Create Bot with empty AllowedChats, verify isAllowed(12345) returns true.
|
||||
- TestIsAllowed_RestrictedList: Create Bot with AllowedChats=[100,200], verify isAllowed(100)==true, isAllowed(999)==false.
|
||||
- TestCheckRateLimit: Create Bot, verify checkRateLimit(1, 60s)==true first call, ==false second call.
|
||||
|
||||
Note: Since telego.NewBot requires a valid token format, for tests that need a Bot struct without a real connection, construct the Bot struct directly (bypassing New) to test isAllowed and rate limit logic independently.
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/salva/Documents/apikey && go test ./pkg/bot/... -v -count=1</automated>
|
||||
</verify>
|
||||
<done>All 4 test cases pass. Bot auth filtering and rate limiting logic verified.</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
- `go build ./pkg/bot/...` compiles without errors
|
||||
- `go test ./pkg/bot/... -v` passes all tests
|
||||
- `grep telego go.mod` shows direct dependency at v1.8.0
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- pkg/bot/bot.go exists with Bot struct, New, Start, Stop, isAllowed, handler stubs
|
||||
- telego v1.8.0 is a direct dependency in go.mod
|
||||
- All unit tests pass
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/17-telegram-scheduler/17-01-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user