From 3071fe151d75a481795f8218a31f3a0fc67ebb99 Mon Sep 17 00:00:00 2001 From: DBT Date: Fri, 27 Feb 2026 03:39:19 +0000 Subject: [PATCH] feishu: add private/group controls (allow_chats, group enable, mention gating) --- config.example.json | 5 +++- pkg/channels/feishu.go | 54 ++++++++++++++++++++++++++++++++++++++++++ pkg/config/config.go | 30 +++++++++++++---------- 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/config.example.json b/config.example.json index 5584e2a..baee046 100644 --- a/config.example.json +++ b/config.example.json @@ -109,7 +109,10 @@ "app_secret": "", "encrypt_key": "", "verification_token": "", - "allow_from": [] + "allow_from": [], + "allow_chats": [], + "enable_groups": true, + "require_mention_in_groups": true }, "dingtalk": { "enabled": false, diff --git a/pkg/channels/feishu.go b/pkg/channels/feishu.go index f4827b2..652dbdf 100644 --- a/pkg/channels/feishu.go +++ b/pkg/channels/feishu.go @@ -152,6 +152,15 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2 if chatID == "" { return nil } + chatType := strings.ToLower(strings.TrimSpace(stringValue(message.ChatType))) + if !c.isAllowedChat(chatID, chatType) { + logger.WarnCF("feishu", "Feishu message rejected by chat allowlist", map[string]interface{}{ + logger.FieldSenderID: extractFeishuSenderID(sender), + logger.FieldChatID: chatID, + "chat_type": chatType, + }) + return nil + } senderID := extractFeishuSenderID(sender) if senderID == "" { @@ -162,6 +171,13 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2 if content == "" { content = "[empty message]" } + if !c.shouldHandleGroupMessage(chatType, content) { + logger.DebugCF("feishu", "Ignoring group message without mention/command", map[string]interface{}{ + logger.FieldSenderID: senderID, + logger.FieldChatID: chatID, + }) + return nil + } metadata := map[string]string{} if messageID := stringValue(message.MessageId); messageID != "" { @@ -187,6 +203,44 @@ func (c *FeishuChannel) handleMessageReceive(_ context.Context, event *larkim.P2 return nil } +func (c *FeishuChannel) isAllowedChat(chatID, chatType string) bool { + chatID = strings.TrimSpace(chatID) + chatType = strings.ToLower(strings.TrimSpace(chatType)) + isGroup := chatType != "" && chatType != "p2p" + if isGroup && !c.config.EnableGroups { + return false + } + if len(c.config.AllowChats) == 0 { + return true + } + for _, allowed := range c.config.AllowChats { + if strings.TrimSpace(allowed) == chatID { + return true + } + } + return false +} + +func (c *FeishuChannel) shouldHandleGroupMessage(chatType, content string) bool { + chatType = strings.ToLower(strings.TrimSpace(chatType)) + isGroup := chatType != "" && chatType != "p2p" + if !isGroup { + return true + } + if !c.config.RequireMentionInGroups { + return true + } + trimmed := strings.TrimSpace(content) + if strings.HasPrefix(trimmed, "/") { + return true + } + lower := strings.ToLower(trimmed) + if strings.Contains(lower, "@") || strings.Contains(lower, "