fix(feishu): gate group pairing by target bot (#1291)

* fix(feishu): require exact bot_open_id match for mention detection

- Previously, when bot_open_id was empty, ALL mentions were treated as bot mentions
- This caused multiple agents in same group to all respond to any mention
- Now requires bot_open_id to be set AND match exactly for mentionedBot=true
- Fixes issue where CPPAI PM would respond even when other agent was mentioned

* fix(feishu): gate group pairing by target bot

---------

Co-authored-by: ntduc <ntduc@cpp.ai.vn>
This commit is contained in:
Duc Nguyenandntduc authored and GitHub committed 2026-06-28 00:25:49 +07:00
1 parent b72959b34c
commit d460c90403
8 files changed
+728 -56

No files matched your search

+27 -7
View File
@@ -8,9 +8,9 @@ import (
func TestParseMessageContent_Text(t *testing.T) {
cases := []struct {
name string
raw string
want string
name string
raw string
want string
}{
{"normal text", `{"text":"hello world"}`, "hello world"},
{"empty raw", "", ""},
@@ -214,10 +214,8 @@ func TestResolveMentions_NoBotID_AllMentionsReplacedWithName(t *testing.T) {
{Key: "@_user_2", OpenID: "ou_B", Name: "Bob"},
}
got := resolveMentions(text, mentions, "")
// botOpenID is empty: all mentions treated as bot → stripped
// (because the condition is: if botOpenID != "" && openID == botOpenID → strip, else → replace with name)
// When botOpenID == "", neither branch strips unless openID matches empty string.
// Both get replaced with @Name.
// botOpenID is empty: no mention is treated as this bot, so all user
// mentions are preserved as readable names.
if got != "@Alice and @Bob" {
t.Errorf("got %q, want %q", got, "@Alice and @Bob")
}
@@ -276,6 +274,28 @@ func TestParseMessageEvent_BotMentioned(t *testing.T) {
}
}
func TestParseMessageEvent_UnknownBotIDDoesNotTreatAnyMentionAsBot(t *testing.T) {
ch := &Channel{}
ev := &MessageEvent{}
ev.Event.Message.MessageType = "text"
ev.Event.Message.Content = `{"text":"@_user_1 please help"}`
ev.Event.Message.Mentions = []EventMention{
{Key: "@_user_1", ID: struct {
OpenID string `json:"open_id"`
UserID string `json:"user_id"`
UnionID string `json:"union_id"`
}{OpenID: "ou_other_bot"}, Name: "OtherBot"},
}
mc := ch.parseMessageEvent(ev)
if mc.MentionedBot {
t.Fatal("MentionedBot must be false when bot open_id is unknown")
}
if mc.Content != "@OtherBot please help" {
t.Fatalf("content = %q, want other mention preserved", mc.Content)
}
}
func TestParseMessageEvent_NoSender(t *testing.T) {
ch := &Channel{}
ev := &MessageEvent{}