diff --git a/models/send_ins.go b/models/send_ins.go index 01c50ed..c10a721 100644 --- a/models/send_ins.go +++ b/models/send_ins.go @@ -22,6 +22,10 @@ type InsEmailConfig struct { type InsDtalkConfig struct { } +// InsQyWeiXinConfig 实例里面的企业微信config +type InsQyWeiXinConfig struct { +} + // InsCustomConfig 实例里面的自定义config type InsCustomConfig struct { } diff --git a/pkg/message/qyweixin.go b/pkg/message/qyweixin.go new file mode 100644 index 0000000..d2a4968 --- /dev/null +++ b/pkg/message/qyweixin.go @@ -0,0 +1,79 @@ +package message + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" +) + +type qywxResponse struct { + Code int `json:"errcode"` + Msg string `json:"errmsg"` +} + +type QyWeiXin struct { + AccessToken string +} + +func (t *QyWeiXin) Request(msg interface{}) ([]byte, error) { + b, err := json.Marshal(msg) + if err != nil { + return nil, err + } + resp, err := http.Post(t.getURL(), "application/json", bytes.NewBuffer(b)) + if err != nil { + return nil, err + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + + } + }(resp.Body) + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var r qywxResponse + err = json.Unmarshal(body, &r) + if err != nil { + return body, err + } + if r.Code != 0 { + return body, errors.New(fmt.Sprintf("response error: %s", string(body))) + } + return body, err +} + +// SendMessageText Function to send message +func (t *QyWeiXin) SendMessageText(text string, at ...string) ([]byte, error) { + msg := map[string]interface{}{ + "msgtype": "text", + "text": map[string]string{ + "content": text, + }, + } + resp, err := t.Request(msg) + return resp, err +} + +func (t *QyWeiXin) SendMessageMarkdown(title, text string, at ...string) ([]byte, error) { + msg := map[string]interface{}{ + "msgtype": "markdown", + "markdown": map[string]string{ + "title": title, + "content": text, + }, + } + resp, err := t.Request(msg) + return resp, err +} + +func (t *QyWeiXin) getURL() string { + url := "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + t.AccessToken + return url +} diff --git a/service/send_ins_service/send_ins.go b/service/send_ins_service/send_ins.go index dca1946..e8fbb68 100644 --- a/service/send_ins_service/send_ins.go +++ b/service/send_ins_service/send_ins.go @@ -35,6 +35,10 @@ func (sw *SendTaskInsService) ValidateDiffIns(ins models.SendTasksIns) (string, var Config models.InsDtalkConfig return "", Config } + if ins.WayType == "QyWeiXin" { + var Config models.InsQyWeiXinConfig + return "", Config + } if ins.WayType == "Custom" { var Config models.InsCustomConfig err := json.Unmarshal([]byte(ins.Config), &Config) diff --git a/service/send_message_service/send_message.go b/service/send_message_service/send_message.go index d2c3f00..f1ecd2b 100644 --- a/service/send_message_service/send_message.go +++ b/service/send_message_service/send_message.go @@ -139,6 +139,15 @@ func (sm *SendMessageService) Send() string { sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg)) continue } + // 企业微信类型的实例发送 + qywxAuth, ok := msgObj.(send_way_service.WayDetailQyWeiXin) + if ok { + es := QyWeiXinService{} + res, errMsg := es.SendQyWeiXinMessage(qywxAuth, ins.SendTasksIns, typeC, sm.Title, content) + sm.LogsAndStatusMark(fmt.Sprintf("返回内容:%s", res), sm.Status) + sm.LogsAndStatusMark(sm.TransError(errMsg), errStrIsSuccess(errMsg)) + continue + } // 自定义webhook类型的实例发送 customAuth, ok := msgObj.(send_way_service.WayDetailCustom) if ok { diff --git a/service/send_message_service/send_qywexin.go b/service/send_message_service/send_qywexin.go new file mode 100644 index 0000000..029b5ce --- /dev/null +++ b/service/send_message_service/send_qywexin.go @@ -0,0 +1,46 @@ +package send_message_service + +import ( + "fmt" + "message-nest/models" + "message-nest/pkg/message" + "message-nest/service/send_ins_service" + "message-nest/service/send_way_service" +) + +type QyWeiXinService struct { +} + +// SendDtalkMessage 执行发送钉钉 +func (s *QyWeiXinService) SendQyWeiXinMessage(auth send_way_service.WayDetailQyWeiXin, ins models.SendTasksIns, typeC string, title string, content string) (string, string) { + insService := send_ins_service.SendTaskInsService{} + errStr, c := insService.ValidateDiffIns(ins) + if errStr != "" { + return errStr, "" + } + _, ok := c.(models.InsQyWeiXinConfig) + if !ok { + return "企业微信config校验失败", "" + } + + errMsg := "" + var res []byte + var err error + cli := message.QyWeiXin{ + AccessToken: auth.AccessToken, + } + if typeC == "text" { + res, err = cli.SendMessageText(content) + if err != nil { + errMsg = fmt.Sprintf("发送失败:%s", ins.ContentType) + } + } else if typeC == "markdown" { + res, err = cli.SendMessageMarkdown(title, content) + if err != nil { + errMsg = fmt.Sprintf("发送失败:%s", ins.ContentType) + } + } else { + errMsg = fmt.Sprintf("未知的企业微信发送内容类型:%s", ins.ContentType) + } + return string(res), errMsg +} diff --git a/service/send_way_service/send_way.go b/service/send_way_service/send_way.go index 067dad9..05ebe8f 100644 --- a/service/send_way_service/send_way.go +++ b/service/send_way_service/send_way.go @@ -38,6 +38,11 @@ type WayDetailDTalk struct { Secret string `json:"secret" validate:"max=100" label:"钉钉加签秘钥"` } +// WayDetailQyWeiXin 企业微信渠道明细字段 +type WayDetailQyWeiXin struct { + AccessToken string `json:"access_token" validate:"required,max=100" label:"企业微信access_token"` +} + // WayDetailCustom 自定义渠道 type WayDetailCustom struct { Webhook string `json:"webhook" validate:"required,max=200" label:"自定义的webhook地址"` @@ -108,6 +113,14 @@ func (sw *SendWay) ValidateDiffWay() (string, interface{}) { } _, Msg := app.CommonPlaygroundValid(dtalk) return Msg, dtalk + } else if sw.Type == "QyWeiXin" { + var config WayDetailQyWeiXin + err := json.Unmarshal([]byte(sw.Auth), &config) + if err != nil { + return "企业微信auth反序列化失败!", empty + } + _, Msg := app.CommonPlaygroundValid(config) + return Msg, config } else if sw.Type == "Custom" { var custom WayDetailCustom err := json.Unmarshal([]byte(sw.Auth), &custom) @@ -142,6 +155,17 @@ func (sw *SendWay) TestSendWay(msgObj interface{}) (string, string) { } return "", string(res) } + qywxAuth, ok := msgObj.(WayDetailQyWeiXin) + if ok { + var cli = message.QyWeiXin{ + AccessToken: qywxAuth.AccessToken, + } + res, err := cli.SendMessageText(testMsg) + if err != nil { + return fmt.Sprintf("发送失败:%s", err), string(res) + } + return "", string(res) + } customAuth, ok := msgObj.(WayDetailCustom) if ok { var cli = message.CustomWebhook{} diff --git a/web/src/constant.js b/web/src/constant.js index da45541..1ec7768 100644 --- a/web/src/constant.js +++ b/web/src/constant.js @@ -29,7 +29,6 @@ const CONSTANT = { taskInsInputs: [ { value: '', col: 'to_account', desc: "目的邮箱账号(发给谁)" }, // { value: '', col: 'title', desc: "邮箱标题" }, - ], }, { @@ -50,6 +49,22 @@ const CONSTANT = { taskInsInputs: [ ], }, + { + type: 'QyWeiXin', + label: '企业微信', + inputs: [ + { subLabel: 'token', value: '', col: 'access_token', desc: "企业微信webhook中的token" }, + { subLabel: '渠道名', value: '', col: 'name', desc: "想要设置的渠道名字" }, + ], + tips: { + }, + taskInsRadios: [ + { subLabel: 'text', content: 'text' }, + { subLabel: 'markdown', content: 'markdown' }, + ], + taskInsInputs: [ + ], + }, { type: 'Custom', label: '自定义', diff --git a/web/src/views/tabsTools/sendTasks/view/editTaskPopUp.vue b/web/src/views/tabsTools/sendTasks/view/editTaskPopUp.vue index 90ba2d0..2c60dfe 100644 --- a/web/src/views/tabsTools/sendTasks/view/editTaskPopUp.vue +++ b/web/src/views/tabsTools/sendTasks/view/editTaskPopUp.vue @@ -205,6 +205,7 @@ export default defineComponent({ const getFinalData = () => { let postData = { id: uuidv4(), + enable: 1, task_id: state.currTaskInput.taskId, way_id: state.currWayTmp.id, way_type: state.currWayTmp.type,