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
}
相关推荐
CHN悠远1 小时前
debian13 安装钉钉后,钉钉无法运行问题的解决办法
linux·运维·服务器·钉钉·debian13
nenchoumi31192 小时前
ROS2 Humble 笔记(七)标准与自定义 Interface 接口
笔记·机器人·ros2
音视频牛哥5 小时前
从 RTSP/RTP/RTCP 到系统级时间闭环:跨平台低延迟RTSP播放架构解析
计算机视觉·机器人·音视频·rtsp播放器·linux rtsp播放器·windows rtsp播放器·安卓播放rtsp流
Wzx1980127 小时前
go基础语法练习
开发语言·后端·golang
EVERSPIN19 小时前
MCU微控制器,N32H47x高性能MCU机器人关节控制方案
单片机·嵌入式硬件·机器人·mcu微控制器
点云SLAM20 小时前
弱纹理图像特征匹配算法推荐汇总
人工智能·深度学习·算法·计算机视觉·机器人·slam·弱纹理图像特征匹配
RedJACK~20 小时前
Go Ebiten小游戏开发:扫雷
开发语言·后端·golang
研究司马懿21 小时前
【ETCD】ETCD——confd配置管理
数据库·golang·自动化·运维开发·etcd·argocd·gitops
权泽谦1 天前
用 Flask + OpenAI API 打造一个智能聊天机器人(附完整源码与部署教程)
python·机器人·flask
洞见新研社1 天前
家庭机器人,从科幻到日常的二十年突围战
大数据·人工智能·机器人