mirror of
https://github.com/tiennm99/miti99bot.git
synced 2026-04-17 19:22:09 +00:00
grammY-based bot with a module plugin system loaded from the MODULES env var. Three command visibility levels (public/protected/private) share a unified command namespace with conflict detection at registry build. - 4 initial modules (util, wordle, loldle, misc); util fully implemented, others are stubs proving the plugin system end-to-end - util: /info (chat/thread/sender ids) + /help (pure renderer over the registry, HTML parse mode, escapes user-influenced strings) - KVStore interface with CFKVStore and a per-module prefixing factory; getJSON/putJSON convenience helpers; other backends drop in via one file - Webhook at POST /webhook with secret-token validation via grammY's webhookCallback; no admin HTTP surface - Post-deploy register script (npm run deploy = wrangler deploy && node --env-file=.env.deploy scripts/register.js) for setWebhook and setMyCommands; --dry-run flag for preview - 56 vitest unit tests across 7 suites covering registry, db wrapper, dispatcher, help renderer, validators, and HTML escaper - biome for lint + format; phased implementation plan under plans/
8.3 KiB
8.3 KiB
Phase 09 — Deploy + docs
Context Links
- Plan: plan.md
- Reports: wrangler + secrets
- All prior phases
Overview
- Priority: P1 (ship gate)
- Status: pending
- Description: first real deploy + documentation. Update README with setup/deploy steps, add an "adding a new module" guide, finalize
wrangler.tomlwith real KV IDs.
Key Insights
- Deploy is a single command —
npm run deploy— which chainswrangler deploy+ the register script from phase-07. No separate webhook registration or admin curl calls. - First-time setup creates two env files:
.dev.vars(forwrangler dev) and.env.deploy(forscripts/register.js). Both gitignored. Both have.examplesiblings committed. - Production secrets for the Worker still live in CF (
wrangler secret put). The register script reads its own copies from.env.deploy— same values, two homes (one for the Worker runtime, one for the deploy script). Document this clearly to avoid confusion. - Adding a new module is a 3-step process: create folder, add to
src/modules/index.js, add toMODULES. Document it.
Requirements
Functional
README.mdupdated with: overview, architecture diagram, setup, local dev, deploy, adding a module, command visibility explanation.wrangler.tomlhas real KV namespace IDs (production + preview)..dev.vars.example+.env.deploy.examplecommitted;.dev.vars+.env.deploygitignored.- A single
docs/or inline README section covers how to add a new module with a minimal example.
Non-functional
- README stays < 250 lines — link to plan phases for deep details if needed.
Architecture
N/A — docs phase.
Related Code Files
Create
docs/adding-a-module.md(standalone guide, referenced from README)
Modify
README.mdwrangler.toml(real KV IDs)
Delete
- none
Implementation Steps
- Create KV namespaces:
Paste both IDs into
wrangler kv namespace create miti99bot-kv wrangler kv namespace create miti99bot-kv --previewwrangler.toml. - Set Worker runtime secrets (used by the deployed Worker):
wrangler secret put TELEGRAM_BOT_TOKEN wrangler secret put TELEGRAM_WEBHOOK_SECRET - Create
.env.deploy(used byscripts/register.jslocally):NOTE:cp .env.deploy.example .env.deploy # then fill in the same TELEGRAM_BOT_TOKEN + TELEGRAM_WEBHOOK_SECRET + WORKER_URL + MODULESWORKER_URLis unknown until after the firstwrangler deploy. For the very first deploy, either (a) deploy once withwrangler deployto learn the URL, fill.env.deploy, then runnpm run deployagain, or (b) use a custom route from the start and put that URL in.env.deployupfront. - Preflight:
All green before deploy.
npm run lint npm test npm run register:dry # prints the payloads without calling Telegram - Deploy (one command from here on):
This runs
npm run deploywrangler deploy && npm run register. The register step calls Telegram'ssetWebhook+setMyCommandswith values from.env.deploy. - Smoke test in Telegram:
- Type
/in a chat with the bot — confirm the popup lists exactly the public commands (/info,/help,/wordle,/loldle,/ping). No protected, no private. /infoshows chat id / thread id / sender id./helpshows util + wordle + loldle + misc sections with public + protected commands; private commands absent./wordle,/loldle,/pingrespond./wstats,/lstats,/mstatsrespond (visible in/helpbut NOT in the/popup)./konami,/ggwp,/fortytworespond when typed, even though they're invisible everywhere.
- Type
- Write
README.md:- Badge-free, plain.
- Sections: What it is, Architecture snapshot, Prereqs, Setup (KV + secrets +
.env.deploy), Local dev, Deploy (npm run deploy), Command visibility levels, Adding a module, Troubleshooting. - Link to
docs/adding-a-module.mdand toplans/260411-0853-telegram-bot-plugin-framework/plan.md.
- Write
docs/adding-a-module.md:- Step 1: Create
src/modules/<name>/index.jsexporting default module object. - Step 2: Add entry to
src/modules/index.jsstatic map. - Step 3: Add
<name>toMODULESin bothwrangler.toml(runtime) and.env.deploy(so the register script picks up new public commands). - Minimal skeleton code block.
- Note on DB namespacing (auto-prefixed).
- Note on command naming rules (
[a-z0-9_]{1,32}, no leading slash, uniform across all visibilities). - Note on visibility levels (public → in
/menu +/help; protected → in/helponly; private → hidden slash command).
- Step 1: Create
- Troubleshooting section — common issues:
- 401 on webhook →
TELEGRAM_WEBHOOK_SECRETmismatch betweenwrangler secretand.env.deploy. They MUST match. /helpempty for a module → check module exportsdefault(not named export).- Module loads but no commands → check
MODULESincludes it (in bothwrangler.tomlAND.env.deploy). - Command conflict error at deploy → two modules registered the same command name; rename one.
npm run registerexits withmissing env: X→ fillXin.env.deploy.- Node < 20.6 →
--env-fileflag unsupported; upgrade Node.
- 401 on webhook →
Todo List
- Create real KV namespaces + paste IDs into
wrangler.toml - Set both runtime secrets via
wrangler secret put(TELEGRAM_BOT_TOKEN,TELEGRAM_WEBHOOK_SECRET) - Create
.env.deployfrom example (token, webhook secret, worker URL, modules) npm run lint+npm test+npm run register:dryall greennpm run deploy(chainswrangler deploy+ register)- End-to-end smoke test in Telegram (9 public/protected commands + 3 private slash commands)
README.mdrewritedocs/adding-a-module.mdguide- Commit + push
Success Criteria
- Bot responds in Telegram to all 11 slash commands (util:
/info+/helppublic; wordle:/wordlepublic,/wstatsprotected,/konamiprivate; loldle:/loldlepublic,/lstatsprotected,/ggwpprivate; misc:/pingpublic,/mstatsprotected,/fortytwoprivate). - Telegram
/menu shows exactly 5 public commands (/info,/help,/wordle,/loldle,/ping) — no protected, no private. /helpoutput lists all four modules and their public + protected commands only.- Private slash commands (
/konami,/ggwp,/fortytwo) respond when invoked but appear nowhere visible. npm run deployis a single command that goes from clean checkout to live bot (after first-time KV + secret setup).- README is enough for a new contributor to deploy their own instance without reading the plan files.
docs/adding-a-module.mdlets a new module be added in < 5 minutes.
Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Runtime and deploy-script secrets drift out of sync | Med | High | Document that both .env.deploy and wrangler secret must hold the SAME TELEGRAM_WEBHOOK_SECRET; mismatch → 401 loop |
| KV preview ID accidentally used in prod | Low | Med | Keep preview_id and id clearly labeled in wrangler.toml |
.dev.vars or .env.deploy committed by mistake |
Low | High | Gitignore both; pre-commit grep for common token prefixes |
| Bot token leaks via error responses | Low | High | grammY's default error handler does not echo tokens; double-check logs |
Security Considerations
TELEGRAM_BOT_TOKENnever appears in code, logs, or commits..dev.vars+.env.deployin.gitignore— verified before first commit.- README explicitly warns against committing either env file.
- Webhook secret rotation: update
.env.deploy, runwrangler secret put TELEGRAM_WEBHOOK_SECRET, thennpm run deploy. The register step re-calls Telegram'ssetWebhookwith the new secret on the same run. Single command does the whole rotation. - Bot token rotation (BotFather reissue): update both
.env.deployandwrangler secret put TELEGRAM_BOT_TOKEN, thennpm run deploy.
Next Steps
- Ship. Feature work begins in a new plan after the user confirms v1 is live.
- Potential follow-ups (NOT in this plan):
- Replace KV with D1 for relational game state.
- Add per-user rate limiting.
- Real wordle/loldle/misc game logic.
- Logging to Cloudflare Logs or external sink.