A Deno/V8-based Telegram business management, communication, and automation system, implementing the owner/users/groups model described in the system overview: publishing, editable buttons, scheduling, destination management, access control, and group-mention assistance.
Deno.serve, background jobs via Deno.cron)src/db.ts if you outgrow it)--unstable-kv --unstable-crontelegram-bot/
├── main.ts # webhook server + cron entry point
├── deno.json # tasks + import map
├── .env.example # required environment variables
├── scripts/set_webhook.ts # one-time webhook registration
└── src/
├── config.ts # env var loading
├── types.ts # domain types
├── db.ts # Deno KV persistence layer
├── bot.ts # command/message routing
├── middleware/auth.ts # owner-only / approved-only gates
└── features/
├── destinations.ts # connect/list/remove channels & groups
├── publish.ts # multi-destination publish + wizard
├── buttons.ts # update a button's URL across old posts
├── scheduling.ts # /schedule + cron-driven publication
├── access.ts # request/approve/decline access
├── groupMention.ts # respond only when @mentioned in groups
└── assistance.ts # simple FAQ-style business assistance
OWNER_ID..env.example to .env and fill in BOT_TOKEN, OWNER_ID, a random WEBHOOK_SECRET, and PUBLIC_URL (set after your first deploy).For local testing, the quickest path is a tunnel (e.g. deno task dev behind ngrok http 8000), setting PUBLIC_URL to the tunnel’s HTTPS URL, then running:
deno task setwebhook
deno task dev
main.ts..env.example in the Deno Deploy dashboard.PUBLIC_URL to your *.deno.dev URL, redeploy, then run deno task setwebhook locally (pointing at the same env vars) to register the webhook.Owner commands (only work for the Telegram account matching OWNER_ID):
| Command | Purpose |
|---|---|
/adddestination <label> |
Run inside a channel/group to connect it |
/listdestinations |
List connected destinations and their ids |
/removedestination <id> |
Disconnect a destination |
/publish |
Start the guided publish flow (text → buttons → destinations) |
/schedule <when> \| <dest ids> \| <text> |
Schedule a post, e.g. /schedule 2026-09-10T10:00 \| main-channel,promo \| Big sale tomorrow! |
/changebutton <buttonId> <newUrl> |
Update a button’s destination across every post that used it |
/requests |
Review and approve/decline pending access requests |
User commands:
| Command | Purpose |
|---|---|
/start |
Greeting and basic guidance |
/requestaccess |
Ask the owner for approval to use gated features |
| plain text | Answered by the FAQ-style business assistance handler |
Groups: the bot only responds when explicitly mentioned, e.g. @YourBot price of Product A?.
src/features/assistance.ts has a small keyword-matched FAQ table — swap the answerBusinessQuestion function for an LLM call or CMS lookup as needed.approvedOnly middleware from src/middleware/auth.ts.src/db.ts; replace its internals to move off Deno KV without touching feature code.Following the privacy principle in the system overview, only functionally necessary data is stored permanently (destinations, published posts + button index, schedules, access decisions). In-progress conversation state (the publish wizard) is stored with a 30-minute TTL and expires automatically if abandoned.