docs(groups): explain reading other bots' messages via admin and bot-to-bot mode

This commit is contained in:
tiennm99 committed 2026-10-09 14:38:17 +07:00
1 parent 6f30d13b2d
commit 231fc96b5f
5 files changed
+46 -14

No files matched your search

+7 -7
View File
@@ -177,20 +177,20 @@ so they stay valid. They are sent back as entities rather than re-rendered as
markup, which avoids escaping and re-parsing content the user never wrote as
markup.
**Another bot's message cannot be saved.** Telegram's own rule: *"Bots will not
be able to see messages from other bots regardless of mode."* The reply arrives
with its content stripped, so there is nothing to store and no setting that
would change it.
**Another bot's message needs group setup.** By default Telegram strips another
bot's message out of a reply, so there is nothing to store. It arrives intact
once the bot has Bot-to-Bot Communication Mode enabled and is a group admin; see
[Group setup](deploy-coolify-selfhosted.md#4-group-setup).
Every refusal for a message that could not be *read* — as opposed to one whose
kind is unsupported — ends with the same advice, because it is the only thing
that works: **forward it into the chat and reply to your copy.** A forwarded
kind is unsupported — ends with the same advice, because it works without any
setup: **forward it into the chat and reply to your copy.** A forwarded
copy is a new message sent by a user, so it arrives intact. Three shapes reach
that advice, and they are told apart deliberately:
| What arrived | Answer |
| --- | --- |
| Reply from a sender marked as a bot | Telegram does not let bots read other bots' messages |
| Reply from a sender marked as a bot | Telegram hid that bot's message; admin rights plus Bot-to-Bot Communication fix it |
| Reply with a message id but no content field at all | That message reached me with no content |
| No reply attached at all | Reply to the message you want to save — and if you did, Telegram did not pass it along |
+24
View File
@@ -205,6 +205,30 @@ truth, so no separate command-menu file or manual registration step is
required. See [Command discovery](../README.md#command-discovery) for how the
menu text is built.
## 4. Group setup
By default a bot in a group runs in privacy mode. It receives only commands
addressed to it, replies to its own messages, and service messages, and it
cannot read messages sent by other bots. That breaks two things:
- A bare `/command` typed as a reply to another bot's message is routed to that
other bot. Address this bot explicitly, as `/command@<this bot>`.
- `/addsticker` and `/alias` replying to another bot's message (for example, an
image another bot posted) get the reply with its content stripped.
To make both work in a group:
1. In @BotFather, enable **Bot-to-Bot Communication Mode** for this bot.
2. Promote the bot to **admin** in the group. Admins receive every message, so
no permissions beyond the defaults are needed.
Disabling privacy mode in BotFather (`/setprivacy`) is the alternative to admin
rights, but Telegram applies it only after the bot is removed from the group and
added back. Admin rights take effect immediately. Verified on 2026-10-09:
`/addsticker@<this bot>` replying to another bot's image failed with privacy
mode off and the bot not re-added, and worked once the bot was promoted to admin.
See Telegram's [privacy mode and bot-to-bot rules](https://core.telegram.org/bots/features#privacy-mode).
## Operations
The live deployment is the Coolify container and MongoDB is the sole system of
+4
View File
@@ -113,6 +113,10 @@ exactly 512px with the aspect ratio preserved, uploaded as a PNG, and then
added — attributed to the pack owner, matching the set it is about to join.
Sources above 2 MB, or with either side above 4096px, are rejected.
**Replying to another bot's image** works only after the
[group setup](deploy-coolify-selfhosted.md#4-group-setup); otherwise Telegram
strips the image out of the reply.
## Video and GIF
A replied video, GIF, animation or video note is downloaded and transcoded with
+10 -6
View File
@@ -34,13 +34,17 @@ const unsupportedRefusal = "That message cannot be saved. Reply to a sticker, ph
// the answer to all of them — only the reason differs.
const forwardAdvice = "Forward it into this chat, then reply to your copy with /alias <name>."
// otherBotRefusal explains a refusal no change here can lift.
// otherBotRefusal explains why another bot's message arrived empty.
//
// Telegram's own rule: "Bots will not be able to see messages from other bots
// regardless of mode." The reply arrives with its content stripped, so there is
// nothing to save and no setting that would help — worth saying outright rather
// than letting unsupportedRefusal imply the format was wrong.
const otherBotRefusal = "Telegram does not let bots read other bots' messages, so I cannot save that one. " + forwardAdvice
// Telegram strips another bot's message out of a reply unless this bot has
// Bot-to-Bot Communication Mode enabled in BotFather and receives every group
// message — as a group admin, or with privacy mode off. Both are chat and
// BotFather settings, not code, so the refusal names them alongside the
// forward workaround rather than letting unsupportedRefusal imply the format
// was wrong.
const otherBotRefusal = "Telegram hid that bot's message from me, so I cannot save it. " +
"I can read other bots' messages only when I am an admin in this chat and Bot-to-Bot Communication is on for me in @BotFather. " +
forwardAdvice
// strippedReplyRefusal answers a reply Telegram delivered empty: it carried a
// message id but no content field at all.
+1 -1
View File
@@ -448,7 +448,7 @@ func TestAlias_ExplainsAnotherBotsMessage(t *testing.T) {
From: &models.User{ID: 555, IsBot: true, FirstName: "OtherBot"},
}))
rb.AssertSentText(t, "does not let bots read other bots")
rb.AssertSentText(t, "hid that bot's message")
}
// A human's unsupported message still gets the format advice, not the bot one.