From 82068de1438959b533a207fe68b26392be7cd9e8 Mon Sep 17 00:00:00 2001 From: JustSong Date: Mon, 8 May 2023 22:20:14 +0800 Subject: [PATCH] feat: support custom channel now (close #72, close #75, #71) --- README.md | 4 ++- channel/custom.go | 31 +++++++++++++++++ channel/main.go | 2 ++ model/channel.go | 1 + web/src/constants/channel.constants.js | 6 ++++ web/src/pages/Channel/EditChannel.js | 48 +++++++++++++++++++++++++- 6 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 channel/custom.go diff --git a/README.md b/README.md index 796ec66..5459181 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式, + Telegram 机器人, + Discord 群机器人, + 群组消息,可以将多个推送通道组合成一个群组,然后向群组发送消息,可以实现一次性推送到多个渠道的功能。 + + 自定义消息,可以自定义消息请求 URL 和请求体格式,实现与其他服务的对接,支持[众多第三方服务](https://iamazing.cn/page/message-pusher-common-custom-templates)。 2. 支持在 Web 端管理发送的消息,支持自动刷新。 3. 支持异步消息。 4. 多种用户登录注册方式: @@ -177,7 +178,8 @@ proxy_send_timeout 300s; 11. `discord`:通过 Discord 群机器人进行推送(注意事项同上)。 12. `one_api`:通过 OneAPI 协议推送消息到 QQ。 13. `group`:通过预先配置的消息推送通道群组进行推送。 - 14. `none`:仅保存到数据库,不做推送。 + 14. `custom`:通过预先配置好的自定义推送通道进行推送。 + 15. `none`:仅保存到数据库,不做推送。 5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。 6. `url`:选填,如果不填则系统自动为消息生成 URL,其内容为消息详情。 7. `to`:选填,推送给指定用户,如果不填则默认推送给自己,受限于具体的消息推送方式,有些推送方式不支持此项。 diff --git a/channel/custom.go b/channel/custom.go new file mode 100644 index 0000000..830f96a --- /dev/null +++ b/channel/custom.go @@ -0,0 +1,31 @@ +package channel + +import ( + "bytes" + "errors" + "message-pusher/model" + "net/http" + "strings" +) + +func SendCustomMessage(message *model.Message, user *model.User, channel_ *model.Channel) error { + url := channel_.URL + if strings.HasPrefix(url, "http:") { + return errors.New("自定义通道必须使用 HTTPS 协议") + } + template := channel_.Other + template = strings.Replace(template, "$url", message.URL, -1) + template = strings.Replace(template, "$to", message.To, -1) + template = strings.Replace(template, "$title", message.Title, -1) + template = strings.Replace(template, "$description", message.Description, -1) + template = strings.Replace(template, "$content", message.Content, -1) + reqBody := []byte(template) + resp, err := http.Post(url, "application/json", bytes.NewReader(reqBody)) + if err != nil { + return err + } + if resp.StatusCode != 200 { + return errors.New(resp.Status) + } + return nil +} diff --git a/channel/main.go b/channel/main.go index c9d9b1c..ca65415 100644 --- a/channel/main.go +++ b/channel/main.go @@ -35,6 +35,8 @@ func SendMessage(message *model.Message, user *model.User, channel_ *model.Chann return SendGroupMessage(message, user, channel_) case model.TypeLarkApp: return SendLarkAppMessage(message, user, channel_) + case model.TypeCustom: + return SendCustomMessage(message, user, channel_) default: return errors.New("不支持的消息通道:" + channel_.Type) } diff --git a/model/channel.go b/model/channel.go index c22043d..f0e6fd5 100644 --- a/model/channel.go +++ b/model/channel.go @@ -20,6 +20,7 @@ const ( TypeOneBot = "one_bot" TypeGroup = "group" TypeLarkApp = "lark_app" + TypeCustom = "custom" ) type Channel struct { diff --git a/web/src/constants/channel.constants.js b/web/src/constants/channel.constants.js index eed43d2..316a776 100644 --- a/web/src/constants/channel.constants.js +++ b/web/src/constants/channel.constants.js @@ -41,6 +41,12 @@ export const CHANNEL_OPTIONS = [ value: 'one_bot', color: '#76FF03', }, + { + key: 'custom', + text: '自定义消息通道', + value: 'custom', + color: '#cc33ff', + }, { key: 'group', text: '群组消息', diff --git a/web/src/pages/Channel/EditChannel.js b/web/src/pages/Channel/EditChannel.js index 79ddb1b..852cd2f 100644 --- a/web/src/pages/Channel/EditChannel.js +++ b/web/src/pages/Channel/EditChannel.js @@ -83,6 +83,19 @@ const EditChannel = () => { ); return; } + break; + case 'custom': + if (!localInputs.url.startsWith('https://')) { + showError('自定义通道的 URL 必须以 https:// 开头!'); + return; + } + try { + JSON.parse(localInputs.other); + }catch (e) { + showError('JSON 格式错误:' + e.message); + return; + } + break; } if (isEditing) { res = await API.put(`/api/channel/`, { @@ -601,7 +614,40 @@ const EditChannel = () => { ); - + case 'custom': + return ( + <> + + 自定义推送,目前仅支持 POST 请求,请求体为 JSON 格式。 +
+ 支持以下模板变量:$title$description$content$url$to。 +
+ 这个页面给出了常见的第三方平台的配置实例,你可以参考这些示例进行配置。 +
+ 注意,为了防止攻击者利用本功能访问内部网络,也为了你的信息安全,请求地址必须使用 HTTPS 协议。 +
+ + + + + + + + ); case 'none': return ( <>