Bot/), built on Telegram.Bot 22, and calls the API’s own public routes with the player’s token.
Commands
How a battle works
- A per-chat cooldown (
BattleCooldownSeconds, 15 s) stops battle spam. - While a battle runs the bot sends a typing heartbeat every
BattleHeartbeatSeconds(4 s) and a “still working” note afterSoftTimeoutSeconds(30 s). - Bot calls to the API time out after
ApiTimeoutSeconds(75 s). - Votes that arrive after the battle state expired get a friendly “vote expired” reply.
Sign-in and sessions
Players sign in with their DualMind email and password inside the chat. The bot exchanges them for a Supabase session and stores it intelegram_sessions (keyed by telegram_chat_id), with the access and refresh tokens encrypted with APP_SECRET. It refreshes expired sessions itself.
Delivery mode and configuration
The bot is enabled only when both a bot token andTelegram:ApiBaseUrl are set. Options bind from the Telegram configuration section (environment variables use Telegram__Name).
In production the API Worker also checks Telegram’s
getWebhookInfo on the first request after each deploy and calls setWebhook if the URL doesn’t point at /api/telegram/webhook.
Run it locally
Set a separate test bot’s token and leaveDeliveryMode on Auto with a localhost ApiBaseUrl: the bot falls back to long polling, so you don’t need a public URL. Never point a local API at the production bot token; Telegram allows only one consumer per bot.