| Real-time, two-way bridge between Discourse Chat and Telegram, with first-class support for Telegram forum topics | |
| GitHub - babylai/discourse-telegram-chat-bridge: Real-time two-way bridge between Discourse Chat and Telegram (design phase / POC) · GitHub | |
| How to install plugins in Discourse |
Features
Each Discourse chat channel is mapped to a Telegram chat — either a plain group, or a specific topic in a supergroup with Topics enabled. A message posted on one side shows up on the other within a second or two.
| Discourse → Telegram | Telegram → Discourse | |
|---|---|---|
| Text (with formatting) | ||
| Emojis | ||
| Replies | ||
| Edits | ||
| Deletions | ||
| Photos | ||
| Other files | ||
| Stickers | — |
- Author attribution: bots can’t impersonate users on either platform, so messages carry the author as a bold prefix —
**Maria:** helloin Discourse, maria: in Telegram. - Loop-safe: messages posted by the bridge itself are never relayed back.
- Idempotent jobs: retries and webhook redeliveries never produce duplicate messages.
- Rate-limit aware: on HTTP 429 the job re-enqueues after exactly the wait Telegram asks for.
- Graceful degradation: files over the Bot API limits (20 MB download / 50 MB upload) become an
[file omitted: name (size)]note; unsupported formatting degrades to plain text. /idsetup command: type/idin any group or topic the bot can see and it replies with the ids plus a ready-to-paste mapping line.
Known limitations
- Deletions in Telegram are not synced to Discourse — the Telegram Bot API has no deletion event. This is a platform limitation, not a configuration issue.
- Telegram only lets bots edit their own messages for 48 hours; Discourse edits of older messages are not reflected on the Telegram side.
- Reactions are not bridged.
- Discourse chat threads are not mapped to Telegram topics; thread replies are bridged flat.
Configuration
1. Create the Telegram bot
- Create a bot via @BotFather and copy the token.
- Disable privacy mode (
/setprivacy→ Disable), or the bot only sees/commands.
If the bot is already in a group, remove and re-add it — the change doesn’t apply to existing memberships otherwise. - Add the bot to your group as an admin (it needs Delete messages for deletion sync).
- To bridge into specific topics, enable Topics in the group settings.
2. Configure the site settings (Admin → Plugins → Telegram Bridge): enable the plugin, paste the bot token, and set a random webhook secret (e.g. openssl rand -hex 24).
3. Register the webhook — easiest through the plugin’s own client, which sets the correct allowed_updates for you:
cd /var/discourse
./launcher enter app
rails runner "puts DiscourseTelegramChatBridge::TelegramClient.new.set_webhook(
url: 'https://YOUR-SITE/telegram-bridge/webhook',
secret_token: SiteSetting.telegram_bridge_webhook_secret)"
allowed_updates lives in the webhook registration stored at Telegram, not in the plugin code. If you register manually and omit edited_message, Telegram silently never delivers edits.
4. Map channels — type /id in each group/topic, then add one line per bridged channel to telegram_bridge_mappings:
chat_channel_id:telegram_chat_id:telegram_thread_id
The Discourse channel id is the number at the end of the channel URL (/chat/c/<slug>/<id>); leave the thread id blank for the General topic or a plain group. On every boot and mapping change the plugin logs one active mappings summary line you can grep to confirm what is bridged.
5. Verify — send a message in each direction. If nothing happens, check in order: the active mappings log line, the webhook info (get_webhook_info), and privacy mode.
Settings
| Name | Description |
|---|---|
telegram_bridge_enabled |
Master on/off switch for the bridge. |
telegram_bridge_bot_token |
Telegram Bot API token, issued by @BotFather (secret). |
telegram_bridge_webhook_secret |
Secret validated against Telegram’s X-Telegram-Bot-Api-Secret-Token header on incoming webhook requests (secret). |
telegram_bridge_mappings |
Channel mappings, one per line: chat_channel_id:telegram_chat_id:telegram_thread_id (thread id optional). |
Privacy note: content from bridged channels leaves your Discourse instance and is stored with Telegram (and vice versa). Only channels explicitly listed in the mappings are ever bridged — but do tell the members of those channels.
