From 38181ab4dbecb60b6e48125fe49399b56f9bb6f2 Mon Sep 17 00:00:00 2001 From: Jiayuan Zhang Date: Fri, 13 Feb 2026 22:12:26 +0800 Subject: [PATCH] refactor(gateway): remove group chat support from Telegram bot Group chats have unresolved issues in the Gateway context: - Per-user deviceId causes context overwrites across groups - Reply chains across users route to wrong Hubs - Welcome messages are noisy in groups Restrict to private chats only until a proper group model is designed. Co-Authored-By: Claude Opus 4.6 --- apps/gateway/telegram/telegram.service.ts | 66 +++-------------------- 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/apps/gateway/telegram/telegram.service.ts b/apps/gateway/telegram/telegram.service.ts index 2fbb220c..c01804eb 100644 --- a/apps/gateway/telegram/telegram.service.ts +++ b/apps/gateway/telegram/telegram.service.ts @@ -132,8 +132,6 @@ function chunkText(text: string, maxChars = MAX_CHARS_PER_MESSAGE): string[] { @Injectable() export class TelegramService implements OnModuleInit { private bot: Bot | null = null; - private botId: number | null = null; - private botUsername: string | null = null; private pendingRequests = new Map(); /** Typing indicator timers, keyed by deviceId */ @@ -159,18 +157,8 @@ export class TelegramService implements OnModuleInit { this.bot = new Bot(token); - // Fetch bot identity for group-chat mention detection - try { - const botInfo = await this.bot.api.getMe(); - this.botId = botInfo.id; - this.botUsername = botInfo.username ?? null; - this.logger.log(`Telegram bot initialized: @${this.botUsername} (id=${this.botId})`); - } catch (err) { - const msg = err instanceof Error ? err.message : String(err); - this.logger.error(`Failed to get bot info: ${msg}`); - } - this.setupHandlers(); + this.logger.log("Telegram bot initialized"); } /** Get grammY webhook callback for Express/NestJS */ @@ -220,9 +208,9 @@ export class TelegramService implements OnModuleInit { } }); - // Text messages + // Text messages (private chats only) this.bot.on("message:text", async (ctx) => { - if (!this.shouldProcessMessage(ctx)) return; + if (!this.isPrivateChat(ctx)) return; await this.handleTextMessage(ctx); }); @@ -280,49 +268,15 @@ export class TelegramService implements OnModuleInit { for (const { filter, getMedia } of mediaTypes) { this.bot.on(filter, async (ctx) => { - if (!this.shouldProcessMessage(ctx)) return; + if (!this.isPrivateChat(ctx)) return; await this.handleMediaMessage(ctx, getMedia(ctx.message)); }); } } - // ── Group chat filtering ── - - /** - * Decide whether this message should be processed. - * Private chats: always. Groups: only @mentions or replies to bot. - */ - private shouldProcessMessage(ctx: Context): boolean { - const msg = ctx.message; - if (!msg) return false; - - const isGroup = msg.chat.type === "group" || msg.chat.type === "supergroup"; - if (!isGroup) return true; - - // Check text entities for @mention - if (this.botUsername) { - const text = (msg as any).text || ""; - const isMentionedInText = msg.entities?.some( - (e) => - e.type === "mention" && - text.substring(e.offset, e.offset + e.length).toLowerCase() === `@${this.botUsername!.toLowerCase()}`, - ); - if (isMentionedInText) return true; - - // Check caption entities for @mention (media messages) - const caption = (msg as any).caption || ""; - const captionEntities = (msg as any).caption_entities as typeof msg.entities | undefined; - const isMentionedInCaption = captionEntities?.some( - (e: any) => - e.type === "mention" && - caption.substring(e.offset, e.offset + e.length).toLowerCase() === `@${this.botUsername!.toLowerCase()}`, - ); - if (isMentionedInCaption) return true; - } - - // Check if reply to bot - const isReplyToBot = msg.reply_to_message?.from?.id === this.botId; - return isReplyToBot; + /** Only process private (direct) messages; silently ignore group chats. */ + private isPrivateChat(ctx: Context): boolean { + return ctx.chat?.type === "private"; } // ── Inbound: text messages ── @@ -332,7 +286,7 @@ export class TelegramService implements OnModuleInit { if (!msg || !msg.text) return; const telegramUserId = String(msg.from?.id); - let text = msg.text.trim(); + const text = msg.text.trim(); this.logger.debug(`Received message: chatId=${msg.chat.id} from=${telegramUserId} text="${text.slice(0, 50)}"`); @@ -342,10 +296,6 @@ export class TelegramService implements OnModuleInit { return; } - // Strip @mention from text for cleaner agent input - if (this.botUsername) { - text = text.replace(new RegExp(`@${this.botUsername}\\s*`, "gi"), "").trim(); - } if (!text) return; // Check if user is bound