feat: channel corp is done
This commit is contained in:
@@ -41,10 +41,11 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式,
|
|||||||
1. 多种消息推送方式:
|
1. 多种消息推送方式:
|
||||||
+ 邮件消息,
|
+ 邮件消息,
|
||||||
+ 微信测试号,
|
+ 微信测试号,
|
||||||
+ 企业微信,
|
+ 企业微信应用号,
|
||||||
|
+ 企业微信群机器人
|
||||||
+ 飞书群机器人,
|
+ 飞书群机器人,
|
||||||
+ 钉钉群机器人,
|
+ 钉钉群机器人,
|
||||||
+ Bark,
|
+ Bark App,
|
||||||
+ [桌面客户端](https://github.com/songquanpeng/personal-assistant)(WIP)
|
+ [桌面客户端](https://github.com/songquanpeng/personal-assistant)(WIP)
|
||||||
2. 多种用户登录注册方式:
|
2. 多种用户登录注册方式:
|
||||||
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
+ 邮箱登录注册以及通过邮箱进行密码重置。
|
||||||
@@ -133,9 +134,11 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式,
|
|||||||
4. `channel`:选填,如果不填则系统使用你在后台设置的默认推送方式。可选的推送方式有:
|
4. `channel`:选填,如果不填则系统使用你在后台设置的默认推送方式。可选的推送方式有:
|
||||||
1. `email`:通过发送邮件的方式进行推送。
|
1. `email`:通过发送邮件的方式进行推送。
|
||||||
2. `test`:通过微信测试号进行推送。
|
2. `test`:通过微信测试号进行推送。
|
||||||
3. `corp`:通过企业微信的应用号进行推送。
|
3. `corp_app`:通过企业微信应用号进行推送。
|
||||||
4. `lark`:通过飞书群机器人进行推送。
|
4. `corp`:通过企业微信群机器人推送。
|
||||||
5. `ding`:通过钉钉群机器人进行推送。
|
5. `lark`:通过飞书群机器人进行推送。
|
||||||
|
6. `ding`:通过钉钉群机器人进行推送。
|
||||||
|
7. `bark`:通过 Bark 进行推送。
|
||||||
5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。
|
5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。
|
||||||
3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。
|
3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
+4
-1
@@ -8,7 +8,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
TypeEmail = "email"
|
TypeEmail = "email"
|
||||||
TypeWeChatTestAccount = "test"
|
TypeWeChatTestAccount = "test"
|
||||||
TypeWeChatCorpAccount = "corp"
|
TypeWeChatCorpAccount = "corp_app"
|
||||||
|
TypeCorp = "corp"
|
||||||
TypeLark = "lark"
|
TypeLark = "lark"
|
||||||
TypeDing = "ding"
|
TypeDing = "ding"
|
||||||
TypeTelegram = "telegram"
|
TypeTelegram = "telegram"
|
||||||
@@ -33,6 +34,8 @@ func (message *Message) Send(user *model.User) error {
|
|||||||
return SendWeChatTestMessage(message, user)
|
return SendWeChatTestMessage(message, user)
|
||||||
case TypeWeChatCorpAccount:
|
case TypeWeChatCorpAccount:
|
||||||
return SendWeChatCorpMessage(message, user)
|
return SendWeChatCorpMessage(message, user)
|
||||||
|
case TypeCorp:
|
||||||
|
return SendCorpMessage(message, user)
|
||||||
case TypeLark:
|
case TypeLark:
|
||||||
return SendLarkMessage(message, user)
|
return SendLarkMessage(message, user)
|
||||||
case TypeDing:
|
case TypeDing:
|
||||||
|
|||||||
@@ -409,6 +409,7 @@ func UpdateSelf(c *gin.Context) {
|
|||||||
WeChatCorpAccountAgentId: user.WeChatCorpAccountAgentId,
|
WeChatCorpAccountAgentId: user.WeChatCorpAccountAgentId,
|
||||||
WeChatCorpAccountUserId: user.WeChatCorpAccountUserId,
|
WeChatCorpAccountUserId: user.WeChatCorpAccountUserId,
|
||||||
WeChatCorpAccountClientType: user.WeChatCorpAccountClientType,
|
WeChatCorpAccountClientType: user.WeChatCorpAccountClientType,
|
||||||
|
CorpWebhookURL: user.CorpWebhookURL,
|
||||||
LarkWebhookURL: user.LarkWebhookURL,
|
LarkWebhookURL: user.LarkWebhookURL,
|
||||||
LarkWebhookSecret: user.LarkWebhookSecret,
|
LarkWebhookSecret: user.LarkWebhookSecret,
|
||||||
DingWebhookURL: user.DingWebhookURL,
|
DingWebhookURL: user.DingWebhookURL,
|
||||||
|
|||||||
+2
-1
@@ -31,6 +31,7 @@ type User struct {
|
|||||||
WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"`
|
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"`
|
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"`
|
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"`
|
LarkWebhookURL string `json:"lark_webhook_url"`
|
||||||
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
||||||
DingWebhookURL string `json:"ding_webhook_url"`
|
DingWebhookURL string `json:"ding_webhook_url"`
|
||||||
@@ -70,7 +71,7 @@ func GetUserById(id int, selectAll bool) (*User, error) {
|
|||||||
"channel", "token",
|
"channel", "token",
|
||||||
"wechat_test_account_id", "wechat_test_account_template_id", "wechat_test_account_open_id",
|
"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",
|
"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
|
}).First(&user, "id = ?", id).Error
|
||||||
}
|
}
|
||||||
return &user, err
|
return &user, err
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ const PushSetting = () => {
|
|||||||
wechat_corp_account_agent_id: '',
|
wechat_corp_account_agent_id: '',
|
||||||
wechat_corp_account_user_id: '',
|
wechat_corp_account_user_id: '',
|
||||||
wechat_corp_account_client_type: '',
|
wechat_corp_account_client_type: '',
|
||||||
|
corp_webhook_url: '',
|
||||||
lark_webhook_url: '',
|
lark_webhook_url: '',
|
||||||
lark_webhook_secret: '',
|
lark_webhook_secret: '',
|
||||||
ding_webhook_url: '',
|
ding_webhook_url: '',
|
||||||
@@ -81,7 +82,7 @@ const PushSetting = () => {
|
|||||||
inputs.wechat_test_account_template_id;
|
inputs.wechat_test_account_template_id;
|
||||||
data.wechat_test_account_open_id = inputs.wechat_test_account_open_id;
|
data.wechat_test_account_open_id = inputs.wechat_test_account_open_id;
|
||||||
break;
|
break;
|
||||||
case 'corp':
|
case 'corp_app':
|
||||||
data.wechat_corp_account_id = inputs.wechat_corp_account_id;
|
data.wechat_corp_account_id = inputs.wechat_corp_account_id;
|
||||||
data.wechat_corp_account_agent_secret =
|
data.wechat_corp_account_agent_secret =
|
||||||
inputs.wechat_corp_account_agent_secret;
|
inputs.wechat_corp_account_agent_secret;
|
||||||
@@ -90,6 +91,9 @@ const PushSetting = () => {
|
|||||||
data.wechat_corp_account_client_type =
|
data.wechat_corp_account_client_type =
|
||||||
inputs.wechat_corp_account_client_type;
|
inputs.wechat_corp_account_client_type;
|
||||||
break;
|
break;
|
||||||
|
case 'corp':
|
||||||
|
data.corp_webhook_url = inputs.corp_webhook_url;
|
||||||
|
break;
|
||||||
case 'lark':
|
case 'lark':
|
||||||
data.lark_webhook_url = inputs.lark_webhook_url;
|
data.lark_webhook_url = inputs.lark_webhook_url;
|
||||||
data.lark_webhook_secret = inputs.lark_webhook_secret;
|
data.lark_webhook_secret = inputs.lark_webhook_secret;
|
||||||
@@ -142,10 +146,11 @@ const PushSetting = () => {
|
|||||||
options={[
|
options={[
|
||||||
{ key: 'email', text: '邮件', value: 'email' },
|
{ key: 'email', text: '邮件', value: 'email' },
|
||||||
{ key: 'test', text: '微信测试号', value: 'test' },
|
{ 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: 'lark', text: '飞书群机器人', value: 'lark' },
|
||||||
{ key: 'ding', text: '钉钉群机器人', value: 'ding' },
|
{ key: 'ding', text: '钉钉群机器人', value: 'ding' },
|
||||||
{ key: 'bark', text: 'Bark', value: 'bark' },
|
{ key: 'bark', text: 'Bark App', value: 'bark' },
|
||||||
]}
|
]}
|
||||||
value={inputs.channel}
|
value={inputs.channel}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
@@ -231,9 +236,9 @@ const PushSetting = () => {
|
|||||||
<Button onClick={() => test('test')}>测试</Button>
|
<Button onClick={() => test('test')}>测试</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
企业微信设置(corp)
|
企业微信应用号设置(corp_app)
|
||||||
<Header.Subheader>
|
<Header.Subheader>
|
||||||
通过企业微信进行推送,点击前往配置:
|
通过企业微信应用号进行推送,点击前往配置:
|
||||||
<a
|
<a
|
||||||
target='_blank'
|
target='_blank'
|
||||||
href='https://work.weixin.qq.com/wework_admin/frame#apps'
|
href='https://work.weixin.qq.com/wework_admin/frame#apps'
|
||||||
@@ -302,13 +307,36 @@ const PushSetting = () => {
|
|||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
/>
|
/>
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
|
<Button onClick={() => submit('corp_app')} loading={loading}>
|
||||||
|
保存
|
||||||
|
</Button>
|
||||||
|
<Button onClick={() => test('corp_app')}>测试</Button>
|
||||||
|
<Divider />
|
||||||
|
<Header as='h3'>
|
||||||
|
企业微信群机器人设置(corp)
|
||||||
|
<Header.Subheader>
|
||||||
|
通过企业微信群机器人进行推送,配置流程:选择一个群聊 -> 设置 ->
|
||||||
|
群机器人 -> 添加 -> 新建 -> 输入名字,点击添加 -> 点击复制 Webhook
|
||||||
|
地址
|
||||||
|
</Header.Subheader>
|
||||||
|
</Header>
|
||||||
|
<Form.Group widths={2}>
|
||||||
|
<Form.Input
|
||||||
|
label='Webhook 地址'
|
||||||
|
name='corp_webhook_url'
|
||||||
|
onChange={handleInputChange}
|
||||||
|
autoComplete='off'
|
||||||
|
value={inputs.corp_webhook_url}
|
||||||
|
placeholder='在此填写企业微信提供的 Webhook 地址'
|
||||||
|
/>
|
||||||
|
</Form.Group>
|
||||||
<Button onClick={() => submit('corp')} loading={loading}>
|
<Button onClick={() => submit('corp')} loading={loading}>
|
||||||
保存
|
保存
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={() => test('corp')}>测试</Button>
|
<Button onClick={() => test('corp')}>测试</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
飞书设置(lark)
|
飞书群机器人设置(lark)
|
||||||
<Header.Subheader>
|
<Header.Subheader>
|
||||||
通过飞书群机器人进行推送,飞书桌面客户端的配置流程:选择一个群聊
|
通过飞书群机器人进行推送,飞书桌面客户端的配置流程:选择一个群聊
|
||||||
-> 设置 -> 群机器人 -> 添加机器人 -> 自定义机器人 -> 添加(
|
-> 设置 -> 群机器人 -> 添加机器人 -> 自定义机器人 -> 添加(
|
||||||
@@ -346,11 +374,11 @@ const PushSetting = () => {
|
|||||||
<Button onClick={() => test('lark')}>测试</Button>
|
<Button onClick={() => test('lark')}>测试</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Header as='h3'>
|
<Header as='h3'>
|
||||||
钉钉设置(ding)
|
钉钉群机器人设置(ding)
|
||||||
<Header.Subheader>
|
<Header.Subheader>
|
||||||
通过钉钉机器人进行推送,钉钉桌面客户端的配置流程:选择一个群聊 ->
|
通过钉钉群机器人进行推送,钉钉桌面客户端的配置流程:选择一个群聊
|
||||||
群设置 -> 智能群助手 -> 添加机器人(点击右侧齿轮图标) -> 自定义
|
-> 群设置 -> 智能群助手 -> 添加机器人(点击右侧齿轮图标) ->
|
||||||
-> 添加(
|
自定义 -> 添加(
|
||||||
<strong>注意选中「加密」</strong>)。具体参见:
|
<strong>注意选中「加密」</strong>)。具体参见:
|
||||||
<a
|
<a
|
||||||
target='_blank'
|
target='_blank'
|
||||||
|
|||||||
Reference in New Issue
Block a user