feat: 新增企业微信应用消息发送渠道
custom-deploy-your-server / build-deploy (push) Has been cancelled
deploy-demo-site / build-deploy (push) Has been cancelled
Deploy Docs to GitHub Pages / build (push) Has been cancelled
Deploy Docs to GitHub Pages / Deploy (push) Has been cancelled

- 添加 WeChatCorpAccount 消息类型常量
- 新增企业微信应用配置结构体和渠道验证逻辑
- 实现企业微信应用消息发送服务,支持 text、markdown 和 textcard 格式
- 添加前端配置界面,支持动态接收者设置
- 集成代理支持(HTTP/HTTPS/SOCKS5)
This commit is contained in:
2026-02-10 18:52:59 +08:00
parent 6ee6910ab7
commit 9538ab481b
11 changed files with 482 additions and 35 deletions
@@ -18,17 +18,18 @@ const (
FormatTypeHTML = channels.FormatTypeHTML
FormatTypeMarkdown = channels.FormatTypeMarkdown
MessageTypeEmail = channels.MessageTypeEmail
MessageTypeDtalk = channels.MessageTypeDtalk
MessageTypeQyWeiXin = channels.MessageTypeQyWeiXin
MessageTypeFeishu = channels.MessageTypeFeishu
MessageTypeCustom = channels.MessageTypeCustom
MessageTypeWeChatOFAccount = channels.MessageTypeWeChatOFAccount
MessageTypeMessageNest = channels.MessageTypeMessageNest
MessageTypeAliyunSMS = channels.MessageTypeAliyunSMS
MessageTypeTelegram = channels.MessageTypeTelegram
MessageTypeBark = channels.MessageTypeBark
MessageTypePushMe = channels.MessageTypePushMe
MessageTypeEmail = channels.MessageTypeEmail
MessageTypeDtalk = channels.MessageTypeDtalk
MessageTypeQyWeiXin = channels.MessageTypeQyWeiXin
MessageTypeWeChatCorpAccount = channels.MessageTypeWeChatCorpAccount
MessageTypeFeishu = channels.MessageTypeFeishu
MessageTypeCustom = channels.MessageTypeCustom
MessageTypeWeChatOFAccount = channels.MessageTypeWeChatOFAccount
MessageTypeMessageNest = channels.MessageTypeMessageNest
MessageTypeAliyunSMS = channels.MessageTypeAliyunSMS
MessageTypeTelegram = channels.MessageTypeTelegram
MessageTypeBark = channels.MessageTypeBark
MessageTypePushMe = channels.MessageTypePushMe
)
// ChannelRegistry 渠道注册表
@@ -97,6 +98,7 @@ func GetGlobalChannelRegistry() *ChannelRegistry {
globalChannelRegistry.Register(channels.NewEmailChannel())
globalChannelRegistry.Register(channels.NewDtalkChannel())
globalChannelRegistry.Register(channels.NewQyWeiXinChannel())
globalChannelRegistry.Register(channels.NewWeChatCorpAccountChannel())
globalChannelRegistry.Register(channels.NewFeishuChannel())
globalChannelRegistry.Register(channels.NewCustomChannel())
globalChannelRegistry.Register(channels.NewWeChatOFAccountChannel())
@@ -13,6 +13,7 @@ const (
MessageTypeEmail = constant.MessageTypeEmail
MessageTypeDtalk = constant.MessageTypeDtalk
MessageTypeQyWeiXin = constant.MessageTypeQyWeiXin
MessageTypeWeChatCorpAccount = constant.MessageTypeWeChatCorpAccount
MessageTypeFeishu = constant.MessageTypeFeishu
MessageTypeCustom = constant.MessageTypeCustom
MessageTypeWeChatOFAccount = constant.MessageTypeWeChatOFAccount
@@ -0,0 +1,76 @@
package channels
import (
"fmt"
"message-nest/models"
"message-nest/pkg/message"
"message-nest/service/send_ins_service"
"message-nest/service/send_way_service"
"strings"
)
type WeChatCorpAccountChannel struct{ *BaseChannel }
func NewWeChatCorpAccountChannel() *WeChatCorpAccountChannel {
return &WeChatCorpAccountChannel{BaseChannel: NewBaseChannel(MessageTypeWeChatCorpAccount, []string{FormatTypeMarkdown, FormatTypeText})}
}
func (c *WeChatCorpAccountChannel) SendUnified(msgObj interface{}, ins models.SendTasksIns, content *UnifiedMessageContent) (string, string) {
auth, ok := msgObj.(*send_way_service.WayDetailWeChatCorpAccount)
if !ok {
return "", "类型转换失败"
}
insService := send_ins_service.SendTaskInsService{}
errStr, configInterface := insService.ValidateDiffIns(ins)
if errStr != "" {
return errStr, ""
}
config, ok := configInterface.(models.InsWeChatCorpAccountConfig)
if !ok {
return "企业微信应用config校验失败", ""
}
contentType, formattedContent, err := c.FormatContent(content)
if err != nil {
return "", err.Error()
}
toUser := config.ToAccount
if content.IsAtAll() {
toUser = "@all"
} else {
atUserIds := content.GetAtUserIds()
if len(atUserIds) > 0 {
toUser = strings.Join(atUserIds, "|")
}
}
cli := message.WeChatCorpAccount{
CorpID: auth.CorpID,
AgentID: auth.AgentID,
AgentSecret: auth.AgentSecret,
ProxyURL: auth.ProxyURL,
}
var res string
var sendErr error
if contentType == FormatTypeMarkdown {
res, sendErr = cli.SendMarkdown(toUser, formattedContent)
} else if contentType == FormatTypeText {
if content.Title != "" && content.URL != "" {
res, sendErr = cli.SendTextCard(toUser, content.Title, formattedContent, content.URL)
} else {
res, sendErr = cli.SendText(toUser, formattedContent)
}
} else {
sendErr = fmt.Errorf("未知的企业微信应用发送内容类型:%s", contentType)
}
var errMsg string
if sendErr != nil {
errMsg = fmt.Sprintf("发送失败:%s", sendErr.Error())
}
return res, errMsg
}