From 07b419a0e7b7cb8774c3d2db47a7a7c3aedaf00d Mon Sep 17 00:00:00 2001 From: liuxiaopai-ai <73659136+liuxiaopai-ai@users.noreply.github.com> Date: Mon, 2 Mar 2026 18:48:36 +0800 Subject: [PATCH] Feishu: honor group/dm prefixes in target parsing --- extensions/feishu/src/targets.test.ts | 16 ++++++++++++++++ extensions/feishu/src/targets.ts | 19 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/extensions/feishu/src/targets.test.ts b/extensions/feishu/src/targets.test.ts index 783ca3c22..e5a6f3063 100644 --- a/extensions/feishu/src/targets.test.ts +++ b/extensions/feishu/src/targets.test.ts @@ -13,6 +13,10 @@ describe("resolveReceiveIdType", () => { it("defaults unprefixed IDs to user_id", () => { expect(resolveReceiveIdType("u_123")).toBe("user_id"); }); + + it("treats explicit group targets as chat_id", () => { + expect(resolveReceiveIdType("group:oc_123")).toBe("chat_id"); + }); }); describe("normalizeFeishuTarget", () => { @@ -25,9 +29,17 @@ describe("normalizeFeishuTarget", () => { expect(normalizeFeishuTarget("feishu:chat:oc_123")).toBe("oc_123"); }); + it("strips provider and group prefixes", () => { + expect(normalizeFeishuTarget("feishu:group:oc_123")).toBe("oc_123"); + }); + it("accepts provider-prefixed raw ids", () => { expect(normalizeFeishuTarget("feishu:ou_123")).toBe("ou_123"); }); + + it("strips provider and dm prefixes", () => { + expect(normalizeFeishuTarget("lark:dm:ou_123")).toBe("ou_123"); + }); }); describe("looksLikeFeishuId", () => { @@ -38,4 +50,8 @@ describe("looksLikeFeishuId", () => { it("accepts provider-prefixed chat targets", () => { expect(looksLikeFeishuId("lark:chat:oc_123")).toBe(true); }); + + it("accepts provider-prefixed group targets", () => { + expect(looksLikeFeishuId("feishu:group:oc_123")).toBe(true); + }); }); diff --git a/extensions/feishu/src/targets.ts b/extensions/feishu/src/targets.ts index 209d0b3a9..524eda4a4 100644 --- a/extensions/feishu/src/targets.ts +++ b/extensions/feishu/src/targets.ts @@ -33,9 +33,15 @@ export function normalizeFeishuTarget(raw: string): string | null { if (lowered.startsWith("chat:")) { return withoutProvider.slice("chat:".length).trim() || null; } + if (lowered.startsWith("group:")) { + return withoutProvider.slice("group:".length).trim() || null; + } if (lowered.startsWith("user:")) { return withoutProvider.slice("user:".length).trim() || null; } + if (lowered.startsWith("dm:")) { + return withoutProvider.slice("dm:".length).trim() || null; + } if (lowered.startsWith("open_id:")) { return withoutProvider.slice("open_id:".length).trim() || null; } @@ -56,6 +62,17 @@ export function formatFeishuTarget(id: string, type?: FeishuIdType): string { export function resolveReceiveIdType(id: string): "chat_id" | "open_id" | "user_id" { const trimmed = id.trim(); + const lowered = trimmed.toLowerCase(); + if (lowered.startsWith("chat:") || lowered.startsWith("group:")) { + return "chat_id"; + } + if (lowered.startsWith("open_id:")) { + return "open_id"; + } + if (lowered.startsWith("user:") || lowered.startsWith("dm:")) { + const normalized = trimmed.replace(/^(user|dm):/i, "").trim(); + return normalized.startsWith(OPEN_ID_PREFIX) ? "open_id" : "user_id"; + } if (trimmed.startsWith(CHAT_ID_PREFIX)) { return "chat_id"; } @@ -70,7 +87,7 @@ export function looksLikeFeishuId(raw: string): boolean { if (!trimmed) { return false; } - if (/^(chat|user|open_id):/i.test(trimmed)) { + if (/^(chat|group|user|dm|open_id):/i.test(trimmed)) { return true; } if (trimmed.startsWith(CHAT_ID_PREFIX)) {