feat: channel Ding is done
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
package channel
|
|
||||||
@@ -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×tamp=%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
@@ -14,5 +14,5 @@ func SendEmailMessage(message *Message, user *model.User) error {
|
|||||||
if subject == "" {
|
if subject == "" {
|
||||||
subject = message.Title
|
subject = message.Title
|
||||||
}
|
}
|
||||||
return common.SendEmail(subject, user.Email, message.Content)
|
return common.SendEmail(subject, user.Email, message.HTMLContent)
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-4
@@ -10,7 +10,7 @@ const (
|
|||||||
TypeWeChatTestAccount = "test"
|
TypeWeChatTestAccount = "test"
|
||||||
TypeWeChatCorpAccount = "corp"
|
TypeWeChatCorpAccount = "corp"
|
||||||
TypeLark = "lark"
|
TypeLark = "lark"
|
||||||
TypeDingTalk = "ding"
|
TypeDing = "ding"
|
||||||
TypeTelegram = "telegram"
|
TypeTelegram = "telegram"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -34,10 +34,9 @@ func (message *Message) Send(user *model.User) error {
|
|||||||
return SendWeChatCorpMessage(message, user)
|
return SendWeChatCorpMessage(message, user)
|
||||||
case TypeLark:
|
case TypeLark:
|
||||||
return SendLarkMessage(message, user)
|
return SendLarkMessage(message, user)
|
||||||
case TypeDingTalk:
|
case TypeDing:
|
||||||
case TypeTelegram:
|
return SendDingMessage(message, user)
|
||||||
default:
|
default:
|
||||||
return errors.New("不支持的消息通道:" + message.Channel)
|
return errors.New("不支持的消息通道:" + message.Channel)
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ type User struct {
|
|||||||
WeChatCorpAccountUserId string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"`
|
WeChatCorpAccountUserId string `json:"wechat_corp_account_user_id" gorm:"column:wechat_corp_account_user_id"`
|
||||||
LarkWebhookURL string `json:"lark_webhook_url"`
|
LarkWebhookURL string `json:"lark_webhook_url"`
|
||||||
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
||||||
|
DingWebhookURL string `json:"ding_webhook_url"`
|
||||||
|
DingWebhookSecret string `json:"ding_webhook_secret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaxUserId() int {
|
func GetMaxUserId() int {
|
||||||
|
|||||||
Reference in New Issue
Block a user