Merge pull request #1171 from mutezebra/feat/feishu-random-emoji-v2
feat(feishu): add random reaction emoji config
This commit is contained in:
commit
7ea7bb0717
5 changed files with 41 additions and 13 deletions
|
|
@ -9,6 +9,10 @@
|
||||||
# ── Chat Channel ──────────────────────────
|
# ── Chat Channel ──────────────────────────
|
||||||
# TELEGRAM_BOT_TOKEN=123456:ABC...
|
# TELEGRAM_BOT_TOKEN=123456:ABC...
|
||||||
# DISCORD_BOT_TOKEN=xxx
|
# DISCORD_BOT_TOKEN=xxx
|
||||||
|
# Feishu (飞书)
|
||||||
|
# PICOCLAW_CHANNELS_FEISHU_APP_ID=cli_xxx
|
||||||
|
# PICOCLAW_CHANNELS_FEISHU_APP_SECRET=xxx
|
||||||
|
# PICOCLAW_CHANNELS_FEISHU_RANDOM_REACTION_EMOJI=Typing,OneSecond
|
||||||
|
|
||||||
# ── Web Search (optional) ────────────────
|
# ── Web Search (optional) ────────────────
|
||||||
# BRAVE_SEARCH_API_KEY=BSA...
|
# BRAVE_SEARCH_API_KEY=BSA...
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,8 @@
|
||||||
"encrypt_key": "",
|
"encrypt_key": "",
|
||||||
"verification_token": "",
|
"verification_token": "",
|
||||||
"allow_from": [],
|
"allow_from": [],
|
||||||
"reasoning_channel_id": ""
|
"reasoning_channel_id": "",
|
||||||
|
"random_reaction_emoji": []
|
||||||
},
|
},
|
||||||
"dingtalk": {
|
"dingtalk": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,8 @@
|
||||||
| app_secret | string | 是 | 飞书应用的 App Secret |
|
| app_secret | string | 是 | 飞书应用的 App Secret |
|
||||||
| encrypt_key | string | 否 | 事件回调加密密钥 |
|
| encrypt_key | string | 否 | 事件回调加密密钥 |
|
||||||
| verification_token | string | 否 | 用于Webhook事件验证的Token |
|
| verification_token | string | 否 | 用于Webhook事件验证的Token |
|
||||||
| allow_from | array | 否 | 用户ID白名单,空表示允许所有用户 |
|
| allow_from | array | 否 | 用户ID白名单,空表示所有用户 |
|
||||||
|
| random_reaction_emoji | array | 否 | 随机添加的表情列表,空则使用默认 "Pin" |
|
||||||
|
|
||||||
## 设置流程
|
## 设置流程
|
||||||
|
|
||||||
|
|
@ -35,3 +36,4 @@
|
||||||
3. 配置事件订阅和Webhook URL
|
3. 配置事件订阅和Webhook URL
|
||||||
4. 设置加密(可选,生产环境建议启用)
|
4. 设置加密(可选,生产环境建议启用)
|
||||||
5. 将 App ID、App Secret、Encrypt Key 和 Verification Token(如果启用加密) 填入配置文件中
|
5. 将 App ID、App Secret、Encrypt Key 和 Verification Token(如果启用加密) 填入配置文件中
|
||||||
|
6. 自定义你希望 PicoClaw react 你消息时的表情(可选, Reference URL: [Feishu Emoji List](https://open.larkoffice.com/document/server-docs/im-v1/message-reaction/emojis-introduce))
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@ package feishu
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -195,18 +197,35 @@ func (c *FeishuChannel) SendPlaceholder(ctx context.Context, chatID string) (str
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReactToMessage implements channels.ReactionCapable.
|
// ReactToMessage implements channels.ReactionCapable.
|
||||||
// Adds an "Pin" reaction and returns an undo function to remove it.
|
// Adds a reaction (randomly chosen from config) and returns an undo function to remove it.
|
||||||
func (c *FeishuChannel) ReactToMessage(ctx context.Context, chatID, messageID string) (func(), error) {
|
func (c *FeishuChannel) ReactToMessage(ctx context.Context, chatID, messageID string) (func(), error) {
|
||||||
|
// Get emoji list from config
|
||||||
|
emojiList := c.config.RandomReactionEmoji
|
||||||
|
if len(emojiList) == 0 {
|
||||||
|
// Default to "Pin" if no config
|
||||||
|
emojiList = []string{"Pin"}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Randomly choose one from the list using crypto/rand for better distribution
|
||||||
|
idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(emojiList))))
|
||||||
|
var chosenEmoji string
|
||||||
|
if err != nil {
|
||||||
|
chosenEmoji = emojiList[0]
|
||||||
|
} else {
|
||||||
|
chosenEmoji = emojiList[idx.Int64()]
|
||||||
|
}
|
||||||
|
|
||||||
req := larkim.NewCreateMessageReactionReqBuilder().
|
req := larkim.NewCreateMessageReactionReqBuilder().
|
||||||
MessageId(messageID).
|
MessageId(messageID).
|
||||||
Body(larkim.NewCreateMessageReactionReqBodyBuilder().
|
Body(larkim.NewCreateMessageReactionReqBodyBuilder().
|
||||||
ReactionType(larkim.NewEmojiBuilder().EmojiType("Pin").Build()).
|
ReactionType(larkim.NewEmojiBuilder().EmojiType(chosenEmoji).Build()).
|
||||||
Build()).
|
Build()).
|
||||||
Build()
|
Build()
|
||||||
|
|
||||||
resp, err := c.client.Im.V1.MessageReaction.Create(ctx, req)
|
resp, err := c.client.Im.V1.MessageReaction.Create(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.ErrorCF("feishu", "Failed to add reaction", map[string]any{
|
logger.ErrorCF("feishu", "Failed to add reaction", map[string]any{
|
||||||
|
"emoji": chosenEmoji,
|
||||||
"message_id": messageID,
|
"message_id": messageID,
|
||||||
"error": err.Error(),
|
"error": err.Error(),
|
||||||
})
|
})
|
||||||
|
|
@ -214,6 +233,7 @@ func (c *FeishuChannel) ReactToMessage(ctx context.Context, chatID, messageID st
|
||||||
}
|
}
|
||||||
if !resp.Success() {
|
if !resp.Success() {
|
||||||
logger.ErrorCF("feishu", "Reaction API error", map[string]any{
|
logger.ErrorCF("feishu", "Reaction API error", map[string]any{
|
||||||
|
"emoji": chosenEmoji,
|
||||||
"message_id": messageID,
|
"message_id": messageID,
|
||||||
"code": resp.Code,
|
"code": resp.Code,
|
||||||
"msg": resp.Msg,
|
"msg": resp.Msg,
|
||||||
|
|
|
||||||
|
|
@ -274,15 +274,16 @@ type TelegramConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type FeishuConfig struct {
|
type FeishuConfig struct {
|
||||||
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_FEISHU_ENABLED"`
|
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_FEISHU_ENABLED"`
|
||||||
AppID string `json:"app_id" env:"PICOCLAW_CHANNELS_FEISHU_APP_ID"`
|
AppID string `json:"app_id" env:"PICOCLAW_CHANNELS_FEISHU_APP_ID"`
|
||||||
AppSecret string `json:"app_secret" env:"PICOCLAW_CHANNELS_FEISHU_APP_SECRET"`
|
AppSecret string `json:"app_secret" env:"PICOCLAW_CHANNELS_FEISHU_APP_SECRET"`
|
||||||
EncryptKey string `json:"encrypt_key" env:"PICOCLAW_CHANNELS_FEISHU_ENCRYPT_KEY"`
|
EncryptKey string `json:"encrypt_key" env:"PICOCLAW_CHANNELS_FEISHU_ENCRYPT_KEY"`
|
||||||
VerificationToken string `json:"verification_token" env:"PICOCLAW_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
|
VerificationToken string `json:"verification_token" env:"PICOCLAW_CHANNELS_FEISHU_VERIFICATION_TOKEN"`
|
||||||
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_FEISHU_ALLOW_FROM"`
|
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_FEISHU_ALLOW_FROM"`
|
||||||
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"`
|
GroupTrigger GroupTriggerConfig `json:"group_trigger,omitempty"`
|
||||||
Placeholder PlaceholderConfig `json:"placeholder,omitempty"`
|
Placeholder PlaceholderConfig `json:"placeholder,omitempty"`
|
||||||
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_FEISHU_REASONING_CHANNEL_ID"`
|
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_FEISHU_REASONING_CHANNEL_ID"`
|
||||||
|
RandomReactionEmoji FlexibleStringSlice `json:"random_reaction_emoji" env:"PICOCLAW_CHANNELS_FEISHU_RANDOM_REACTION_EMOJI"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DiscordConfig struct {
|
type DiscordConfig struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue