diff --git a/channel/main.go b/channel/main.go index 3b79730..f155e79 100644 --- a/channel/main.go +++ b/channel/main.go @@ -29,6 +29,8 @@ func SendMessage(message *model.Message, user *model.User, channel_ *model.Chann return SendDiscordMessage(message, user, channel_) case model.TypeNone: return nil + case model.TypeOneBot: + return SendOneBotMessage(message, user, channel_) default: return errors.New("不支持的消息通道:" + channel_.Type) } diff --git a/channel/one-bot.go b/channel/one-bot.go new file mode 100644 index 0000000..1af0709 --- /dev/null +++ b/channel/one-bot.go @@ -0,0 +1,85 @@ +package channel + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "message-pusher/model" + "net/http" + "strconv" + "strings" +) + +type oneBotMessageRequest struct { + MessageType string `json:"message_type"` + UserId int64 `json:"user_id"` + GroupId int64 `json:"group_id"` + Message string `json:"message"` + AutoEscape bool `json:"auto_escape"` +} + +type oneBotMessageResponse struct { + Message string `json:"message"` + Status string `json:"status"` + RetCode int `json:"retcode"` +} + +func SendOneBotMessage(message *model.Message, user *model.User, channel_ *model.Channel) error { + url := fmt.Sprintf("%s/send_msg", channel_.URL) + req := oneBotMessageRequest{ + Message: message.Content, + } + if message.Content == "" { + req.Message = message.Description + } + target := channel_.AccountId + if message.To != "" { + target = message.To + } + parts := strings.Split(target, "_") + var idStr string + var type_ string + if len(parts) == 1 { + type_ = "user" + idStr = parts[0] + } else if len(parts) == 2 { + type_ = parts[0] + idStr = parts[1] + } else { + return errors.New("无效的 OneBot 配置") + } + id, _ := strconv.ParseInt(idStr, 10, 64) + if type_ == "user" { + req.UserId = id + req.MessageType = "private" + } else if type_ == "group" { + req.GroupId = id + req.MessageType = "group" + } else { + return errors.New("无效的 OneBot 配置") + } + reqBody, err := json.Marshal(req) + if err != nil { + return err + } + request, _ := http.NewRequest("POST", url, bytes.NewReader(reqBody)) + request.Header.Set("Authorization", "Bearer "+channel_.Secret) + request.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(request) + if err != nil { + return err + } + if resp.StatusCode != 200 { + return errors.New(resp.Status) + } + var res oneBotMessageResponse + err = json.NewDecoder(resp.Body).Decode(&res) + if err != nil { + return err + } + if res.RetCode != 0 { + return errors.New(res.Message) + } + return nil +} diff --git a/model/channel.go b/model/channel.go index ed9e863..77d2cbe 100644 --- a/model/channel.go +++ b/model/channel.go @@ -16,6 +16,7 @@ const ( TypeBark = "bark" TypeClient = "client" TypeNone = "none" + TypeOneBot = "one_bot" ) type Channel struct { diff --git a/web/src/constants/channel.constants.js b/web/src/constants/channel.constants.js index f2f4449..e5c25ee 100644 --- a/web/src/constants/channel.constants.js +++ b/web/src/constants/channel.constants.js @@ -29,6 +29,12 @@ export const CHANNEL_OPTIONS = [ value: 'discord', color: '#404eed', }, + { + key: 'one_bot', + text: 'OneBot 协议', + value: 'one_bot', + color: '#616cff', + }, { key: 'none', text: '不推送', diff --git a/web/src/pages/Channel/EditChannel.js b/web/src/pages/Channel/EditChannel.js index 1c1dc12..219aa48 100644 --- a/web/src/pages/Channel/EditChannel.js +++ b/web/src/pages/Channel/EditChannel.js @@ -61,7 +61,15 @@ const EditChannel = () => { localInputs.app_id = `${inputs.corp_id}|${inputs.agent_id}`; break; case 'bark': - localInputs.url = 'https://api.day.app'; + if (localInputs.url === '') { + localInputs.url = 'https://api.day.app'; + } + break; + case 'one_bot': + if (localInputs.url.endsWith('/')) { + localInputs.url = localInputs.url.slice(0, -1); + } + break; } if (isEditing) { res = await API.put(`/api/channel/`, { @@ -453,6 +461,42 @@ const EditChannel = () => { ); + case 'one_bot': + return ( + <> + + 通过 OneBot 协议进行推送,可以使用 cqhttp 等实现。 + 利用 OneBot 协议可以实现推送 QQ 消息。 + + + + + + + + ); case 'none': return ( <>