feat: add feishu and aliyunsms
This commit is contained in:
@@ -47,6 +47,25 @@ var HostedMsgCleanDefaultValueMap = map[string]string{
|
||||
|
||||
const AboutSectionName = "about"
|
||||
|
||||
// 消息格式类型常量
|
||||
const (
|
||||
FormatTypeText = "text"
|
||||
FormatTypeHTML = "html"
|
||||
FormatTypeMarkdown = "markdown"
|
||||
)
|
||||
|
||||
// 消息类型常量
|
||||
const (
|
||||
MessageTypeEmail = "Email"
|
||||
MessageTypeDtalk = "Dtalk"
|
||||
MessageTypeQyWeiXin = "QyWeiXin"
|
||||
MessageTypeFeishu = "Feishu"
|
||||
MessageTypeCustom = "Custom"
|
||||
MessageTypeWeChatOFAccount = "WeChatOFAccount"
|
||||
MessageTypeMessageNest = "MessageNest"
|
||||
MessageTypeAliyunSMS = "AliyunSMS"
|
||||
)
|
||||
|
||||
// 限制goroutine的最大数量
|
||||
var MaxSendTaskSemaphoreChan = make(chan string, 2048)
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
package message
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type feishuResponse struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
type Feishu struct {
|
||||
AccessToken string
|
||||
Secret string
|
||||
}
|
||||
|
||||
// genSign 生成飞书签名
|
||||
func (f *Feishu) genSign(timestamp int64) string {
|
||||
if f.Secret == "" {
|
||||
return ""
|
||||
}
|
||||
stringToSign := fmt.Sprintf("%v\n%s", timestamp, f.Secret)
|
||||
h := hmac.New(sha256.New, []byte(stringToSign))
|
||||
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
return signature
|
||||
}
|
||||
|
||||
// SendMessageText 发送文本消息
|
||||
func (f *Feishu) SendMessageText(content string, atMobiles ...string) ([]byte, error) {
|
||||
timestamp := time.Now().Unix()
|
||||
sign := f.genSign(timestamp)
|
||||
|
||||
msg := map[string]interface{}{
|
||||
"timestamp": strconv.FormatInt(timestamp, 10),
|
||||
"sign": sign,
|
||||
"msg_type": "text",
|
||||
"content": map[string]interface{}{
|
||||
"text": content,
|
||||
},
|
||||
}
|
||||
|
||||
return f.send(msg)
|
||||
}
|
||||
|
||||
// SendMessageMarkdown 发送 Markdown 消息
|
||||
func (f *Feishu) SendMessageMarkdown(title, content string, atMobiles ...string) ([]byte, error) {
|
||||
timestamp := time.Now().Unix()
|
||||
sign := f.genSign(timestamp)
|
||||
|
||||
// 处理 @ 人员
|
||||
atContent := ""
|
||||
if len(atMobiles) > 0 {
|
||||
for _, mobile := range atMobiles {
|
||||
if mobile == "all" {
|
||||
atContent += "<at user_id=\"all\">所有人</at>"
|
||||
} else {
|
||||
atContent += fmt.Sprintf("<at user_id=\"%s\"></at>", mobile)
|
||||
}
|
||||
}
|
||||
content = atContent + "\n" + content
|
||||
}
|
||||
|
||||
msg := map[string]interface{}{
|
||||
"timestamp": strconv.FormatInt(timestamp, 10),
|
||||
"sign": sign,
|
||||
"msg_type": "interactive",
|
||||
"card": map[string]interface{}{
|
||||
"header": map[string]interface{}{
|
||||
"title": map[string]interface{}{
|
||||
"tag": "plain_text",
|
||||
"content": title,
|
||||
},
|
||||
},
|
||||
"elements": []map[string]interface{}{
|
||||
{
|
||||
"tag": "markdown",
|
||||
"content": content,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return f.send(msg)
|
||||
}
|
||||
|
||||
// send 发送请求
|
||||
func (f *Feishu) send(msg map[string]interface{}) ([]byte, error) {
|
||||
url := fmt.Sprintf("https://open.feishu.cn/open-apis/bot/v2/hook/%s", f.AccessToken)
|
||||
|
||||
jsonData, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("JSON序列化失败: %v", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("创建请求失败: %v", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := &http.Client{Timeout: 10 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("发送请求失败: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("读取响应失败: %v", err)
|
||||
}
|
||||
|
||||
var result feishuResponse
|
||||
if err := json.Unmarshal(body, &result); err != nil {
|
||||
return body, fmt.Errorf("解析响应失败: %v", err)
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
return body, fmt.Errorf("飞书返回错误: %s", result.Msg)
|
||||
}
|
||||
|
||||
return body, nil
|
||||
}
|
||||
Reference in New Issue
Block a user