feishu: add private/group controls (allow_chats, group enable, mention gating)

This commit is contained in:
DBT
2026-02-27 03:39:19 +00:00
parent 371164ab9d
commit 3071fe151d
3 changed files with 76 additions and 13 deletions

View File

@@ -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,

View File

@@ -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, "<at") {
return true
}
return false
}
func extractFeishuSenderID(sender *larkim.EventSender) string {
if sender == nil || sender.SenderId == nil {
return ""

View File

@@ -146,12 +146,15 @@ type TelegramConfig struct {
}
type FeishuConfig struct {
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_FEISHU_ENABLED"`
AppID string `json:"app_id" env:"CLAWGO_CHANNELS_FEISHU_APP_ID"`
AppSecret string `json:"app_secret" env:"CLAWGO_CHANNELS_FEISHU_APP_SECRET"`
EncryptKey string `json:"encrypt_key" env:"CLAWGO_CHANNELS_FEISHU_ENCRYPT_KEY"`
VerificationToken string `json:"verification_token" env:"CLAWGO_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_FEISHU_ALLOW_FROM"`
Enabled bool `json:"enabled" env:"CLAWGO_CHANNELS_FEISHU_ENABLED"`
AppID string `json:"app_id" env:"CLAWGO_CHANNELS_FEISHU_APP_ID"`
AppSecret string `json:"app_secret" env:"CLAWGO_CHANNELS_FEISHU_APP_SECRET"`
EncryptKey string `json:"encrypt_key" env:"CLAWGO_CHANNELS_FEISHU_ENCRYPT_KEY"`
VerificationToken string `json:"verification_token" env:"CLAWGO_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
AllowFrom []string `json:"allow_from" env:"CLAWGO_CHANNELS_FEISHU_ALLOW_FROM"`
AllowChats []string `json:"allow_chats" env:"CLAWGO_CHANNELS_FEISHU_ALLOW_CHATS"`
EnableGroups bool `json:"enable_groups" env:"CLAWGO_CHANNELS_FEISHU_ENABLE_GROUPS"`
RequireMentionInGroups bool `json:"require_mention_in_groups" env:"CLAWGO_CHANNELS_FEISHU_REQUIRE_MENTION_IN_GROUPS"`
}
type DiscordConfig struct {
@@ -389,12 +392,15 @@ func DefaultConfig() *Config {
RequireMentionInGroups: true,
},
Feishu: FeishuConfig{
Enabled: false,
AppID: "",
AppSecret: "",
EncryptKey: "",
VerificationToken: "",
AllowFrom: []string{},
Enabled: false,
AppID: "",
AppSecret: "",
EncryptKey: "",
VerificationToken: "",
AllowFrom: []string{},
AllowChats: []string{},
EnableGroups: true,
RequireMentionInGroups: true,
},
Discord: DiscordConfig{
Enabled: false,