diff --git a/README.md b/README.md
index 4fb1643..f91d998 100644
--- a/README.md
+++ b/README.md
@@ -57,6 +57,7 @@ _✨ 搭建专属于你的消息推送服务,支持多种消息推送方式,
+ WebSocket 客户端([官方客户端](https://github.com/songquanpeng/personal-assistant),[接入文档](./docs/API.md#websocket-客户端)),
+ Telegram 机器人,
+ Discord 群机器人,
+ + 群组消息,可以将多个推送通道组合成一个群组,然后向群组发送消息,可以实现一次性推送到多个渠道的功能。
2. 多种用户登录注册方式:
+ 邮箱登录注册以及通过邮箱进行密码重置。
+ [GitHub 开放授权](https://github.com/settings/applications/new)。
@@ -172,7 +173,8 @@ proxy_send_timeout 300s;
9. `telegram`:通过 Telegram 机器人进行推送(`description` 或 `content` 字段二选一,支持 Markdown 的子集)。
10. `discord`:通过 Discord 群机器人进行推送(注意事项同上)。
11. `one_api`:通过 OneAPI 协议推送消息到 QQ。
- 12. `none`:仅保存到数据库,不做推送。
+ 12. `group`:通过预先配置的消息推送通道群组进行推送。
+ 13. `none`:仅保存到数据库,不做推送。
5. `token`:如果你在后台设置了推送 token,则此项必填。另外可以通过设置 HTTP `Authorization` 头部设置此项。
6. `url`:选填,如果不填则系统自动为消息生成 URL,其内容为消息详情。
7. `to`:选填,推送给指定用户,如果不填则默认推送给自己,受限于具体的消息推送方式,有些推送方式不支持此项。
diff --git a/channel/group.go b/channel/group.go
new file mode 100644
index 0000000..5cb1fff
--- /dev/null
+++ b/channel/group.go
@@ -0,0 +1,31 @@
+package channel
+
+import (
+ "errors"
+ "message-pusher/model"
+ "strings"
+)
+
+func SendGroupMessage(message *model.Message, user *model.User, channel_ *model.Channel) error {
+ subChannels := strings.Split(channel_.AppId, "|")
+ subTargets := strings.Split(channel_.AccountId, "|")
+ if len(subChannels) != len(subTargets) {
+ return errors.New("无效的群组消息配置,子通道数量与子目标数量不一致")
+ }
+ for i := 0; i < len(subChannels); i++ {
+ message.To = subTargets[i]
+ message.Channel = subChannels[i]
+ subChannel, err := model.GetChannelByName(subChannels[i], user.Id)
+ if err != nil {
+ return errors.New("获取群组消息子通道失败:" + err.Error())
+ }
+ if subChannel.Type == model.TypeGroup {
+ return errors.New("群组消息子通道不能是群组消息")
+ }
+ err = SendMessage(message, user, subChannel)
+ if err != nil {
+ return errors.New("发送群组消息失败:" + err.Error())
+ }
+ }
+ return nil
+}
diff --git a/channel/main.go b/channel/main.go
index f155e79..afa409d 100644
--- a/channel/main.go
+++ b/channel/main.go
@@ -31,6 +31,8 @@ func SendMessage(message *model.Message, user *model.User, channel_ *model.Chann
return nil
case model.TypeOneBot:
return SendOneBotMessage(message, user, channel_)
+ case model.TypeGroup:
+ return SendGroupMessage(message, user, channel_)
default:
return errors.New("不支持的消息通道:" + channel_.Type)
}
diff --git a/model/channel.go b/model/channel.go
index 47a6ea1..185c9e6 100644
--- a/model/channel.go
+++ b/model/channel.go
@@ -18,6 +18,7 @@ const (
TypeClient = "client"
TypeNone = "none"
TypeOneBot = "one_bot"
+ TypeGroup = "group"
)
type Channel struct {
diff --git a/web/src/constants/channel.constants.js b/web/src/constants/channel.constants.js
index e5c25ee..fa62df1 100644
--- a/web/src/constants/channel.constants.js
+++ b/web/src/constants/channel.constants.js
@@ -33,7 +33,13 @@ export const CHANNEL_OPTIONS = [
key: 'one_bot',
text: 'OneBot 协议',
value: 'one_bot',
- color: '#616cff',
+ color: '#76FF03',
+ },
+ {
+ key: 'group',
+ text: '群组消息',
+ value: 'group',
+ color: '#FF9800',
},
{
key: 'none',
diff --git a/web/src/pages/Channel/EditChannel.js b/web/src/pages/Channel/EditChannel.js
index 219aa48..da1ea3a 100644
--- a/web/src/pages/Channel/EditChannel.js
+++ b/web/src/pages/Channel/EditChannel.js
@@ -20,7 +20,7 @@ const EditChannel = () => {
url: '',
other: '',
corp_id: '', // only for corp_app
- agent_id: '', // only for corp_app
+ agent_id: '' // only for corp_app
};
const [inputs, setInputs] = useState(originInputs);
@@ -70,11 +70,22 @@ const EditChannel = () => {
localInputs.url = localInputs.url.slice(0, -1);
}
break;
+ case 'group':
+ let channels = localInputs.app_id.split('|');
+ let targets = localInputs.account_id.split('|');
+ if (localInputs.account_id === '') {
+ for (let i = 0; i < channels.length - 1; i++) {
+ localInputs.account_id += '|';
+ }
+ } else if (channels.length !== targets.length) {
+ showError('群组通道的子通道数量与目标数量不匹配,对于不需要指定的目标请直接留空');
+ return;
+ }
}
if (isEditing) {
res = await API.put(`/api/channel/`, {
...localInputs,
- id: parseInt(channelId),
+ id: parseInt(channelId)
});
} else {
res = await API.post(`/api/channel`, localInputs);
@@ -247,9 +258,9 @@ const EditChannel = () => {
{
key: 'plugin',
text: '微信中的企业微信插件',
- value: 'plugin',
+ value: 'plugin'
},
- { key: 'app', text: '企业微信 APP', value: 'app' },
+ { key: 'app', text: '企业微信 APP', value: 'app' }
]}
value={inputs.other}
onChange={handleInputChange}
@@ -465,10 +476,11 @@ const EditChannel = () => {
return (
<>
123456789||@wechat,两个连续的分隔符表示跳过该渠道。
+