// Telegram tests cover targets plugin behavior. import { describe, expect, it } from "vitest"; import { isNumericTelegramSenderUserId, isNumericTelegramUserId, normalizeTelegramAllowFromEntry, } from "./allow-from.js"; import { resolveTelegramGroupRequireMention, resolveTelegramGroupToolPolicy, } from "./group-policy.js"; import { looksLikeTelegramTargetId, normalizeTelegramMessagingTarget } from "./normalize.js"; import { installMaybePersistResolvedTelegramTargetTests } from "./target-writeback.test-shared.js"; import { isNumericTelegramChatId, normalizeTelegramChatId, normalizeTelegramLookupTarget, normalizeTelegramOutboundTarget, parseTelegramTarget, stripTelegramInternalPrefixes, } from "./targets.js"; const numericTelegramTargetNormalizers = [ { name: "normalizeTelegramChatId", normalize: normalizeTelegramChatId }, { name: "normalizeTelegramLookupTarget", normalize: normalizeTelegramLookupTarget }, ]; describe("stripTelegramInternalPrefixes", () => { it("strips telegram prefix", () => { expect(stripTelegramInternalPrefixes("telegram:123")).toBe("123"); }); it("strips telegram+group prefixes", () => { expect(stripTelegramInternalPrefixes("telegram:group:-100123")).toBe("-100123"); }); it("does not strip group prefix without telegram prefix", () => { expect(stripTelegramInternalPrefixes("group:-100123")).toBe("group:-100123"); }); it("is idempotent", () => { expect(stripTelegramInternalPrefixes("@mychannel")).toBe("@mychannel"); }); }); describe("parseTelegramTarget", () => { it("parses plain chatId", () => { expect(parseTelegramTarget("-1001234567890")).toEqual({ chatId: "-1001234567890", chatType: "group", }); }); it("parses @username", () => { expect(parseTelegramTarget("@mychannel")).toEqual({ chatId: "@mychannel", chatType: "unknown", }); }); it("parses chatId:topicId format", () => { expect(parseTelegramTarget("-1001234567890:123")).toEqual({ chatId: "-1001234567890", messageThreadId: 123, chatType: "group", }); }); it("parses chatId:topic:topicId format", () => { expect(parseTelegramTarget("-1001234567890:topic:456")).toEqual({ chatId: "-1001234567890", messageThreadId: 456, chatType: "group", }); }); it("trims whitespace", () => { expect(parseTelegramTarget(" -1001234567890:99 ")).toEqual({ chatId: "-1001234567890", messageThreadId: 99, chatType: "group", }); }); it("does not treat non-numeric suffix as topicId", () => { expect(parseTelegramTarget("-1001234567890:abc")).toEqual({ chatId: "-1001234567890:abc", chatType: "unknown", }); }); it("does not route unsafe topic suffixes", () => { expect(parseTelegramTarget("-1001234567890:9007199254740992")).toEqual({ chatId: "-1001234567890:9007199254740992", chatType: "unknown", }); expect(parseTelegramTarget("-1001234567890:topic:9007199254740992")).toEqual({ chatId: "-1001234567890:topic:9007199254740992", chatType: "unknown", }); }); it("strips internal prefixes before parsing", () => { expect(parseTelegramTarget("telegram:group:-1001234567890:topic:456")).toEqual({ chatId: "-1001234567890", messageThreadId: 456, chatType: "group", }); }); }); describe("telegram numeric target normalization", () => { it.each(numericTelegramTargetNormalizers)( "$name keeps numeric chat ids unchanged", ({ normalize }) => { expect(normalize("-1001234567890")).toBe("-1001234567890"); expect(normalize("123456789")).toBe("123456789"); }, ); }); describe("normalizeTelegramOutboundTarget", () => { it("normalizes legacy durable group retry targets for Telegram sends", () => { expect(normalizeTelegramOutboundTarget("group:-1001234567890")).toBe("-1001234567890"); }); it("normalizes legacy durable group retry targets with topic suffixes", () => { expect(normalizeTelegramOutboundTarget("group:-1001234567890:topic:77")).toBe( "-1001234567890:topic:77", ); expect(normalizeTelegramOutboundTarget("group:-1001234567890:77")).toBe("-1001234567890:77"); }); it("keeps already-valid numeric and non-numeric targets on the send path", () => { expect(normalizeTelegramOutboundTarget("-1001234567890")).toBe("-1001234567890"); expect(normalizeTelegramOutboundTarget("group:not-a-number")).toBe("group:not-a-number"); expect(normalizeTelegramOutboundTarget("@mychannel")).toBe("@mychannel"); }); }); describe("normalizeTelegramChatId", () => { it("rejects username and t.me forms", () => { expect(normalizeTelegramChatId("telegram:https://t.me/MyChannel")).toBeUndefined(); expect(normalizeTelegramChatId("tg:t.me/mychannel")).toBeUndefined(); expect(normalizeTelegramChatId("@MyChannel")).toBeUndefined(); expect(normalizeTelegramChatId("MyChannel")).toBeUndefined(); }); it("returns undefined for empty input", () => { expect(normalizeTelegramChatId(" ")).toBeUndefined(); }); }); describe("normalizeTelegramLookupTarget", () => { it("normalizes legacy t.me and username targets", () => { expect(normalizeTelegramLookupTarget("telegram:https://t.me/MyChannel")).toBe("@MyChannel"); expect(normalizeTelegramLookupTarget("tg:t.me/mychannel")).toBe("@mychannel"); expect(normalizeTelegramLookupTarget("@MyChannel")).toBe("@MyChannel"); expect(normalizeTelegramLookupTarget("MyChannel")).toBe("@MyChannel"); }); it("rejects invalid username forms", () => { expect(normalizeTelegramLookupTarget("@bad-handle")).toBeUndefined(); expect(normalizeTelegramLookupTarget("bad-handle")).toBeUndefined(); expect(normalizeTelegramLookupTarget("ab")).toBeUndefined(); }); }); describe("isNumericTelegramChatId", () => { it("matches numeric telegram chat ids", () => { expect(isNumericTelegramChatId("-1001234567890")).toBe(true); expect(isNumericTelegramChatId("123456789")).toBe(true); }); it("rejects non-numeric chat ids", () => { expect(isNumericTelegramChatId("@mychannel")).toBe(false); expect(isNumericTelegramChatId("t.me/mychannel")).toBe(false); }); }); describe("telegram group policy", () => { it("resolves topic-level requireMention and chat-level tools for topic ids", () => { const telegramCfg = { channels: { telegram: { botToken: "telegram-test", groups: { "-1001": { requireMention: true, tools: { allow: ["message.send"] }, topics: { "77": { requireMention: false, }, }, }, "*": { requireMention: true, }, }, }, }, } as any; expect( resolveTelegramGroupRequireMention({ cfg: telegramCfg, groupId: "-1001:topic:77" }), ).toBe(false); expect(resolveTelegramGroupToolPolicy({ cfg: telegramCfg, groupId: "-1001:topic:77" })).toEqual( { allow: ["message.send"], }, ); }); it("honors account-scoped topic requireMention overrides", () => { const telegramCfg = { channels: { telegram: { botToken: "telegram-test", groups: { "-1001": { requireMention: true, topics: { "77": { requireMention: true, }, }, }, }, accounts: { work: { botToken: "telegram-work", groups: { "-1001": { topics: { "77": { requireMention: false, }, }, }, }, }, }, }, }, } as any; expect( resolveTelegramGroupRequireMention({ cfg: telegramCfg, accountId: "work", groupId: "-1001:topic:77", }), ).toBe(false); }); }); describe("telegram allow-from helpers", () => { it("normalizes tg/telegram prefixes", () => { const cases = [ { value: " TG:123 ", expected: "123" }, { value: "telegram:@someone", expected: "@someone" }, ] as const; for (const testCase of cases) { expect(normalizeTelegramAllowFromEntry(testCase.value)).toBe(testCase.expected); } }); it("accepts signed numeric IDs", () => { const cases = [ { value: "123456789", expected: true }, { value: "-1001234567890", expected: true }, { value: "@someone", expected: false }, { value: "12 34", expected: false }, ] as const; for (const testCase of cases) { expect(isNumericTelegramUserId(testCase.value)).toBe(testCase.expected); } }); it("accepts only positive numeric sender user IDs", () => { const cases = [ { value: "123456789", expected: true }, { value: "-1001234567890", expected: false }, { value: "@someone", expected: false }, ] as const; for (const testCase of cases) { expect(isNumericTelegramSenderUserId(testCase.value)).toBe(testCase.expected); } }); }); describe("telegram target normalization", () => { it("normalizes telegram prefixes, group targets, and topic suffixes", () => { expect(normalizeTelegramMessagingTarget("telegram:123456")).toBe("telegram:123456"); expect(normalizeTelegramMessagingTarget("tg:group:-100123")).toBe("telegram:group:-100123"); expect(normalizeTelegramMessagingTarget("telegram:-100123:topic:99")).toBe( "telegram:-100123:topic:99", ); }); it("returns undefined for invalid telegram recipients", () => { expect(normalizeTelegramMessagingTarget("telegram:")).toBeUndefined(); expect(normalizeTelegramMessagingTarget(" ")).toBeUndefined(); }); it("detects valid telegram target identifiers", () => { expect(looksLikeTelegramTargetId("telegram:123456")).toBe(true); expect(looksLikeTelegramTargetId("tg:group:-100123")).toBe(true); expect(looksLikeTelegramTargetId("hello world")).toBe(false); }); }); installMaybePersistResolvedTelegramTargetTests({ includeGatewayScopeCases: true });