diff --git a/README.md b/README.md index 444d3f3..2816d85 100644 --- a/README.md +++ b/README.md @@ -165,6 +165,9 @@ proxy_send_timeout 300s; 11. `none`:仅保存到数据库,不做推送。 5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。 6. `url`:选填,如果不填则系统自动为消息生成 URL,其内容为消息详情。 + 7. `to`:选填,推送给指定用户,如果不填则默认推送给自己,受限于具体的消息推送方式,有些推送方式不支持此项。 + 1. `@all`:推送给所有用户。 + 2. `user1|user2|user3`:推送给多个用户,用户之间使用 `|` 分隔。 3. `POST` 请求方式:字段与上面 `GET` 请求方式保持一致。 + 注意:请求体编码格式为 `application/json`,`v0.3.2` 版本起支持 Post Form。 diff --git a/channel/corp.go b/channel/corp.go index 58f298a..9329a07 100644 --- a/channel/corp.go +++ b/channel/corp.go @@ -7,6 +7,7 @@ import ( "fmt" "message-pusher/model" "net/http" + "strings" ) type corpMessageRequest struct { @@ -17,6 +18,7 @@ type corpMessageRequest struct { Markdown struct { Content string `json:"content"` } `json:"markdown"` + MentionedList []string `json:"mentioned_list"` } type corpMessageResponse struct { @@ -25,6 +27,7 @@ type corpMessageResponse struct { } func SendCorpMessage(message *model.Message, user *model.User) error { + // https://developer.work.weixin.qq.com/document/path/91770 if user.CorpWebhookURL == "" { return errors.New("未配置企业微信群机器人消息推送方式") } @@ -38,7 +41,9 @@ func SendCorpMessage(message *model.Message, user *model.User) error { messageRequest.MessageType = "markdown" messageRequest.Markdown.Content = message.Content } - + if message.To != "" { + messageRequest.MentionedList = strings.Split(message.To, "|") + } jsonData, err := json.Marshal(messageRequest) if err != nil { return err diff --git a/channel/ding.go b/channel/ding.go index 7436030..3b7df8d 100644 --- a/channel/ding.go +++ b/channel/ding.go @@ -11,6 +11,7 @@ import ( "message-pusher/model" "net/http" "net/url" + "strings" "time" ) @@ -23,6 +24,10 @@ type dingMessageRequest struct { Title string `json:"title"` Text string `json:"text"` } `json:"markdown"` + At struct { + AtUserIds []string `json:"atUserIds"` + IsAtAll bool `json:"isAtAll"` + } } type dingMessageResponse struct { @@ -31,6 +36,7 @@ type dingMessageResponse struct { } 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 == "" { return errors.New("未配置钉钉群机器人消息推送方式") } @@ -45,6 +51,13 @@ func SendDingMessage(message *model.Message, user *model.User) error { messageRequest.Markdown.Title = message.Title 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() sign, err := dingSign(user.DingWebhookSecret, timestamp) diff --git a/channel/discord.go b/channel/discord.go index 6aecafa..60ad019 100644 --- a/channel/discord.go +++ b/channel/discord.go @@ -6,6 +6,7 @@ import ( "errors" "message-pusher/model" "net/http" + "strings" ) type discordMessageRequest struct { @@ -27,6 +28,15 @@ func SendDiscordMessage(message *model.Message, user *model.User) error { messageRequest := discordMessageRequest{ 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) if err != nil { diff --git a/channel/email.go b/channel/email.go index 4e143ca..13f2909 100644 --- a/channel/email.go +++ b/channel/email.go @@ -21,5 +21,6 @@ func SendEmailMessage(message *model.Message, user *model.User) error { common.SysLog(err.Error()) } } + // TODO: support message.To return common.SendEmail(subject, user.Email, message.HTMLContent) } diff --git a/channel/lark.go b/channel/lark.go index b582463..14b1187 100644 --- a/channel/lark.go +++ b/channel/lark.go @@ -11,6 +11,7 @@ import ( "message-pusher/model" "net/http" "strconv" + "strings" "time" ) @@ -46,15 +47,27 @@ type larkMessageResponse struct { } func SendLarkMessage(message *model.Message, user *model.User) error { + // https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN#e1cdee9f if user.LarkWebhookURL == "" { return errors.New("未配置飞书群机器人消息推送方式") } messageRequest := larkMessageRequest{ MessageType: "text", } + atPrefix := "" + if message.To != "" { + if message.To == "@all" { + atPrefix = "所有人" + } else { + ids := strings.Split(message.To, "|") + for _, id := range ids { + atPrefix += fmt.Sprintf(" ", id) + } + } + } if message.Content == "" { messageRequest.MessageType = "text" - messageRequest.Content.Text = message.Description + messageRequest.Content.Text = atPrefix + message.Description } else { messageRequest.MessageType = "interactive" 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{ Tag: "div", Text: larkMessageRequestCardElementText{ - Content: message.Content, + Content: atPrefix + message.Content, Tag: "lark_md", }, }) diff --git a/channel/telegram.go b/channel/telegram.go index c1bf533..c5776ad 100644 --- a/channel/telegram.go +++ b/channel/telegram.go @@ -21,6 +21,7 @@ type telegramMessageResponse struct { } func SendTelegramMessage(message *model.Message, user *model.User) error { + // https://core.telegram.org/bots/api#sendmessage if user.TelegramBotToken == "" || user.TelegramChatId == "" { return errors.New("未配置 Telegram 机器人消息推送方式") } diff --git a/channel/wechat-corp-account.go b/channel/wechat-corp-account.go index 56dfad0..0bffa21 100644 --- a/channel/wechat-corp-account.go +++ b/channel/wechat-corp-account.go @@ -104,6 +104,9 @@ func SendWeChatCorpMessage(message *model.Message, user *model.User) error { ToUser: user.WeChatCorpAccountUserId, AgentId: user.WeChatCorpAccountAgentId, } + if message.To != "" { + messageRequest.ToUser = message.To + } if message.Content == "" { if message.Title == "" { messageRequest.MessageType = "text" diff --git a/controller/message.go b/controller/message.go index 94e0aff..3206cda 100644 --- a/controller/message.go +++ b/controller/message.go @@ -20,6 +20,7 @@ func GetPushMessage(c *gin.Context) { URL: c.Query("url"), Channel: c.Query("channel"), Token: c.Query("token"), + To: c.Query("to"), } if message.Description == "" { // Keep compatible with ServerChan @@ -41,6 +42,7 @@ func PostPushMessage(c *gin.Context) { Channel: c.PostForm("channel"), Token: c.PostForm("token"), Desp: c.PostForm("desp"), + To: c.PostForm("to"), } if message == (model.Message{}) { // Looks like the user is using JSON diff --git a/model/message.go b/model/message.go index 014cb5a..1917d8f 100644 --- a/model/message.go +++ b/model/message.go @@ -19,6 +19,7 @@ type Message struct { HTMLContent string `json:"html_content" gorm:"-:all"` Timestamp int64 `json:"timestamp" gorm:"type:int64"` 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) {