feat: add to field to specify the receiver (close #48)
This commit is contained in:
@@ -165,6 +165,9 @@ proxy_send_timeout 300s;
|
|||||||
11. `none`:仅保存到数据库,不做推送。
|
11. `none`:仅保存到数据库,不做推送。
|
||||||
5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。
|
5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。
|
||||||
6. `url`:选填,如果不填则系统自动为消息生成 URL,其内容为消息详情。
|
6. `url`:选填,如果不填则系统自动为消息生成 URL,其内容为消息详情。
|
||||||
|
7. `to`:选填,推送给指定用户,如果不填则默认推送给自己,受限于具体的消息推送方式,有些推送方式不支持此项。
|
||||||
|
1. `@all`:推送给所有用户。
|
||||||
|
2. `user1|user2|user3`:推送给多个用户,用户之间使用 `|` 分隔。
|
||||||
3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。
|
3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。
|
||||||
+ 注意:请求体编码格式为 `application/json`,`v0.3.2` 版本起支持 Post Form。
|
+ 注意:请求体编码格式为 `application/json`,`v0.3.2` 版本起支持 Post Form。
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"message-pusher/model"
|
"message-pusher/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type corpMessageRequest struct {
|
type corpMessageRequest struct {
|
||||||
@@ -17,6 +18,7 @@ type corpMessageRequest struct {
|
|||||||
Markdown struct {
|
Markdown struct {
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
} `json:"markdown"`
|
} `json:"markdown"`
|
||||||
|
MentionedList []string `json:"mentioned_list"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type corpMessageResponse struct {
|
type corpMessageResponse struct {
|
||||||
@@ -25,6 +27,7 @@ type corpMessageResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendCorpMessage(message *model.Message, user *model.User) error {
|
func SendCorpMessage(message *model.Message, user *model.User) error {
|
||||||
|
// https://developer.work.weixin.qq.com/document/path/91770
|
||||||
if user.CorpWebhookURL == "" {
|
if user.CorpWebhookURL == "" {
|
||||||
return errors.New("未配置企业微信群机器人消息推送方式")
|
return errors.New("未配置企业微信群机器人消息推送方式")
|
||||||
}
|
}
|
||||||
@@ -38,7 +41,9 @@ func SendCorpMessage(message *model.Message, user *model.User) error {
|
|||||||
messageRequest.MessageType = "markdown"
|
messageRequest.MessageType = "markdown"
|
||||||
messageRequest.Markdown.Content = message.Content
|
messageRequest.Markdown.Content = message.Content
|
||||||
}
|
}
|
||||||
|
if message.To != "" {
|
||||||
|
messageRequest.MentionedList = strings.Split(message.To, "|")
|
||||||
|
}
|
||||||
jsonData, err := json.Marshal(messageRequest)
|
jsonData, err := json.Marshal(messageRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"message-pusher/model"
|
"message-pusher/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,6 +24,10 @@ type dingMessageRequest struct {
|
|||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Text string `json:"text"`
|
Text string `json:"text"`
|
||||||
} `json:"markdown"`
|
} `json:"markdown"`
|
||||||
|
At struct {
|
||||||
|
AtUserIds []string `json:"atUserIds"`
|
||||||
|
IsAtAll bool `json:"isAtAll"`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type dingMessageResponse struct {
|
type dingMessageResponse struct {
|
||||||
@@ -31,6 +36,7 @@ type dingMessageResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendDingMessage(message *model.Message, user *model.User) error {
|
func SendDingMessage(message *model.Message, user *model.User) error {
|
||||||
|
// https://open.dingtalk.com/document/robots/custom-robot-access#title-72m-8ag-pqw
|
||||||
if user.DingWebhookURL == "" {
|
if user.DingWebhookURL == "" {
|
||||||
return errors.New("未配置钉钉群机器人消息推送方式")
|
return errors.New("未配置钉钉群机器人消息推送方式")
|
||||||
}
|
}
|
||||||
@@ -45,6 +51,13 @@ func SendDingMessage(message *model.Message, user *model.User) error {
|
|||||||
messageRequest.Markdown.Title = message.Title
|
messageRequest.Markdown.Title = message.Title
|
||||||
messageRequest.Markdown.Text = message.Content
|
messageRequest.Markdown.Text = message.Content
|
||||||
}
|
}
|
||||||
|
if message.To != "" {
|
||||||
|
if message.To == "@all" {
|
||||||
|
messageRequest.At.IsAtAll = true
|
||||||
|
} else {
|
||||||
|
messageRequest.At.AtUserIds = strings.Split(message.To, "|")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
timestamp := time.Now().UnixMilli()
|
timestamp := time.Now().UnixMilli()
|
||||||
sign, err := dingSign(user.DingWebhookSecret, timestamp)
|
sign, err := dingSign(user.DingWebhookSecret, timestamp)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"message-pusher/model"
|
"message-pusher/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type discordMessageRequest struct {
|
type discordMessageRequest struct {
|
||||||
@@ -27,6 +28,15 @@ func SendDiscordMessage(message *model.Message, user *model.User) error {
|
|||||||
messageRequest := discordMessageRequest{
|
messageRequest := discordMessageRequest{
|
||||||
Content: message.Content,
|
Content: message.Content,
|
||||||
}
|
}
|
||||||
|
// https://discord.com/developers/docs/reference#message-formatting
|
||||||
|
if message.To != "" {
|
||||||
|
messageRequest.Content = ""
|
||||||
|
ids := strings.Split(message.To, "|")
|
||||||
|
for _, id := range ids {
|
||||||
|
messageRequest.Content = "<@" + id + "> " + messageRequest.Content
|
||||||
|
}
|
||||||
|
messageRequest.Content = messageRequest.Content + message.Content
|
||||||
|
}
|
||||||
|
|
||||||
jsonData, err := json.Marshal(messageRequest)
|
jsonData, err := json.Marshal(messageRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -21,5 +21,6 @@ func SendEmailMessage(message *model.Message, user *model.User) error {
|
|||||||
common.SysLog(err.Error())
|
common.SysLog(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: support message.To
|
||||||
return common.SendEmail(subject, user.Email, message.HTMLContent)
|
return common.SendEmail(subject, user.Email, message.HTMLContent)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -11,6 +11,7 @@ import (
|
|||||||
"message-pusher/model"
|
"message-pusher/model"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,15 +47,27 @@ type larkMessageResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendLarkMessage(message *model.Message, user *model.User) error {
|
func SendLarkMessage(message *model.Message, user *model.User) error {
|
||||||
|
// https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN#e1cdee9f
|
||||||
if user.LarkWebhookURL == "" {
|
if user.LarkWebhookURL == "" {
|
||||||
return errors.New("未配置飞书群机器人消息推送方式")
|
return errors.New("未配置飞书群机器人消息推送方式")
|
||||||
}
|
}
|
||||||
messageRequest := larkMessageRequest{
|
messageRequest := larkMessageRequest{
|
||||||
MessageType: "text",
|
MessageType: "text",
|
||||||
}
|
}
|
||||||
|
atPrefix := ""
|
||||||
|
if message.To != "" {
|
||||||
|
if message.To == "@all" {
|
||||||
|
atPrefix = "<at user_id=\"all\">所有人</at>"
|
||||||
|
} else {
|
||||||
|
ids := strings.Split(message.To, "|")
|
||||||
|
for _, id := range ids {
|
||||||
|
atPrefix += fmt.Sprintf("<at user_id=\"%s\"> </at>", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if message.Content == "" {
|
if message.Content == "" {
|
||||||
messageRequest.MessageType = "text"
|
messageRequest.MessageType = "text"
|
||||||
messageRequest.Content.Text = message.Description
|
messageRequest.Content.Text = atPrefix + message.Description
|
||||||
} else {
|
} else {
|
||||||
messageRequest.MessageType = "interactive"
|
messageRequest.MessageType = "interactive"
|
||||||
messageRequest.Card.Config.WideScreenMode = true
|
messageRequest.Card.Config.WideScreenMode = true
|
||||||
@@ -62,7 +75,7 @@ func SendLarkMessage(message *model.Message, user *model.User) error {
|
|||||||
messageRequest.Card.Elements = append(messageRequest.Card.Elements, larkMessageRequestCardElement{
|
messageRequest.Card.Elements = append(messageRequest.Card.Elements, larkMessageRequestCardElement{
|
||||||
Tag: "div",
|
Tag: "div",
|
||||||
Text: larkMessageRequestCardElementText{
|
Text: larkMessageRequestCardElementText{
|
||||||
Content: message.Content,
|
Content: atPrefix + message.Content,
|
||||||
Tag: "lark_md",
|
Tag: "lark_md",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ type telegramMessageResponse struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func SendTelegramMessage(message *model.Message, user *model.User) error {
|
func SendTelegramMessage(message *model.Message, user *model.User) error {
|
||||||
|
// https://core.telegram.org/bots/api#sendmessage
|
||||||
if user.TelegramBotToken == "" || user.TelegramChatId == "" {
|
if user.TelegramBotToken == "" || user.TelegramChatId == "" {
|
||||||
return errors.New("未配置 Telegram 机器人消息推送方式")
|
return errors.New("未配置 Telegram 机器人消息推送方式")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,9 @@ func SendWeChatCorpMessage(message *model.Message, user *model.User) error {
|
|||||||
ToUser: user.WeChatCorpAccountUserId,
|
ToUser: user.WeChatCorpAccountUserId,
|
||||||
AgentId: user.WeChatCorpAccountAgentId,
|
AgentId: user.WeChatCorpAccountAgentId,
|
||||||
}
|
}
|
||||||
|
if message.To != "" {
|
||||||
|
messageRequest.ToUser = message.To
|
||||||
|
}
|
||||||
if message.Content == "" {
|
if message.Content == "" {
|
||||||
if message.Title == "" {
|
if message.Title == "" {
|
||||||
messageRequest.MessageType = "text"
|
messageRequest.MessageType = "text"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ func GetPushMessage(c *gin.Context) {
|
|||||||
URL: c.Query("url"),
|
URL: c.Query("url"),
|
||||||
Channel: c.Query("channel"),
|
Channel: c.Query("channel"),
|
||||||
Token: c.Query("token"),
|
Token: c.Query("token"),
|
||||||
|
To: c.Query("to"),
|
||||||
}
|
}
|
||||||
if message.Description == "" {
|
if message.Description == "" {
|
||||||
// Keep compatible with ServerChan
|
// Keep compatible with ServerChan
|
||||||
@@ -41,6 +42,7 @@ func PostPushMessage(c *gin.Context) {
|
|||||||
Channel: c.PostForm("channel"),
|
Channel: c.PostForm("channel"),
|
||||||
Token: c.PostForm("token"),
|
Token: c.PostForm("token"),
|
||||||
Desp: c.PostForm("desp"),
|
Desp: c.PostForm("desp"),
|
||||||
|
To: c.PostForm("to"),
|
||||||
}
|
}
|
||||||
if message == (model.Message{}) {
|
if message == (model.Message{}) {
|
||||||
// Looks like the user is using JSON
|
// Looks like the user is using JSON
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type Message struct {
|
|||||||
HTMLContent string `json:"html_content" gorm:"-:all"`
|
HTMLContent string `json:"html_content" gorm:"-:all"`
|
||||||
Timestamp int64 `json:"timestamp" gorm:"type:int64"`
|
Timestamp int64 `json:"timestamp" gorm:"type:int64"`
|
||||||
Link string `json:"link" gorm:"unique;index"`
|
Link string `json:"link" gorm:"unique;index"`
|
||||||
|
To string `json:"to" gorm:"column:to"` // if specified, will send to this user(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMessageById(id int, userId int) (*Message, error) {
|
func GetMessageById(id int, userId int) (*Message, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user