Overview
The Telegram transport (internal/transport/telegram/) speaks the Telegram Bot HTTP API directly — no third-party SDK. Long-polling getUpdates for inbound; sendMessage for outbound.
Prerequisites
- A bot. In Telegram, message @BotFather, send
/newbot, choose a name and a_bot-suffixed username. BotFather hands back an HTTP API token that looks like123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11. - The user IDs you want to authorise. Telegram user IDs are numeric. The bot cannot resolve
@usernameto a user ID by itself — the standard trick is to have every authorised user send/startto the bot once, then read thefrom.idfrom the log.
Configuration
telegram:
token: "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
reply_header: ""
allowlist:
- "12345678"
- "98765432"
| Field | Default | Effect |
|---|---|---|
token |
required | Bot token from BotFather. |
base_url |
https://api.telegram.org |
Override for a local Bot API server. |
reply_header |
empty | Prepended to every outbound reply. |
allowlist |
[] |
Telegram user IDs whose messages are handled. |
Command-line
rousseau telegram --token 123456:ABC... --allow 12345678 --allow 98765432
--allow may be repeated.
Long-polling
The transport calls getUpdates with a 30-second PollTimeout by default (internal/transport/telegram/client.go). Every returned update advances an internal offset, so messages are never redelivered even across restarts.
There is no webhook. The daemon needs no inbound HTTP surface.
Message shape
Only text messages are handled. Media, stickers, and voice notes are ignored (a future upgrade could route audio through the same whisper.cpp path as WhatsApp).
Failure modes
| Symptom | Fix |
|---|---|
| No updates arrive | Confirm the bot has been messaged at least once — Telegram does not deliver historic messages. |
| 409 Conflict on getUpdates | Another instance is polling with the same token. Stop the other one. |
| Allowlist rejects a real user | Log the from.id field; user IDs are numeric and do not match @username. |