golang调用钉钉发送群机器人消息
因为当时用的wire依赖注入,所以需要用多个钉钉机器人的时候,就把每个client实例加入到了map里
go
package ding
type Client interface {
// SendMessage 发送钉钉
SendMessage(s string, at ...string) error
}
type ClientOpt struct {
Name string
Token string
Secret string
}
type ClientOptList []*ClientOpt
type ClientList map[string]Client
func NewClientList(opt ClientOptList) ClientList {
l := make(map[string]Client)
for _, item := range opt {
if item.Token != "" && item.Secret != "" {
l[item.Name] = NewClient(item.Token, item.Secret)
}
}
return l
}
func (p ClientList) GetClient(name string) Client {
if v, ok := p[name]; ok {
return v
}
return nil
}
func (p ClientList) SendMessage(client string, s string, at ...string) error {
if v, ok := p[client]; ok {
return v.SendMessage(s, at...)
}
return nil
}
go
package ding
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"time"
)
type ClientImpl struct {
AccessToken string
Secret string
EnableAt bool
AtAll bool
}
func NewClient(token, secret string, opt ...DingOptionFn) Client {
r := &ClientImpl{
AccessToken: token,
Secret: secret,
}
for _, v := range opt {
v(r)
}
return r
}
type DingOptionFn func(*ClientImpl)
func WithEnableAt() DingOptionFn {
return func(client *ClientImpl) {
client.EnableAt = true
}
}
func WithAtAll() DingOptionFn {
return func(client *ClientImpl) {
client.AtAll = true
}
}
// From https://github.com/wanghuiyt/ding
// SendMessage Function to send message
//
//goland:noinspection GoUnhandledErrorResult
func (p *ClientImpl) SendMessage(s string, at ...string) error {
msg := map[string]interface{}{
"msgtype": "text",
"text": map[string]string{
"content": s,
},
}
if p.EnableAt {
if p.AtAll {
if len(at) > 0 {
return errors.New("the parameter \"AtAll\" is \"true\", but the \"at\" parameter of SendMessage is not empty")
}
msg["at"] = map[string]interface{}{
"isAtAll": p.AtAll,
}
} else {
msg["at"] = map[string]interface{}{
"atMobiles": at,
"isAtAll": p.AtAll,
}
}
} else {
if len(at) > 0 {
return errors.New("the parameter \"EnableAt\" is \"false\", but the \"at\" parameter of SendMessage is not empty")
}
}
b, err := json.Marshal(msg)
if err != nil {
return err
}
resp, err := http.Post(p.getURL(), "application/json", bytes.NewBuffer(b))
if err != nil {
return err
}
defer resp.Body.Close()
_, err = io.ReadAll(resp.Body)
if err != nil {
return err
}
return nil
}
func (p *ClientImpl) hmacSha256(stringToSign string, secret string) string {
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(stringToSign))
return base64.StdEncoding.EncodeToString(h.Sum(nil))
}
func (p *ClientImpl) getURL() string {
wh := "https://oapi.dingtalk.com/robot/send?access_token=" + p.AccessToken
timestamp := time.Now().UnixNano() / 1e6
stringToSign := fmt.Sprintf("%d\n%s", timestamp, p.Secret)
sign := p.hmacSha256(stringToSign, p.Secret)
url := fmt.Sprintf("%s×tamp=%d&sign=%s", wh, timestamp, sign)
return url
}