im add wechat_robot and dingtalk_robot (#332)

* im wechat

* im wechat

* im add wechat_robot dingtalk_robot

Co-authored-by: alickliming <alickliming@didi.global.com>
This commit is contained in:
alick-liming 2020-10-11 08:24:04 +08:00 committed by GitHub
parent 8c5e9534b2
commit e84d7f8741
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 160 additions and 1 deletions

View File

@ -73,7 +73,7 @@ sender:
worker: 10 worker: 10
api: http://127.0.0.1:2008/voice api: http://127.0.0.1:2008/voice
im: im:
# three choice: shell|api|wechat # five choice: shell|api|wechat|wechat_robot|dingtalk_robot
way: shell way: shell
worker: 10 worker: 10
api: http://127.0.0.1:2008/im api: http://127.0.0.1:2008/im

View File

@ -12,6 +12,7 @@ import (
"github.com/didi/nightingale/src/common/dataobj" "github.com/didi/nightingale/src/common/dataobj"
"github.com/didi/nightingale/src/modules/rdb/config" "github.com/didi/nightingale/src/modules/rdb/config"
"github.com/didi/nightingale/src/modules/rdb/dingtalk"
"github.com/didi/nightingale/src/modules/rdb/redisc" "github.com/didi/nightingale/src/modules/rdb/redisc"
"github.com/didi/nightingale/src/modules/rdb/wechat" "github.com/didi/nightingale/src/modules/rdb/wechat"
) )
@ -50,6 +51,10 @@ func sendIm(message *dataobj.Message) {
sendImByShell(message) sendImByShell(message)
case "wechat": case "wechat":
sendImByWeChat(message) sendImByWeChat(message)
case "wechat_robot":
sendImByWeChatRobot(message)
case "dingtalk_robot":
sendImByDingTalkRobot(message)
default: default:
logger.Errorf("not support %s to send im, im: %+v", config.Config.Sender["im"].Way, message) logger.Errorf("not support %s to send im, im: %+v", config.Config.Sender["im"].Way, message)
} }
@ -103,3 +108,62 @@ func sendImByWeChat(message *dataobj.Message) {
} }
} }
} }
func sendImByWeChatRobot(message *dataobj.Message) {
cnt := len(message.Tos)
if cnt == 0 {
logger.Warningf("im send wechat_robot fail, empty tos, message: %+v", message)
return
}
for i := 0; i < cnt; i++ {
toUser := strings.TrimSpace(message.Tos[i])
if toUser == "" {
continue
}
mess := wechat.Message{
ToUser: toUser,
MsgType: "text",
Text: wechat.Content{Content: message.Content},
}
err := wechat.RobotSend(mess)
if err != nil {
logger.Warningf("im wechat_robot send to %s fail: %v", message.Tos[i], err)
} else {
logger.Infof("im wechat_robot send to %s succ", message.Tos[i])
}
}
}
func sendImByDingTalkRobot(message *dataobj.Message) {
cnt := len(message.Tos)
if cnt == 0 {
logger.Warningf("im send dingtalk_robot fail, empty tos, message: %+v", message)
return
}
nodupDingCluster := make(map[string]bool, cnt)
for i := 0; i < cnt; i++ {
toUser := strings.TrimSpace(message.Tos[i])
if toUser == "" {
continue
}
if _, ok := nodupDingCluster[toUser]; !ok {
nodupDingCluster[toUser] = true
}
}
for tokenUser, ok := range nodupDingCluster {
if ok {
err := dingtalk.RobotSend(tokenUser, message.Content)
if err != nil {
logger.Warningf("im dingtalk_robot send to %s fail: %v", tokenUser, err)
} else {
logger.Infof("im dingtalk_robot send to %s succ", tokenUser)
}
}
}
}

View File

@ -0,0 +1,69 @@
package dingtalk
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type Result struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
}
type dingReqData struct {
Msgtype string `json:"msgtype"`
Text *textContent `json:"text"`
}
type textContent struct {
Content string `json:"content"`
}
// RobotSend robot发送信息
func RobotSend(tokenUser, sendContent string) error {
url := "https://oapi.dingtalk.com/robot/send?access_token=" + tokenUser
dingReqData := new(dingReqData)
dingReqData.Msgtype = "text"
reqContent := new(textContent)
reqContent.Content = sendContent
dingReqData.Text = reqContent
content, err := json.Marshal(dingReqData)
if err != nil {
return fmt.Errorf("dingtalk marshal req data err: %v", err)
}
data := bytes.NewReader(content)
req, err := http.NewRequest("POST", url, data)
if err != nil {
return fmt.Errorf("dingtalk create new req err: %v", err)
}
req.Header.Set("Content-Type", "application/json")
r, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("dingtalk do req err: %v", err)
}
defer r.Body.Close()
resp, err := ioutil.ReadAll(r.Body)
if err != nil {
return fmt.Errorf("dingtalk read req body err: %v", err)
}
result := Result{}
err = json.Unmarshal(resp, &result)
if err != nil {
return fmt.Errorf("dingtalk unmarshal req content err: %v", err)
}
if result.ErrCode != 0 {
err = fmt.Errorf("dingtalk req return ErrCode = %d ErrMsg = %s", result.ErrCode, result.ErrMsg)
}
return err
}

View File

@ -179,3 +179,29 @@ func encodeJSON(v interface{}) ([]byte, error) {
} }
return buf.Bytes(), nil return buf.Bytes(), nil
} }
// RobotSend robot发送信息
func RobotSend(msg Message) error {
url := "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + msg.ToUser
resultByte, err := jsonPost(url, msg)
if err != nil {
return fmt.Errorf("invoke send api fail: %v", err)
}
result := Result{}
err = json.Unmarshal(resultByte, &result)
if err != nil {
return fmt.Errorf("parse send api response fail: %v", err)
}
if result.ErrCode != 0 {
err = fmt.Errorf("invoke send api return ErrCode = %d", result.ErrCode)
}
if result.InvalidUser != "" || result.InvalidParty != "" || result.InvalidTag != "" {
err = fmt.Errorf("invoke send api partial fail, invalid user: %s, invalid party: %s, invalid tag: %s", result.InvalidUser, result.InvalidParty, result.InvalidTag)
}
return err
}