From adaa30c73aa9b7cc26f2704be68133d4fc09798c Mon Sep 17 00:00:00 2001 From: Ayaan Zaidi Date: Mon, 12 Jan 2026 22:03:42 +0530 Subject: [PATCH] test(telegram): cover General topic typing fallback --- CHANGELOG.md | 1 + src/telegram/bot.test.ts | 43 ++++++++++++++++++++++++++++++++++++++++ src/telegram/bot.ts | 9 ++------- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f5fc793c..56e09eb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Fixes - Auto-reply: inline `/status` now honors allowlists (authorized stripped + replied inline; unauthorized leaves text for the agent) to match command gating tests. +- Telegram: show typing indicator in General forum topics. (#779) — thanks @azade-c. ## 2026.1.11 diff --git a/src/telegram/bot.test.ts b/src/telegram/bot.test.ts index 829ef1bf2..991075ec6 100644 --- a/src/telegram/bot.test.ts +++ b/src/telegram/bot.test.ts @@ -1676,6 +1676,49 @@ describe("createTelegramBot", () => { }); }); + it("falls back to General topic thread id for typing in forums", async () => { + onSpy.mockReset(); + sendChatActionSpy.mockReset(); + const replySpy = replyModule.__replySpy as unknown as ReturnType< + typeof vi.fn + >; + replySpy.mockReset(); + + loadConfig.mockReturnValue({ + telegram: { + groupPolicy: "open", + groups: { "*": { requireMention: false } }, + }, + }); + + createTelegramBot({ token: "tok" }); + const handler = getOnHandler("message") as ( + ctx: Record, + ) => Promise; + + await handler({ + message: { + chat: { + id: -1001234567890, + type: "supergroup", + title: "Forum Group", + is_forum: true, + }, + from: { id: 12345, username: "testuser" }, + text: "hello", + date: 1736380800, + message_id: 42, + }, + me: { username: "clawdbot_bot" }, + getFile: async () => ({ download: async () => new Uint8Array() }), + }); + + expect(replySpy).toHaveBeenCalledTimes(1); + expect(sendChatActionSpy).toHaveBeenCalledWith(-1001234567890, "typing", { + message_thread_id: 1, + }); + }); + it("applies topic skill filters and system prompts", async () => { onSpy.mockReset(); const replySpy = replyModule.__replySpy as unknown as ReturnType< diff --git a/src/telegram/bot.ts b/src/telegram/bot.ts index e23bac5f7..da2a17a7b 100644 --- a/src/telegram/bot.ts +++ b/src/telegram/bot.ts @@ -1,11 +1,4 @@ // @ts-nocheck -/** - * Telegram uses message_thread_id=1 internally for the General topic in forum supergroups. - * User-created topics have IDs based on message_id (typically millions+), so no collision risk. - * See: https://core.telegram.org/bots/api#sendchataction - */ -const TELEGRAM_GENERAL_TOPIC_ID = 1; - import { sequentialize } from "@grammyjs/runner"; import { apiThrottler } from "@grammyjs/transformer-throttler"; import type { ApiClientOptions, Message } from "grammy"; @@ -79,6 +72,8 @@ import { } from "./pairing-store.js"; import { resolveTelegramVoiceSend } from "./voice.js"; +const TELEGRAM_GENERAL_TOPIC_ID = 1; + const PARSE_ERR_RE = /can't parse entities|parse entities|find end of the entity/i;