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
}
相关推荐
小lo想吃棒棒糖25 分钟前
把 启元机器人Q1 的训练搬到昇腾 910B:从 MuJoCo 到 PPO 的一次完整迁移
人工智能·python·机器人·昇腾·具身智能
szxinmai主板定制专家1 小时前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
大江东去浪淘尽千古风流人物1 小时前
【RoboDojo】仿真与真实双轨机器人操纵基准:测试流程与防作弊机制深度解析
机器人·vla·评测基准·机器人操纵·robodojo·sim-to-real
脆性薄片搬运谢工10 小时前
移栽电控箱放在机架上还是单独落地,产线布局哪个更合理?
机器人·脆性薄片搬运专机·桁架机械手·桁架机器人·特种桁架搬运专机
广州虚拟动力-动捕&虚拟主播11 小时前
从视角一致性看具身智能:头戴式采集设备的不可替代性
机器人
xwz小王子16 小时前
Science Advances 让机器人触觉在重压下继续分辨微小变化
机器人·1024程序员节
xiaogai_gai17 小时前
采购业务退款单同步实战:从钉钉审批流到金蝶云星空付款单
java·数据库·钉钉
GlobalInfo21 小时前
机器人线缆用无卤TPU料市场分析报告深度版:产业洞察、技术演进与路径
大数据·人工智能·机器人
AiNightVision1 天前
电力巡检夜视方案选型指南——无人机/机器人/固定监测三种场景怎么选
人工智能·科技·车载系统·机器人·无人机·边缘计算·视频
紧跟先前的步伐1 天前
Go AI Agent 实战 22|完善 Agent 执行循环:从工具调用到最终回答
人工智能·ai·golang