From 5e874e65f8441ca446ee10e4357ab1d87e2b79be Mon Sep 17 00:00:00 2001 From: wantoper <305986045@qq.com> Date: Wed, 28 May 2025 17:42:01 +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=A3=9E=E4=B9=A6=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/feishu.go | 106 +++++++++++++++++++++++++ backend/internal/report/feishu_test.go | 28 +++++++ backend/internal/report/report.go | 4 + 3 files changed, 138 insertions(+) create mode 100644 backend/internal/report/feishu.go create mode 100644 backend/internal/report/feishu_test.go diff --git a/backend/internal/report/feishu.go b/backend/internal/report/feishu.go new file mode 100644 index 0000000..d6addb9 --- /dev/null +++ b/backend/internal/report/feishu.go @@ -0,0 +1,106 @@ +package report + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "io" + "net/http" + "time" +) + +type FeishuReport struct { + webHookUrl string + secret string +} + +func NewFeishuReport(webHookUrl, secret string) *FeishuReport { + return &FeishuReport{webHookUrl: webHookUrl, secret: secret} +} + +func (f *FeishuReport) sign(params *map[string]any) error { + timestamp := time.Now().Unix() + stringToSign := fmt.Sprintf("%v", timestamp) + "\n" + f.secret + var data []byte + h := hmac.New(sha256.New, []byte(stringToSign)) + _, err := h.Write(data) + if err != nil { + return fmt.Errorf("生成签名失败: %v", err) + } + signature := base64.StdEncoding.EncodeToString(h.Sum(nil)) + (*params)["timestamp"] = timestamp + (*params)["sign"] = signature + return nil +} + +func (f *FeishuReport) SendText(msg string) error { + data := map[string]any{ + "timestamp": 0, + "content": map[string]any{ + "text": msg, + }, + "msg_type": "text", + "sign": "", + } + if err := f.sign(&data); err != nil { + return err + } + jsonData, err := json.Marshal(data) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", f.webHookUrl, bytes.NewReader(jsonData)) + if err != nil { + return fmt.Errorf("创建请求失败: %v", err) + } + 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["code"].(float64) != 0 { + return fmt.Errorf("发送失败: %s", res["msg"].(string)) + } + return nil +} + +func NotifyFeishu(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 := NewFeishuReport(config["webhook"], config["secret"]) + err = report.SendText(notifyMsg) + if err != nil { + return fmt.Errorf("飞书发送失败: %w", err) + } + return nil +} diff --git a/backend/internal/report/feishu_test.go b/backend/internal/report/feishu_test.go new file mode 100644 index 0000000..c3f46e6 --- /dev/null +++ b/backend/internal/report/feishu_test.go @@ -0,0 +1,28 @@ +package report + +import ( + "testing" +) + +func TestFeishuSend(test *testing.T) { + report := NewFeishuReport("", "") + err := report.SendText("test msg") + if err != nil { + test.Errorf("FeishuSend failed: %v", err) + } +} + +func TestNotifyFeishu(test *testing.T) { + params := map[string]any{ + "provider_id": "3", + "body": "测试消息通道", + "subject": "测试消息通道", + } + + err := NotifyFeishu(params) + if err != nil { + test.Error("NotifyWebHook failed", "error", err) + } else { + test.Log("NotifyWebHook success") + } +} diff --git a/backend/internal/report/report.go b/backend/internal/report/report.go index a2679c8..1d974a0 100644 --- a/backend/internal/report/report.go +++ b/backend/internal/report/report.go @@ -126,6 +126,8 @@ func NotifyTest(id string) error { err = NotifyMail(params) case "webhook": err = NotifyWebHook(params) + case "feishu": + err = NotifyFeishu(params) } return err } @@ -145,6 +147,8 @@ func Notify(params map[string]any) error { // return NotifyBt(params) case "webhook": return NotifyWebHook(params) + case "feishu": + return NotifyFeishu(params) default: return fmt.Errorf("不支持的通知类型") }