Browse Source

feat: channel Ding is done

JustSong 3 years ago
parent
commit
d18eefe6b6
5 changed files with 92 additions and 6 deletions
  1. 0 1
      channel/ding-talk.go
  2. 86 0
      channel/ding.go
  3. 1 1
      channel/email.go
  4. 3 4
      channel/main.go
  5. 2 0
      model/user.go

+ 0 - 1
channel/ding-talk.go

@@ -1 +0,0 @@
-package channel

+ 86 - 0
channel/ding.go

@@ -0,0 +1,86 @@
+package channel
+
+import (
+	"bytes"
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"message-pusher/model"
+	"net/http"
+	"net/url"
+	"time"
+)
+
+type dingMessageRequest struct {
+	MessageType string `json:"msgtype"`
+	Text        struct {
+		Content string `json:"content"`
+	} `json:"text"`
+	Markdown struct {
+		Title string `json:"title"`
+		Text  string `json:"text"`
+	} `json:"markdown"`
+}
+
+type dingMessageResponse struct {
+	Code    int    `json:"errcode"`
+	Message string `json:"errmsg"`
+}
+
+func SendDingMessage(message *Message, user *model.User) error {
+	if user.DingWebhookURL == "" {
+		return errors.New("未配置钉钉群机器人消息推送方式")
+	}
+	messageRequest := dingMessageRequest{
+		MessageType: "text",
+	}
+	if message.Content == "" {
+		messageRequest.MessageType = "text"
+		messageRequest.Text.Content = message.Description
+	} else {
+		messageRequest.MessageType = "markdown"
+		messageRequest.Markdown.Title = message.Title
+		messageRequest.Markdown.Text = message.Content
+	}
+
+	timestamp := time.Now().UnixMilli()
+	sign, err := dingSign(user.DingWebhookSecret, timestamp)
+	if err != nil {
+		return err
+	}
+	jsonData, err := json.Marshal(messageRequest)
+	if err != nil {
+		return err
+	}
+	resp, err := http.Post(fmt.Sprintf("%s&timestamp=%d&sign=%s", user.DingWebhookURL, timestamp, sign), "application/json",
+		bytes.NewBuffer(jsonData))
+	if err != nil {
+		return err
+	}
+	var res dingMessageResponse
+	err = json.NewDecoder(resp.Body).Decode(&res)
+	if err != nil {
+		return err
+	}
+	if res.Code != 0 {
+		return errors.New(res.Message)
+	}
+	return nil
+}
+
+func dingSign(secret string, timestamp int64) (string, error) {
+	// https://open.dingtalk.com/document/robots/customize-robot-security-settings
+	// timestamp + key -> sha256 -> URL encode
+	stringToSign := fmt.Sprintf("%d\n%s", timestamp, secret)
+	h := hmac.New(sha256.New, []byte(secret))
+	_, err := h.Write([]byte(stringToSign))
+	if err != nil {
+		return "", err
+	}
+	signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
+	signature = url.QueryEscape(signature)
+	return signature, nil
+}

+ 1 - 1
channel/email.go

@@ -14,5 +14,5 @@ func SendEmailMessage(message *Message, user *model.User) error {
 	if subject == "" {
 		subject = message.Title
 	}
-	return common.SendEmail(subject, user.Email, message.Content)
+	return common.SendEmail(subject, user.Email, message.HTMLContent)
 }

+ 3 - 4
channel/main.go

@@ -10,7 +10,7 @@ const (
 	TypeWeChatTestAccount = "test"
 	TypeWeChatCorpAccount = "corp"
 	TypeLark              = "lark"
-	TypeDingTalk          = "ding"
+	TypeDing              = "ding"
 	TypeTelegram          = "telegram"
 )
 
@@ -34,10 +34,9 @@ func (message *Message) Send(user *model.User) error {
 		return SendWeChatCorpMessage(message, user)
 	case TypeLark:
 		return SendLarkMessage(message, user)
-	case TypeDingTalk:
-	case TypeTelegram:
+	case TypeDing:
+		return SendDingMessage(message, user)
 	default:
 		return errors.New("不支持的消息通道:" + message.Channel)
 	}
-	return nil
 }

+ 2 - 0
model/user.go

@@ -29,6 +29,8 @@ type User struct {
 	WeChatCorpAccountUserId            string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"`
 	LarkWebhookURL                     string `json:"lark_webhook_url"`
 	LarkWebhookSecret                  string `json:"lark_webhook_secret"`
+	DingWebhookURL                     string `json:"ding_webhook_url"`
+	DingWebhookSecret                  string `json:"ding_webhook_secret"`
 }
 
 func GetMaxUserId() int {