From d894fe32d8568bc3f692eaa4b51f2ed78750eee6 Mon Sep 17 00:00:00 2001 From: JustSong Date: Fri, 25 Nov 2022 12:04:36 +0800 Subject: [PATCH] feat: channel corp is done --- README.md | 13 ++++--- channel/corp.go | 60 +++++++++++++++++++++++++++++++ channel/main.go | 5 ++- controller/user.go | 1 + model/user.go | 3 +- web/src/components/PushSetting.js | 48 +++++++++++++++++++------ 6 files changed, 113 insertions(+), 17 deletions(-) create mode 100644 channel/corp.go diff --git a/README.md b/README.md index f09d98c..28f9fcf 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,11 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式, 1. 多种消息推送方式: + 邮件消息, + 微信测试号, - + 企业微信, + + 企业微信应用号, + + 企业微信群机器人 + 飞书群机器人, + 钉钉群机器人, - + Bark, + + Bark App, + [桌面客户端](https://github.com/songquanpeng/personal-assistant)(WIP) 2. 多种用户登录注册方式: + 邮箱登录注册以及通过邮箱进行密码重置。 @@ -133,9 +134,11 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式, 4. `channel`:选填,如果不填则系统使用你在后台设置的默认推送方式。可选的推送方式有: 1. `email`:通过发送邮件的方式进行推送。 2. `test`:通过微信测试号进行推送。 - 3. `corp`:通过企业微信的应用号进行推送。 - 4. `lark`:通过飞书群机器人进行推送。 - 5. `ding`:通过钉钉群机器人进行推送。 + 3. `corp_app`:通过企业微信应用号进行推送。 + 4. `corp`:通过企业微信群机器人推送。 + 5. `lark`:通过飞书群机器人进行推送。 + 6. `ding`:通过钉钉群机器人进行推送。 + 7. `bark`:通过 Bark 进行推送。 5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。 3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。 diff --git a/channel/corp.go b/channel/corp.go new file mode 100644 index 0000000..d0ba935 --- /dev/null +++ b/channel/corp.go @@ -0,0 +1,60 @@ +package channel + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "message-pusher/model" + "net/http" +) + +type corpMessageRequest struct { + MessageType string `json:"msgtype"` + Text struct { + Content string `json:"content"` + } `json:"text"` + Markdown struct { + Content string `json:"content"` + } `json:"markdown"` +} + +type corpMessageResponse struct { + Code int `json:"errcode"` + Message string `json:"errmsg"` +} + +func SendCorpMessage(message *Message, user *model.User) error { + if user.CorpWebhookURL == "" { + return errors.New("未配置企业微信群机器人消息推送方式") + } + messageRequest := corpMessageRequest{ + MessageType: "text", + } + if message.Content == "" { + messageRequest.MessageType = "text" + messageRequest.Text.Content = message.Description + } else { + messageRequest.MessageType = "markdown" + messageRequest.Markdown.Content = message.Content + } + + jsonData, err := json.Marshal(messageRequest) + if err != nil { + return err + } + resp, err := http.Post(fmt.Sprintf("%s", user.CorpWebhookURL), "application/json", + bytes.NewBuffer(jsonData)) + if err != nil { + return err + } + var res corpMessageResponse + err = json.NewDecoder(resp.Body).Decode(&res) + if err != nil { + return err + } + if res.Code != 0 { + return errors.New(res.Message) + } + return nil +} diff --git a/channel/main.go b/channel/main.go index 77153e5..58cecdd 100644 --- a/channel/main.go +++ b/channel/main.go @@ -8,7 +8,8 @@ import ( const ( TypeEmail = "email" TypeWeChatTestAccount = "test" - TypeWeChatCorpAccount = "corp" + TypeWeChatCorpAccount = "corp_app" + TypeCorp = "corp" TypeLark = "lark" TypeDing = "ding" TypeTelegram = "telegram" @@ -33,6 +34,8 @@ func (message *Message) Send(user *model.User) error { return SendWeChatTestMessage(message, user) case TypeWeChatCorpAccount: return SendWeChatCorpMessage(message, user) + case TypeCorp: + return SendCorpMessage(message, user) case TypeLark: return SendLarkMessage(message, user) case TypeDing: diff --git a/controller/user.go b/controller/user.go index bea72e5..6d53a7a 100644 --- a/controller/user.go +++ b/controller/user.go @@ -409,6 +409,7 @@ func UpdateSelf(c *gin.Context) { WeChatCorpAccountAgentId: user.WeChatCorpAccountAgentId, WeChatCorpAccountUserId: user.WeChatCorpAccountUserId, WeChatCorpAccountClientType: user.WeChatCorpAccountClientType, + CorpWebhookURL: user.CorpWebhookURL, LarkWebhookURL: user.LarkWebhookURL, LarkWebhookSecret: user.LarkWebhookSecret, DingWebhookURL: user.DingWebhookURL, diff --git a/model/user.go b/model/user.go index a6dc7dc..f606fcb 100644 --- a/model/user.go +++ b/model/user.go @@ -31,6 +31,7 @@ type User struct { WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"` WeChatCorpAccountUserId string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"` WeChatCorpAccountClientType string `json:"wechat_corp_account_client_type" gorm:"column:wechat_corp_account_client_type;default=plugin"` + CorpWebhookURL string `json:"corp_webhook_url" gorm:"corp_webhook_url"` LarkWebhookURL string `json:"lark_webhook_url"` LarkWebhookSecret string `json:"lark_webhook_secret"` DingWebhookURL string `json:"ding_webhook_url"` @@ -70,7 +71,7 @@ func GetUserById(id int, selectAll bool) (*User, error) { "channel", "token", "wechat_test_account_id", "wechat_test_account_template_id", "wechat_test_account_open_id", "wechat_corp_account_id", "wechat_corp_account_agent_id", "wechat_corp_account_user_id", "wechat_corp_account_client_type", - "lark_webhook_url", "ding_webhook_url", "bark_server", + "corp_webhook_url", "lark_webhook_url", "ding_webhook_url", "bark_server", }).First(&user, "id = ?", id).Error } return &user, err diff --git a/web/src/components/PushSetting.js b/web/src/components/PushSetting.js index 9e5e89f..e9dea8d 100644 --- a/web/src/components/PushSetting.js +++ b/web/src/components/PushSetting.js @@ -24,6 +24,7 @@ const PushSetting = () => { wechat_corp_account_agent_id: '', wechat_corp_account_user_id: '', wechat_corp_account_client_type: '', + corp_webhook_url: '', lark_webhook_url: '', lark_webhook_secret: '', ding_webhook_url: '', @@ -81,7 +82,7 @@ const PushSetting = () => { inputs.wechat_test_account_template_id; data.wechat_test_account_open_id = inputs.wechat_test_account_open_id; break; - case 'corp': + case 'corp_app': data.wechat_corp_account_id = inputs.wechat_corp_account_id; data.wechat_corp_account_agent_secret = inputs.wechat_corp_account_agent_secret; @@ -90,6 +91,9 @@ const PushSetting = () => { data.wechat_corp_account_client_type = inputs.wechat_corp_account_client_type; break; + case 'corp': + data.corp_webhook_url = inputs.corp_webhook_url; + break; case 'lark': data.lark_webhook_url = inputs.lark_webhook_url; data.lark_webhook_secret = inputs.lark_webhook_secret; @@ -142,10 +146,11 @@ const PushSetting = () => { options={[ { key: 'email', text: '邮件', value: 'email' }, { key: 'test', text: '微信测试号', value: 'test' }, - { key: 'corp', text: '企业微信', value: 'corp' }, + { key: 'corp_app', text: '企业微信应用号', value: 'corp_app' }, + { key: 'corp', text: '企业微信群机器人', value: 'corp' }, { key: 'lark', text: '飞书群机器人', value: 'lark' }, { key: 'ding', text: '钉钉群机器人', value: 'ding' }, - { key: 'bark', text: 'Bark', value: 'bark' }, + { key: 'bark', text: 'Bark App', value: 'bark' }, ]} value={inputs.channel} onChange={handleInputChange} @@ -231,9 +236,9 @@ const PushSetting = () => {
- 企业微信设置(corp) + 企业微信应用号设置(corp_app) - 通过企业微信进行推送,点击前往配置: + 通过企业微信应用号进行推送,点击前往配置: { onChange={handleInputChange} /> + + + +
+ 企业微信群机器人设置(corp) + + 通过企业微信群机器人进行推送,配置流程:选择一个群聊 -> 设置 -> + 群机器人 -> 添加 -> 新建 -> 输入名字,点击添加 -> 点击复制 Webhook + 地址 + +
+ + +
- 飞书设置(lark) + 飞书群机器人设置(lark) 通过飞书群机器人进行推送,飞书桌面客户端的配置流程:选择一个群聊 -> 设置 -> 群机器人 -> 添加机器人 -> 自定义机器人 -> 添加( @@ -346,11 +374,11 @@ const PushSetting = () => {
- 钉钉设置(ding) + 钉钉群机器人设置(ding) - 通过钉钉机器人进行推送,钉钉桌面客户端的配置流程:选择一个群聊 -> - 群设置 -> 智能群助手 -> 添加机器人(点击右侧齿轮图标) -> 自定义 - -> 添加( + 通过钉钉群机器人进行推送,钉钉桌面客户端的配置流程:选择一个群聊 + -> 群设置 -> 智能群助手 -> 添加机器人(点击右侧齿轮图标) -> + 自定义 -> 添加( 注意选中「加密」)。具体参见: