diff --git a/extensions/telegram/src/bot-handlers.runtime.ts b/extensions/telegram/src/bot-handlers.runtime.ts index 4d59e2677c3..b0925baf861 100644 --- a/extensions/telegram/src/bot-handlers.runtime.ts +++ b/extensions/telegram/src/bot-handlers.runtime.ts @@ -193,6 +193,13 @@ export const registerTelegramHandlers = ({ : async () => ({}); return { message, me: ctx.me, getFile }; }; + const isSelfAuthoredTelegramMessage = ( + ctx: Pick, + message: Message, + ): boolean => { + const botId = ctx.me?.id; + return typeof botId === "number" && message.from?.id === botId; + }; const inboundDebouncer = createInboundDebouncer({ debounceMs, resolveDebounceMs: (entry) => @@ -1728,6 +1735,9 @@ export const registerTelegramHandlers = ({ if (!msg) { return; } + if (isSelfAuthoredTelegramMessage(ctx, msg)) { + return; + } const isGroup = msg.chat.type === "group" || msg.chat.type === "supergroup"; const isForum = await resolveTelegramForumFlag({ chatId: msg.chat.id, diff --git a/extensions/telegram/src/bot.create-telegram-bot.test.ts b/extensions/telegram/src/bot.create-telegram-bot.test.ts index 56a93e41d07..cbc4cc139d0 100644 --- a/extensions/telegram/src/bot.create-telegram-bot.test.ts +++ b/extensions/telegram/src/bot.create-telegram-bot.test.ts @@ -507,6 +507,44 @@ describe("createTelegramBot", () => { } }); }); + + it("ignores private self-authored message updates instead of issuing a pairing challenge", async () => { + await withIsolatedStateDirAsync(async () => { + loadConfig.mockReturnValue({ + channels: { telegram: { dmPolicy: "pairing" } }, + }); + readChannelAllowFromStore.mockResolvedValue([]); + upsertChannelPairingRequest.mockClear(); + sendMessageSpy.mockClear(); + replySpy.mockClear(); + + createTelegramBot({ token: "tok" }); + const handler = getOnHandler("message") as (ctx: Record) => Promise; + + await handler({ + message: { + chat: { id: 1234, type: "private", first_name: "Harold" }, + message_id: 1884, + date: 1736380800, + from: { id: 7, is_bot: true, first_name: "OpenClaw", username: "openclaw_bot" }, + pinned_message: { + message_id: 1883, + date: 1736380799, + chat: { id: 1234, type: "private", first_name: "Harold" }, + from: { id: 7, is_bot: true, first_name: "OpenClaw", username: "openclaw_bot" }, + text: "Binding: Review pull request 54118 (openclaw)", + }, + }, + me: { id: 7, is_bot: true, first_name: "OpenClaw", username: "openclaw_bot" }, + getFile: async () => ({ download: async () => new Uint8Array() }), + }); + + expect(upsertChannelPairingRequest).not.toHaveBeenCalled(); + expect(sendMessageSpy).not.toHaveBeenCalled(); + expect(replySpy).not.toHaveBeenCalled(); + }); + }); + it("blocks unauthorized DM media before download and sends pairing reply", async () => { await withIsolatedStateDirAsync(async () => { loadConfig.mockReturnValue({