Files
miti99bot/plans/260411-0853-telegram-bot-plugin-framework/plan.md
tiennm99 c4314f21df feat: scaffold plug-n-play telegram bot on cloudflare workers
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/
2026-04-11 09:49:06 +07:00

3.1 KiB

title, description, status, priority, effort, branch, tags, created
title description status priority effort branch tags created
Telegram Bot Plugin Framework on Cloudflare Workers Greenfield JS Telegram bot with plug-n-play modules, KV-backed store, webhook on CF Workers. pending P2 14h main
telegram
cloudflare-workers
grammy
plugin-system
javascript
2026-04-11

Telegram Bot Plugin Framework

Greenfield JS bot on Cloudflare Workers. grammY + KV. Modules load from MODULES env var. Three command visibility levels (public/protected/private). Pluggable DB behind a minimal interface.

Phases

# Phase Status Effort Blockers
01 Scaffold project pending 1h
02 Webhook entrypoint pending 1h 01
03 DB abstraction pending 1.5h 01
04 Module framework pending 2.5h 02, 03
05 util module pending 1.5h 04
06 Stub modules pending 1h 04
07 Post-deploy register script pending 1h 05
08 Tests pending 2.5h 04, 05, 06
09 Deploy + docs pending 2h 07, 08

Key dependencies

  • grammY ^1.30.0, adapter "cloudflare-mod"
  • wrangler (npm), Cloudflare account, KV namespace
  • vitest (plain node pool — pure-logic tests only, no workerd)
  • biome (lint + format, single tool)

Architecture snapshot

  • src/index.js — fetch handler: POST /webhook + GET / health. No admin HTTP surface.
  • src/bot.js — memoized Bot instance + dispatcher wiring
  • src/db/KVStore interface (JSDoc with getJSON/putJSON/list-cursor), cf-kv-store.js, create-store.js (prefixing factory)
  • src/modules/registry.js — load modules, build command tables (public/protected/private + unified allCommands), detect conflicts, expose getCurrentRegistry
  • src/modules/dispatcher.js — grammY middleware: every command in allCommands registered via bot.command() regardless of visibility (private = hidden slash command)
  • src/modules/index.js — static import map { util: () => import("./util/index.js"), ... }
  • src/modules/{util,wordle,loldle,misc}/index.js — module entry points
  • scripts/register.js — post-deploy node script calling Telegram setWebhook + setMyCommands. Chained via npm run deploy = wrangler deploy && npm run register.

Open questions

  1. grammY version pin — pick exact version at phase-01 time (npm view grammy version). Plan assumes ^1.30.0.

Resolved in revision pass (2026-04-11):

  • Private commands are hidden slash commands (same regex, routed via bot.command()), not text-match easter eggs.
  • No admin HTTP surface; post-deploy scripts/register.js handles setWebhook + setMyCommands. ADMIN_SECRET dropped entirely.
  • KV interface exposes expirationTtl, list() cursor, and getJSON / putJSON helpers. No metadata.
  • Conflict policy: unified namespace across all visibilities, throw at buildRegistry.
  • /help parse mode: HTML.