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
}
相关推荐
haing20198 小时前
协作机器人拖动示教控制方法的实现原理介绍
机器人·拖动示教
北京盟通科技官方账号10 小时前
Ixxat Mobilizer系列:助力汽车组件的高效下线测试
网络协议·机器人·自动化·汽车·制造
秋刀鱼 ..10 小时前
第五届大数据经济与数字化管理国际学术会议(BDEDM 2026)
大数据·运维·人工智能·python·机器人·自动化
秋刀鱼 ..10 小时前
第五届大数据、信息与计算机网络国际学术会议(BDICN 2026)
大数据·人工智能·python·计算机网络·机器人·制造
TsingtaoAI12 小时前
具身智能核心突破:物理模拟器与世界模型协同技术拆解
人工智能·机器人
秋刀鱼 ..12 小时前
2025机器人与智能制造技术国际会议 (ISRIMT 2025)
人工智能·python·机器人·制造·新人首发
abcefg_h12 小时前
Cookie,Session的介绍和如何保持TCP连接
网络·网络协议·tcp/ip·golang
电话交换机IPPBX-3CX13 小时前
IPPBX电话客服机器人实战:自定义知识库 + OpenAI 实时语音
人工智能·机器人·open ai·电话交换机
卿雪14 小时前
Redis 缓存问题:穿透、击穿、雪崩是什么及其解决方案
java·数据库·redis·sql·mysql·缓存·golang
Deepoch14 小时前
Deepoc具身智能:让采摘机器人读懂果实的生命语言
大数据·人工智能·机器人·采摘机器人·农业机器人·deepoc