1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-05-04 19:17:37 +08:00

forward message sending supported.

This commit is contained in:
Mrs4s 2020-07-29 21:45:43 +08:00
parent b73aeb6666
commit 57153d2d4a
6 changed files with 203 additions and 5 deletions

View File

@ -18,7 +18,7 @@
- [x] 修改群名 - [x] 修改群名
- [x] 消息撤回事件 - [x] 消息撤回事件
- [x] 解析/发送 回复消息 - [x] 解析/发送 回复消息
- [x] 解析合并转发 - [x] 解析/发送 合并转发
- [ ] 使用代理请求网络图片 - [ ] 使用代理请求网络图片
#### 实现 #### 实现

View File

@ -12,6 +12,7 @@ import (
"path" "path"
"runtime" "runtime"
"strconv" "strconv"
"time"
) )
// https://cqhttp.cc/docs/4.15/#/API?id=get_login_info-%E8%8E%B7%E5%8F%96%E7%99%BB%E5%BD%95%E5%8F%B7%E4%BF%A1%E6%81%AF // https://cqhttp.cc/docs/4.15/#/API?id=get_login_info-%E8%8E%B7%E5%8F%96%E7%99%BB%E5%BD%95%E5%8F%B7%E4%BF%A1%E6%81%AF
@ -119,6 +120,76 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, m gjson.Result) MSG {
return Failed(100) return Failed(100)
} }
func (bot *CQBot) CQSendGroupForwardMessage(groupId int64, m gjson.Result) MSG {
if m.Type != gjson.JSON {
return Failed(100)
}
var nodes []*message.ForwardNode
ts := time.Now().Add(-time.Minute * 5)
hasCustom := func() bool {
for _, item := range m.Array() {
if item.Get("data.uin").Exists() {
return true
}
}
return false
}()
convert := func(e gjson.Result) {
if e.Get("type").Str != "node" {
return
}
ts.Add(time.Second)
if e.Get("data.id").Exists() {
i, _ := strconv.Atoi(e.Get("data.id").Str)
m := bot.GetGroupMessage(int32(i))
if m != nil {
sender := m["sender"].(message.Sender)
nodes = append(nodes, &message.ForwardNode{
SenderId: sender.Uin,
SenderName: (&sender).DisplayName(),
Time: func() int32 {
if hasCustom {
return int32(ts.Unix())
}
return m["time"].(int32)
}(),
Message: bot.ConvertStringMessage(m["message"].(string), true),
})
return
}
log.Warnf("警告: 引用消息 %v 错误或数据库未开启.", e.Get("data.id").Str)
return
}
uin, _ := strconv.ParseInt(e.Get("data.uin").Str, 10, 64)
name := e.Get("data.name").Str
content := bot.ConvertObjectMessage(e.Get("data.content"), true)
if uin != 0 && name != "" && len(content) > 0 {
nodes = append(nodes, &message.ForwardNode{
SenderId: uin,
SenderName: name,
Time: int32(ts.Unix()),
Message: content,
})
return
}
log.Warnf("警告: 非法 Forward node 将跳过")
}
if m.IsArray() {
for _, item := range m.Array() {
convert(item)
}
} else {
convert(m)
}
if len(nodes) > 0 {
gm := bot.Client.SendGroupForwardMessage(groupId, &message.ForwardMessage{Nodes: nodes})
return OK(MSG{
"message_id": ToGlobalId(groupId, gm.Id),
})
}
return Failed(100)
}
// https://cqhttp.cc/docs/4.15/#/API?id=send_private_msg-%E5%8F%91%E9%80%81%E7%A7%81%E8%81%8A%E6%B6%88%E6%81%AF // https://cqhttp.cc/docs/4.15/#/API?id=send_private_msg-%E5%8F%91%E9%80%81%E7%A7%81%E8%81%8A%E6%B6%88%E6%81%AF
func (bot *CQBot) CQSendPrivateMessage(userId int64, m gjson.Result) MSG { func (bot *CQBot) CQSendPrivateMessage(userId int64, m gjson.Result) MSG {
if m.Type == gjson.String { if m.Type == gjson.String {

View File

@ -142,6 +142,9 @@ func (bot *CQBot) ConvertObjectMessage(m gjson.Result, group bool) (r []message.
} }
r = append(r, elem) r = append(r, elem)
} }
if m.Type == gjson.String {
return bot.ConvertStringMessage(m.Str, group)
}
if m.IsArray() { if m.IsArray() {
for _, e := range m.Array() { for _, e := range m.Array() {
convertElem(e) convertElem(e)

View File

@ -4,10 +4,122 @@
## CQCode ## CQCode
| Code | 示例 | 说明 | ### 回复
| ------- | -------------------- | ------------------------------------------------------------ |
| reply | [CQ:reply,id=123456] | 回复ID为 `123456`的信息. 发送时一条 `message` 仅能使用一次 | Type : `reply`
| forward | [CQ:forward,id=abcd] | ID为abcd的转发消息, 暂时仅能接收. 可通过 `/get_forward_msg` API获取具体信息 |
范围: **发送/接收**
参数:
| 参数名 | 类型 | 说明 |
| ------ | ---- | ------------------------------------- |
| id | int | 回复时所引用的消息id, 必须为本群消息. |
示例: `[CQ:reply,id=123456]`
### 合并转发
Type: `forward`
范围: **接收**
参数:
| 参数名 | 类型 | 说明 |
| ------ | ------ | ------------------------------------------------------------ |
| id | string | 合并转发ID, 需要通过 `/get_forward_msg` API获取转发的具体内容 |
示例: `[CQ:forward,id=xxxx]`
### 合并转发消息节点
Type: `node`
范围: **发送**
参数:
| 参数名 | 类型 | 说明 | 特殊说明 |
| ------- | ------- | -------------- | ------------------------------------------------------------ |
| id | int32 | 转发消息id | 直接引用他人的消息合并转发, 实际查看顺序为原消息发送顺序 **与下面的自定义消息二选一** |
| name | string | 发送者显示名字 | 用于自定义消息 (自定义消息并合并转发,实际查看顺序为自定义消息段顺序) |
| uin | int64 | 发送者QQ号 | 用于自定义消息 |
| content | message | 具体消息 | 用于自定义消息 **不支持转发套娃,不支持引用回复** |
特殊说明: **需要使用单独的API `/send_group_forward_msg` 发送并且由于消息段较为复杂仅支持Array形式入参。 如果引用消息和自定义消息同时出现,实际查看顺序将取消息段顺序. 另外按 [CQHTTP](https://cqhttp.cc/docs/4.15/#/Message?id=格式) 文档说明, `data` 应全为字符串, 但由于需要接收`message` 类型的消息, 所以 *仅限此Type的content字段* 支持Array套娃**
示例:
直接引用消息合并转发:
````json
[
{
"type": "node",
"data": {
"id": "123"
}
},
{
"type": "node",
"data": {
"id": "456"
}
}
]
````
自定义消息合并转发:
````json
[
{
"type": "node",
"data": {
"name": "消息发送者A",
"uin": "10086",
"content": [
{
"type": "text",
"data": {"text": "测试消息1"}
}
]
}
},
{
"type": "node",
"data": {
"name": "消息发送者B",
"uin": "10087",
"content": "[CQ:image,file=xxxxx]测试消息2"
}
}
]
````
引用自定义混合合并转发:
````json
[
{
"type": "node",
"data": {
"name": "自定义发送者",
"uin": "10086",
"content": "我是自定义消息"
}
},
{
"type": "node",
"data": {
"id": "123"
}
}
]
````
## API ## API

View File

@ -97,6 +97,9 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) {
s.engine.Any("/send_group_msg", s.SendGroupMessage) s.engine.Any("/send_group_msg", s.SendGroupMessage)
s.engine.Any("/send_group_msg_async", s.SendGroupMessage) s.engine.Any("/send_group_msg_async", s.SendGroupMessage)
s.engine.Any("/send_group_forward_msg", s.SendGroupForwardMessage)
s.engine.Any("/send_group_forward_msg_async", s.SendGroupForwardMessage)
s.engine.Any("/delete_msg", s.DeleteMessage) s.engine.Any("/delete_msg", s.DeleteMessage)
s.engine.Any("/delete_msg_async", s.DeleteMessage) s.engine.Any("/delete_msg_async", s.DeleteMessage)
@ -246,6 +249,12 @@ func (s *httpServer) SendGroupMessage(c *gin.Context) {
c.JSON(200, s.bot.CQSendGroupMessage(gid, gjson.Result{Type: gjson.String, Str: msg})) c.JSON(200, s.bot.CQSendGroupMessage(gid, gjson.Result{Type: gjson.String, Str: msg}))
} }
func (s *httpServer) SendGroupForwardMessage(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
msg := getParam(c, "messages")
c.JSON(200, s.bot.CQSendGroupForwardMessage(gid, gjson.Parse(msg)))
}
func (s *httpServer) GetImage(c *gin.Context) { func (s *httpServer) GetImage(c *gin.Context) {
file := getParam(c, "file") file := getParam(c, "file")
c.JSON(200, s.bot.CQGetImage(file)) c.JSON(200, s.bot.CQGetImage(file))

View File

@ -331,6 +331,9 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"send_group_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "send_group_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message")) return bot.CQSendGroupMessage(p.Get("group_id").Int(), p.Get("message"))
}, },
"send_group_forward_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSendGroupForwardMessage(p.Get("group_id").Int(), p.Get("messages"))
},
"send_private_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "send_private_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message")) return bot.CQSendPrivateMessage(p.Get("user_id").Int(), p.Get("message"))
}, },