From c7e8dee436ffe65035a724267e7a86160c9cc8b0 Mon Sep 17 00:00:00 2001 From: wantoper <305986045@qq.com> Date: Thu, 29 May 2025 10:27:09 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=E3=80=90?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E3=80=91=E9=92=89=E9=92=89=E7=BE=A4=E6=9C=BA?= =?UTF-8?q?=E5=99=A8=E4=BA=BA=E9=80=9A=E7=9F=A5=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/report/dingtalk.go | 105 +++++++++++++++++++++++ backend/internal/report/dingtalk_test.go | 28 ++++++ backend/internal/report/report.go | 4 + 3 files changed, 137 insertions(+) create mode 100644 backend/internal/report/dingtalk.go create mode 100644 backend/internal/report/dingtalk_test.go diff --git a/backend/internal/report/dingtalk.go b/backend/internal/report/dingtalk.go new file mode 100644 index 0000000..d4b4dbb --- /dev/null +++ b/backend/internal/report/dingtalk.go @@ -0,0 +1,105 @@ +package report + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "time" +) + +type DingtalkReport struct { + webHookUrl string + secret string +} + +func NewDingtalkReport(webHookUrl, secret string) *DingtalkReport { + return &DingtalkReport{webHookUrl: webHookUrl, secret: secret} +} + +func (d *DingtalkReport) sign() (string, error) { + timestamp := time.Now().UnixNano() / 1000000 + stringToSign := fmt.Sprintf("%d\n%s", timestamp, d.secret) + hash := hmac.New(sha256.New, []byte(d.secret)) + hash.Write([]byte(stringToSign)) + sum := hash.Sum(nil) + signature := base64.StdEncoding.EncodeToString(sum) + + webhookurl, _ := url.Parse(d.webHookUrl) + query := webhookurl.Query() + query.Set("timestamp", fmt.Sprint(timestamp)) + query.Set("sign", signature) + webhookurl.RawQuery = query.Encode() + + return webhookurl.String(), nil +} + +func (d *DingtalkReport) SendText(msg string) error { + data := map[string]any{ + "text": map[string]any{ + "content": msg, + }, + "msgtype": "text", + } + jsonData, err := json.Marshal(data) + if err != nil { + return err + } + + signUrl, err := d.sign() + if err != nil { + return err + } + req, _ := http.NewRequest("POST", signUrl, bytes.NewReader(jsonData)) + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return fmt.Errorf("请求钉钉失败: %v", err) + } + body, _ := io.ReadAll(resp.Body) + defer resp.Body.Close() + var res map[string]interface{} + err = json.Unmarshal(body, &res) + if err != nil { + return fmt.Errorf("返回值解析失败: %v", err) + } + + if res["errcode"].(float64) != 0 { + return fmt.Errorf("发送失败: %s", res["errmsg"].(string)) + } + return nil + +} + +func NotifyDingtalk(params map[string]any) error { + if params == nil { + return fmt.Errorf("缺少参数") + } + providerID := params["provider_id"].(string) + + providerData, err := GetReport(providerID) + if err != nil { + return err + } + configStr := providerData["config"].(string) + var config map[string]string + err = json.Unmarshal([]byte(configStr), &config) + if err != nil { + return fmt.Errorf("解析配置失败: %v", err) + } + notifyMsg := fmt.Sprintf("%s : %s", params["subject"].(string), params["body"].(string)) + + report := NewDingtalkReport(config["webhook"], config["secret"]) + err = report.SendText(notifyMsg) + if err != nil { + return fmt.Errorf("Dingtalk发送失败: %w", err) + } + return nil +} diff --git a/backend/internal/report/dingtalk_test.go b/backend/internal/report/dingtalk_test.go new file mode 100644 index 0000000..120ebcd --- /dev/null +++ b/backend/internal/report/dingtalk_test.go @@ -0,0 +1,28 @@ +package report + +import ( + "testing" +) + +func TestDingdingSend(test *testing.T) { + report := NewDingtalkReport("", "") + err := report.SendText("test msg") + if err != nil { + test.Errorf("Dingding failed: %v", err) + } +} + +func TestNotifyDingding(test *testing.T) { + params := map[string]any{ + "provider_id": "4", + "body": "测试消息通道", + "subject": "测试消息通道", + } + + err := NotifyDingtalk(params) + if err != nil { + test.Error("NotifyDingtalk failed", "error", err) + } else { + test.Log("NotifyDingtalk success") + } +} diff --git a/backend/internal/report/report.go b/backend/internal/report/report.go index 1d974a0..f2fcbdc 100644 --- a/backend/internal/report/report.go +++ b/backend/internal/report/report.go @@ -128,6 +128,8 @@ func NotifyTest(id string) error { err = NotifyWebHook(params) case "feishu": err = NotifyFeishu(params) + case "dingtalk": + err = NotifyDingtalk(params) } return err } @@ -149,6 +151,8 @@ func Notify(params map[string]any) error { return NotifyWebHook(params) case "feishu": return NotifyFeishu(params) + case "dingtalk": + return NotifyDingtalk(params) default: return fmt.Errorf("不支持的通知类型") }