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

embedded/2024/10/18 13:18:59/

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

因为当时用的wire依赖注入,所以需要用多个钉钉机器人的时候,就把每个client实例加入到了map里

package dingtype Client interface {// SendMessage 发送钉钉SendMessage(s string, at ...string) error
}type ClientOpt struct {Name   stringToken  stringSecret string
}
type ClientOptList []*ClientOpt
type ClientList map[string]Clientfunc 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
}
package dingimport ("bytes""crypto/hmac""crypto/sha256""encoding/base64""encoding/json""errors""fmt""io""net/http""time"
)type ClientImpl struct {AccessToken stringSecret      stringEnableAt    boolAtAll       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.AccessTokentimestamp := time.Now().UnixNano() / 1e6stringToSign := 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
}

http://www.ppmy.cn/embedded/29077.html

相关文章

基于SpringBoot+Vue的旅游网站系统

初衷 在后台收到很多私信是咨询毕业设计怎么做的?有没有好的毕业设计参考?能感觉到现在的毕业生和当时的我有着同样的问题,但是当时的我没有被骗,因为现在很多人是被骗的,还没有出学校还是社会经验少,容易相信别人。…

rust语言tokio库spawn, blocking_spawn等的使用

目录 tokio的spawn以及spawn_blocking的使用tokio::task::spawn方法解析tokio::task::spawn_blocking()方法解析 时间会遗忘一切 最后更新时间2024.04.29 tokio版本: tokio的spawn以及spawn_blocking的使用 tokio::task::spawn方法解析 tokio的实现原理以及源码…

Dynamic-Programming

目录 前言 引入 1) Fibonacci 2) 最短路径 - Bellman-Ford 3) 不同路径-Leetcode 62 4) 0-1 背包问题 降维 5) 完全背包问题 降维 6) 零钱兑换问题-Leetcode322 降维 零钱兑换 II-Leetcode 518 7) 钢条切割问题 降维 类似题目 Leetcode-343 整数拆分 8) 最长…

mybatis - XxxMapper.java接口中方法的参数 和 返回值类型,怎样在 XxxMapper.xml 中配置的问题

这个例子中的mybatis-config.xml文件,引用这个文件即可 实体类src/main/java/com.atguigu.pojo/Employee.java package com.atguigu.pojo;public class Employee {private Integer id;private String name;private String plone;public Integer getId() {return i…

MySQL LIKE通配符(%,_)及escape实例讲解

LIKE操作符常用于模式匹配查询数据。以正确的方式使用LIKE运算符对于提高查询性能至关重要。 LIKE操作符允许您从基于指定的模式选择表中的数据。因此,LIKE操作符经常用于SELECT语句的WHERE子句中。 MySQL提供了两个通配符与LIKE操作符一起使用:百分比…

【Vue3】watch监听使用【超详细】

文章目录 情况一:监听ref定义的基本类型数据情况二:监听ref定义的对象类型数据情况三:监听reactive定义的对象类型数据情况四:监听ref或reactive定义的对象类型数据中某个属性情况五:监听上述多个数据 #watch使用结构 watch(被监视的数据,监视的回调,配置对象(deep,immediate等…

Go 泛型函数中的 ~ 符号 的意义 -- 用于指定类型的底层类型

本文通过 slices.Clone 泛型函数介绍了 Go 是如何使用类型推断完成参数类型的解构。简单来说,如果第一个类型参数是一个复合类型,则可以通过第二、第三或更多的类型参数约束复杂类型中的类型参数,而类型推断则可以通过第一个参数推断出后续类…

【ZZULIOJ】1092: 素数表(函数专题)(Java)

目录 题目描述 输入 输出 样例输入 Copy 样例输出 Copy code 题目描述 输入两个正整数m和n,输出m和n之间的所有素数。 要求程序定义一个prime()函数和一个main()函数,prime()函数判断一个整数n是否是素数,其余功能在main()函数中实现。…