feat: channel Lark is done
This commit is contained in:
@@ -4,8 +4,8 @@
|
|||||||
## TODOs
|
## TODOs
|
||||||
+ [ ] Token Store 测试(内存泄漏检查,不必要的拷贝的检查)
|
+ [ ] Token Store 测试(内存泄漏检查,不必要的拷贝的检查)
|
||||||
+ [ ] 添加 & 更新推送配置信息时对 Token Store 进行妥善更新
|
+ [ ] 添加 & 更新推送配置信息时对 Token Store 进行妥善更新
|
||||||
+ [ ] 微信消息推送 API
|
+ [x] 微信消息推送 API
|
||||||
+ [ ] 支持飞书
|
+ [x] 支持飞书
|
||||||
+ [ ] 支持钉钉
|
+ [ ] 支持钉钉
|
||||||
+ [ ] 支持 Telegram
|
+ [ ] 支持 Telegram
|
||||||
+ [ ] 重新编写 README
|
+ [ ] 重新编写 README
|
||||||
|
|||||||
+110
@@ -1 +1,111 @@
|
|||||||
package channel
|
package channel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"message-pusher/model"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type larkMessageRequestCardElementText struct {
|
||||||
|
Content string `json:"content"`
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type larkMessageRequestCardElement struct {
|
||||||
|
Tag string `json:"tag"`
|
||||||
|
Text larkMessageRequestCardElementText `json:"text"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type larkMessageRequest struct {
|
||||||
|
MessageType string `json:"msg_type"`
|
||||||
|
Timestamp string `json:"timestamp"`
|
||||||
|
Sign string `json:"sign"`
|
||||||
|
Content struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
} `json:"content"`
|
||||||
|
Card struct {
|
||||||
|
Config struct {
|
||||||
|
WideScreenMode bool `json:"wide_screen_mode"`
|
||||||
|
EnableForward bool `json:"enable_forward"`
|
||||||
|
}
|
||||||
|
Elements []larkMessageRequestCardElement `json:"elements"`
|
||||||
|
} `json:"card"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type larkMessageResponse struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Message string `json:"msg"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendLarkMessage(message *Message, user *model.User) error {
|
||||||
|
if user.LarkWebhookURL == "" {
|
||||||
|
return errors.New("未配置飞书群机器人消息推送方式")
|
||||||
|
}
|
||||||
|
messageRequest := larkMessageRequest{
|
||||||
|
MessageType: "text",
|
||||||
|
}
|
||||||
|
if message.Content == "" {
|
||||||
|
messageRequest.MessageType = "text"
|
||||||
|
messageRequest.Content.Text = message.Description
|
||||||
|
} else {
|
||||||
|
messageRequest.MessageType = "interactive"
|
||||||
|
messageRequest.Card.Config.WideScreenMode = true
|
||||||
|
messageRequest.Card.Config.EnableForward = true
|
||||||
|
messageRequest.Card.Elements = append(messageRequest.Card.Elements, larkMessageRequestCardElement{
|
||||||
|
Tag: "div",
|
||||||
|
Text: larkMessageRequestCardElementText{
|
||||||
|
Content: message.Content,
|
||||||
|
Tag: "lark_md",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
timestamp := now.Unix()
|
||||||
|
sign, err := larkSign(user.LarkWebhookSecret, timestamp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
messageRequest.Sign = sign
|
||||||
|
messageRequest.Timestamp = strconv.FormatInt(timestamp, 10)
|
||||||
|
jsonData, err := json.Marshal(messageRequest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
resp, err := http.Post(user.LarkWebhookURL, "application/json",
|
||||||
|
bytes.NewBuffer(jsonData))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var res larkMessageResponse
|
||||||
|
err = json.NewDecoder(resp.Body).Decode(&res)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if res.Code != 0 {
|
||||||
|
return errors.New(res.Message)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func larkSign(secret string, timestamp int64) (string, error) {
|
||||||
|
// https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN
|
||||||
|
// timestamp + key -> sha256 -> base64 encode
|
||||||
|
stringToSign := fmt.Sprintf("%v", timestamp) + "\n" + secret
|
||||||
|
var data []byte
|
||||||
|
h := hmac.New(sha256.New, []byte(stringToSign))
|
||||||
|
_, err := h.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||||
|
return signature, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type Message struct {
|
|||||||
URL string `json:"url"`
|
URL string `json:"url"`
|
||||||
Channel string `json:"channel"`
|
Channel string `json:"channel"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
|
HTMLContent string `json:"html_content"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (message *Message) Send(user *model.User) error {
|
func (message *Message) Send(user *model.User) error {
|
||||||
@@ -32,6 +33,7 @@ func (message *Message) Send(user *model.User) error {
|
|||||||
case TypeWeChatCorpAccount:
|
case TypeWeChatCorpAccount:
|
||||||
return SendWeChatCorpMessage(message, user)
|
return SendWeChatCorpMessage(message, user)
|
||||||
case TypeLark:
|
case TypeLark:
|
||||||
|
return SendLarkMessage(message, user)
|
||||||
case TypeDingTalk:
|
case TypeDingTalk:
|
||||||
case TypeTelegram:
|
case TypeTelegram:
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -85,13 +85,7 @@ func pushMessageHelper(c *gin.Context, message *channel.Message) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
common.SysLog(err.Error())
|
common.SysLog(err.Error())
|
||||||
} else {
|
} else {
|
||||||
message.Content = buf.String()
|
message.HTMLContent = buf.String()
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if message.Description != "" {
|
|
||||||
message.Content = message.Description
|
|
||||||
} else {
|
|
||||||
message.Content = "无内容"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if message.Channel == "" {
|
if message.Channel == "" {
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ type User struct {
|
|||||||
WeChatCorpAccountSecret string `json:"wechat_corp_account_secret" gorm:"column:wechat_corp_account_secret"`
|
WeChatCorpAccountSecret string `json:"wechat_corp_account_secret" gorm:"column:wechat_corp_account_secret"`
|
||||||
WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"`
|
WeChatCorpAccountAgentId string `json:"wechat_corp_account_agent_id" gorm:"column:wechat_corp_account_agent_id"`
|
||||||
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"`
|
||||||
|
LarkWebhookSecret string `json:"lark_webhook_secret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMaxUserId() int {
|
func GetMaxUserId() int {
|
||||||
|
|||||||
Reference in New Issue
Block a user