golang调用钉钉发送群机器人消息

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&timestamp=%d&sign=%s", wh, timestamp, sign)
	return url
}
相关推荐
田里的水稻7 小时前
ubuntu22.04_openclaw_ROS2
人工智能·python·机器人
小红卒10 小时前
Go语言安全开发学习笔记1:Windows反向TCP反弹Shell 原理与代码
golang
年少无为呀!10 小时前
OpenClaw 飞书 Skill 开发完全指南
python·机器人·飞书·助手·openclaw·skill开发
yhdata11 小时前
精准锚定2032!全自动移液机器人市场规模预计突破97.8亿元
人工智能·机器人
YMWM_11 小时前
机器人模型预测控制MPC简要介绍
机器人·控制算法
niuniudengdeng11 小时前
六面独立转动魔方还原机器人设计与实现
数学·算法·机器人
沫儿笙11 小时前
CLOOS克鲁斯机器人H型钢柱焊接节气装置
机器人
zh路西法12 小时前
【宇树机器人强化学习】(一):PPO算法的python实现与解析
python·深度学习·算法·机器学习·机器人
胡摩西13 小时前
毫米级精准定位如何实现机器人自动回充:技术原理与工程实现
人工智能·机器学习·机器人·slam·室内定位·agv·roomaps
是Yu欸13 小时前
【CANN】Pi0机器人大模型 × 昇腾A2 测评
机器人·大模型·华为snap·gitcode·昇腾·vla