From ba2827f706bbe2bdb673d6dddd8fb14bbd4d8808 Mon Sep 17 00:00:00 2001 From: weiqinl Date: Sat, 1 Aug 2026 23:33:12 +0800 Subject: [PATCH] fix(telegram): use Array.from instead of spread for code point length validation (#111443) --- extensions/telegram/src/send-forum-topics.ts | 4 +- extensions/telegram/src/send.test.ts | 72 ++++++++++++++++++++ 2 files changed, 74 insertions(+), 2 deletions(-) diff --git a/extensions/telegram/src/send-forum-topics.ts b/extensions/telegram/src/send-forum-topics.ts index 4bf118e7b7c9..a94a772261b7 100644 --- a/extensions/telegram/src/send-forum-topics.ts +++ b/extensions/telegram/src/send-forum-topics.ts @@ -49,7 +49,7 @@ export async function editForumTopicTelegram( if (nameProvided && !trimmedName) { throw new Error("Telegram forum topic name is required"); } - if (trimmedName && trimmedName.length > 128) { + if (trimmedName && Array.from(trimmedName).length > 128) { throw new Error("Telegram forum topic name must be 128 characters or fewer"); } const iconProvided = opts.iconCustomEmojiId !== undefined; @@ -177,7 +177,7 @@ export async function createForumTopicTelegram( throw new Error("Forum topic name is required"); } const trimmedName = name.trim(); - if (trimmedName.length > 128) { + if (Array.from(trimmedName).length > 128) { throw new Error("Forum topic name must be 128 characters or fewer"); } diff --git a/extensions/telegram/src/send.test.ts b/extensions/telegram/src/send.test.ts index 54dc39c39dd1..f569324bcc6f 100644 --- a/extensions/telegram/src/send.test.ts +++ b/extensions/telegram/src/send.test.ts @@ -826,6 +826,31 @@ describe("sendMessageTelegram", () => { }); }); + it.each([ + ["65 emoji", "๐Ÿ˜€".repeat(65)], + ["128 emoji", "๐Ÿ˜€".repeat(128)], + ["128 mixed emoji and ASCII characters", "๐Ÿ˜€".repeat(64) + "a".repeat(64)], + ["128 CJK characters", "็•Œ".repeat(128)], + ])("accepts %s forum topic names by Unicode code points", async (_label, name) => { + loadConfig.mockReturnValue({ + channels: { + telegram: { + botToken: "tok", + }, + }, + }); + botApi.editForumTopic.mockResolvedValue(true); + + await editForumTopicTelegram("-1001234567890", 271, { + cfg: TELEGRAM_TEST_CFG, + token: "tok", + accountId: "default", + name, + }); + + expect(botApi.editForumTopic).toHaveBeenCalledWith("-1001234567890", 271, { name }); + }); + it("strips topic suffixes before editing a Telegram forum topic", async () => { loadConfig.mockReturnValue({ channels: { @@ -5106,6 +5131,24 @@ describe("createForumTopicTelegram", () => { }); } + it.each([ + ["65 emoji", "๐ŸŽƒ".repeat(65)], + ["128 emoji", "๐ŸŽƒ".repeat(128)], + ["128 mixed emoji and ASCII characters", "๐ŸŽƒ".repeat(64) + "a".repeat(64)], + ["128 CJK characters", "็•Œ".repeat(128)], + ])("accepts %s forum topic names by Unicode code points", async (_label, name) => { + const createForumTopic = vi.fn().mockResolvedValue({ message_thread_id: 400, name }); + const api = { createForumTopic } as unknown as Bot["api"]; + + await createForumTopicTelegram("-1001234567890", name, { + cfg: TELEGRAM_TEST_CFG, + token: "tok", + api, + }); + + expect(createForumTopic).toHaveBeenCalledWith("-1001234567890", name, undefined); + }); + it("rejects an invalid topic name before creating a Telegram client", async () => { botCtorSpy.mockClear(); @@ -5117,5 +5160,34 @@ describe("createForumTopicTelegram", () => { ).rejects.toThrow("Forum topic name is required"); expect(botCtorSpy).not.toHaveBeenCalled(); }); + + it.each([ + ["129 ASCII characters", "a".repeat(129)], + ["129 emoji", "๐ŸŽƒ".repeat(129)], + ["19 multi-code-point emoji graphemes", "๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ".repeat(19)], + ])("rejects %s exceeding 128 Unicode code points on create and edit", async (_label, name) => { + const createForumTopic = vi.fn(); + const editForumTopic = vi.fn(); + const api = { createForumTopic, editForumTopic } as unknown as Bot["api"]; + + await expect( + createForumTopicTelegram("-1001234567890", name, { + cfg: TELEGRAM_TEST_CFG, + token: "tok", + api, + }), + ).rejects.toThrow("128 characters or fewer"); + await expect( + editForumTopicTelegram("-1001234567890", 271, { + cfg: TELEGRAM_TEST_CFG, + token: "tok", + api, + name, + }), + ).rejects.toThrow("128 characters or fewer"); + + expect(createForumTopic).not.toHaveBeenCalled(); + expect(editForumTopic).not.toHaveBeenCalled(); + }); }); /* oxlint-disable max-lines -- TODO: split this grandfathered oversized file. */