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
}
相关推荐
Tony Bai4 小时前
Go 安全新提案:runtime/secret 能否终结密钥残留的噩梦?
java·开发语言·jvm·安全·golang
haing20198 小时前
人形机器人WBC控制方法介绍
机器人·wbc控制
卿雪11 小时前
Redis 线程模型:Redis为什么这么快?Redis为什么引入多线程?
java·数据库·redis·sql·mysql·缓存·golang
RPA机器人就用八爪鱼14 小时前
RPA赋能产品日报自动化:企业决策效率提升新引擎
机器人·rpa
源代码•宸14 小时前
分布式缓存-GO(项目整体架构简介、Ubuntu 22.04 64位安装GoLang、安装Docker、解决Go module 的依赖问题)
经验分享·分布式·后端·ubuntu·缓存·docker·golang
MC皮蛋侠客14 小时前
Linux安装go及环境配置教程
linux·运维·golang
RPA机器人就用八爪鱼14 小时前
RPA采集爬虫:数据采集自动化的高效解决方案
机器人·rpa
golang学习记14 小时前
Redis Pipeline 实战指南:提升 Go 后端性能的利器
redis·golang·php
林伟_fpga15 小时前
室联人形机器人居家服务:提高安全性、任务场景降维、工作流程
人工智能·机器人
拿博客当笔记本15 小时前
[ROS2实战] 从零打造SLAM机器人(一):基于ESP32与Micro-ROS的底盘运动控制与里程计实现
机器人