diff --git a/README.md b/README.md index 4cd982b..0f39931 100644 --- a/README.md +++ b/README.md @@ -80,13 +80,14 @@ | ------------------------------------------------------------ | | [私聊信息](https://cqhttp.cc/docs/4.15/#/Post?id=私聊消息) | | [群消息](https://cqhttp.cc/docs/4.15/#/Post?id=群消息) | -| [群消息撤回(拓展Event)](docs/cqhttp.md#群消息撤回) | -| [好友消息撤回(拓展Event)](docs/cqhttp.md#好友消息撤回) | +| [群消息撤回(拓展Event)](docs/cqhttp.md#群消息撤回) | +| [好友消息撤回(拓展Event)](docs/cqhttp.md#好友消息撤回) | +| 群内提示事件(拓展Event)(docs/cqhttp.md#群内戳一戳) | | [群管理员变动](https://cqhttp.cc/docs/4.15/#/Post?id=群管理员变动) | | [群成员减少](https://cqhttp.cc/docs/4.15/#/Post?id=群成员减少) | | [群成员增加](https://cqhttp.cc/docs/4.15/#/Post?id=群成员增加) | | [群禁言](https://cqhttp.cc/docs/4.15/#/Post?id=群禁言) | -| [群文件上传](https://cqhttp.cc/docs/4.15/#/Post?id=群文件上传)| +| [群文件上传](https://cqhttp.cc/docs/4.15/#/Post?id=群文件上传) | | [加好友请求](https://cqhttp.cc/docs/4.15/#/Post?id=加好友请求) | | [加群请求/邀请](https://cqhttp.cc/docs/4.15/#/Post?id=加群请求/邀请) | diff --git a/coolq/bot.go b/coolq/bot.go index 063b94d..3083d13 100644 --- a/coolq/bot.go +++ b/coolq/bot.go @@ -59,6 +59,7 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot { bot.Client.OnTempMessage(bot.tempMessageEvent) bot.Client.OnGroupMuted(bot.groupMutedEvent) bot.Client.OnGroupMessageRecalled(bot.groupRecallEvent) + bot.Client.OnGroupNotify(bot.groupNotifyEvent) bot.Client.OnFriendMessageRecalled(bot.friendRecallEvent) bot.Client.OnJoinGroup(bot.joinGroupEvent) bot.Client.OnLeaveGroup(bot.leaveGroupEvent) diff --git a/coolq/cqcode.go b/coolq/cqcode.go index 76929d5..670a5df 100644 --- a/coolq/cqcode.go +++ b/coolq/cqcode.go @@ -71,6 +71,11 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M "data": map[string]string{"qq": fmt.Sprint(o.Target)}, } } + case *message.RedBagElement: + m = MSG{ + "type": "redbag", + "data": map[string]string{"title": o.Title}, + } case *message.ForwardElement: m = MSG{ "type": "forward", @@ -159,6 +164,8 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st continue } r += fmt.Sprintf("[CQ:at,qq=%d]", o.Target) + case *message.RedBagElement: + r += fmt.Sprintf("[CQ:redbag,title=%s]", o.Title) case *message.ForwardElement: r += fmt.Sprintf("[CQ:forward,id=%s]", o.ResId) case *message.FaceElement: diff --git a/coolq/event.go b/coolq/event.go index e91a0ed..a7fa0fa 100644 --- a/coolq/event.go +++ b/coolq/event.go @@ -205,6 +205,42 @@ func (bot *CQBot) groupRecallEvent(c *client.QQClient, e *client.GroupMessageRec }) } +func (bot *CQBot) groupNotifyEvent(c *client.QQClient, e client.IGroupNotifyEvent) { + group := c.FindGroup(e.From()) + switch notify := e.(type) { + case *client.GroupPokeNotifyEvent: + sender := group.FindMember(notify.Sender) + receiver := group.FindMember(notify.Receiver) + log.Infof("群 %v 内 %v 戳了戳 %v", formatGroupName(group), formatMemberName(sender), formatMemberName(receiver)) + bot.dispatchEventMessage(MSG{ + "post_type": "notice", + "group_id": group.Code, + "notice_type": "notify", + "notify_type": "poke", + "self_id": c.Uin, + "user_id": notify.Sender, + "sender_id": notify.Sender, + "receiver_id": notify.Receiver, + "time": time.Now().Unix(), + }) + case *client.GroupRedBagLuckyKingNotifyEvent: + sender := group.FindMember(notify.Sender) + luckyKing := group.FindMember(notify.LuckyKing) + log.Infof("群 %v 内 %v 的红包被抢完, %v 是运气王", formatGroupName(group), formatMemberName(sender), formatMemberName(luckyKing)) + bot.dispatchEventMessage(MSG{ + "post_type": "notice", + "group_id": group.Code, + "notice_type": "notify", + "notify_type": "lucky_king", + "self_id": c.Uin, + "user_id": notify.Sender, + "sender_id": notify.Sender, + "lucky_king_id": notify.LuckyKing, + "time": time.Now().Unix(), + }) + } +} + func (bot *CQBot) friendRecallEvent(c *client.QQClient, e *client.FriendMessageRecalledEvent) { f := c.FindFriend(e.FriendUin) gid := ToGlobalId(e.FriendUin, e.MessageId) diff --git a/docs/config.md b/docs/config.md index ccdff7c..cedef08 100644 --- a/docs/config.md +++ b/docs/config.md @@ -77,7 +77,7 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为: | post_message_format | string | 上报信息类型 | | ignore_invalid_cqcode| bool | 是否忽略错误的CQ码 | | force_fragmented | bool | 是否强制分片发送群长消息 | -| heartbeat_interval | int64 | 心跳间隔时间,单位秒,若0则关闭心跳 | +| heartbeat_interval | int64 | 心跳间隔时间,单位秒。小于0则关闭心跳,等于0使用默认值(5秒) | | http_config | object | HTTP API配置 | | ws_config | object | Websocket API 配置 | | ws_reverse_servers | object[] | 反向 Websocket API 配置 | @@ -90,3 +90,28 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为: > 注2: 分片发送为原酷Q发送长消息的老方案, 发送速度更优/兼容性更好,但在有发言频率限制的群里,可能无法发送。关闭后将优先使用新方案, 能发送更长的消息, 但发送速度更慢,在部分老客户端将无法解析. > 注3:关闭心跳服务可能引起断线,请谨慎关闭 + +## 设备信息 + +默认生成的设备信息如下所示: + +``` json +{ + "protocol": 0, + "display": "xxx", + "finger_print": "xxx", + "boot_id": "xxx", + "proc_version": "xxx", + "imei": "xxx" +} +``` + +在大部分情况下 我们只需要关心 `protocol` 字段: + +| 值 | 类型 | 限制 | +| ---- | ------------- | ----------------------------------------------------- | +| 0 | Android Pad | 无法接收 `group_notify` 事件、无法接收口令红包 | +| 1 | Android Phone | 无 | +| 2 | Android Watch | 除了 `Android Pad` 有的限制外还包括: 无法接收撤回消息 | + +> 注意, 根据协议的不同, 各类消息有所限制 \ No newline at end of file diff --git a/docs/cqhttp.md b/docs/cqhttp.md index 6c13a80..3ef1681 100644 --- a/docs/cqhttp.md +++ b/docs/cqhttp.md @@ -18,6 +18,20 @@ Type : `reply` 示例: `[CQ:reply,id=123456]` +### 红包 + +Type: `redbag` + +范围: **接收** + +参数: + +| 参数名 | 类型 | 说明 | +| ------ | ------ | ----------- | +| title | string | 祝福语/口令 | + +示例: `[CQ:redbag,title=恭喜发财]` + ### 合并转发 Type: `forward` @@ -362,3 +376,30 @@ Type: `cardimage` | `user_id` | int64 | | 好友id | | `message_id` | int64 | | 被撤回的消息id | +#### 群内戳一戳 + +> 注意:此事件无法在平板和手表协议上触发 + +**上报数据** + +| 字段 | 类型 | 可能的值 | 说明 | +| ------------- | ------ | -------------- | -------------- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `notify` | 消息类型 | +| `notify_type` | string | `poke` | 提示类型 | +| `user_id` | int64 | | 发送者id | +| `receiver_id` | int64 | | 被戳者id | + +#### 群红包运气王提示 + +> 注意:此事件无法在平板和手表协议上触发 + +**上报数据** + +| 字段 | 类型 | 可能的值 | 说明 | +| ------------- | ------ | -------------- | -------------- | +| `post_type` | string | `notice` | 上报类型 | +| `notice_type` | string | `notify` | 消息类型 | +| `notify_type` | string | `lucky_king` | 提示类型 | +| `user_id` | int64 | | 红包发送者id | +| `lucky_king_id` | int64 | | 运气王id | diff --git a/docs/file.md b/docs/file.md index 4fe926e..8ab82d0 100644 --- a/docs/file.md +++ b/docs/file.md @@ -7,6 +7,7 @@ go-cqhttp 默认生成的文件树如下所示: ├── go-cqhttp ├── config.json ├── device.json +├── servers.bin ├── logs │ └── xx-xx-xx.log └── data @@ -20,6 +21,7 @@ go-cqhttp 默认生成的文件树如下所示: | go-cqhttp | go-cqhttp可执行文件 | | config.json | 运行配置文件 | | device.json | 虚拟设备配置文件 | +| servers.bin | 储存QQ服务器地址 | | logs | 日志存放目录 | | data | 数据目录 | | data/images | 图片缓存目录 | diff --git a/go.mod b/go.mod index d5d97aa..56ddcdf 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/Mrs4s/go-cqhttp go 1.14 require ( - github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb + github.com/Mrs4s/MiraiGo v0.0.0-20200912123655-d92d61c5998e github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/gin-gonic/gin v1.6.3 github.com/go-playground/validator/v10 v10.3.0 // indirect diff --git a/go.sum b/go.sum index 4accc77..cb98193 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Mrs4s/MiraiGo v0.0.0-20200909095006-dde8bded28d1 h1:3cmUqA5RaikLx+59SODlBA7tjORQoh4t1w5CzH5bIH8= -github.com/Mrs4s/MiraiGo v0.0.0-20200909095006-dde8bded28d1/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= -github.com/Mrs4s/MiraiGo v0.0.0-20200909103204-808a63a78efe h1:O2BW87BwpwZDsn7YFHLfRGFGvTS4OUZsG2UiA13OxcQ= -github.com/Mrs4s/MiraiGo v0.0.0-20200909103204-808a63a78efe/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= -github.com/Mrs4s/MiraiGo v0.0.0-20200910010455-37409b1f6b9c h1:bhVr3W0+WTVN+vgZGlxD4iFSV9L3CmUg/lt91h+Ll18= -github.com/Mrs4s/MiraiGo v0.0.0-20200910010455-37409b1f6b9c/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= -github.com/Mrs4s/MiraiGo v0.0.0-20200910013944-236c0f629099 h1:b+Tmo9h5leZmQokdUu8c2xSIRkkSYoP1z8G+zcwwyRY= -github.com/Mrs4s/MiraiGo v0.0.0-20200910013944-236c0f629099/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= -github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb h1:WRj/3obehfAMTNKfNo+X3NVqXjeNurMk2yy6haNl/Yk= -github.com/Mrs4s/MiraiGo v0.0.0-20200911100852-71bc19cd42eb/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= +github.com/Mrs4s/MiraiGo v0.0.0-20200912123655-d92d61c5998e h1:wiaXXMPnYCfA+rX1wy9SNrDyW3O43wfun5dIYKKK3BI= +github.com/Mrs4s/MiraiGo v0.0.0-20200912123655-d92d61c5998e/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -70,8 +62,6 @@ github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdA github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible h1:4mNlp+/SvALIPFpbXV3kxNJJno9iKFWGxSDE13Kl66Q= -github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q= @@ -148,8 +138,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/main.go b/main.go index 8bb79cd..71344e7 100644 --- a/main.go +++ b/main.go @@ -214,6 +214,17 @@ func main() { log.Info("Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消.") time.Sleep(time.Second * 5) log.Info("开始尝试登录并同步消息...") + log.Infof("使用协议: %v", func() string { + switch client.SystemDeviceInfo.Protocol { + case client.AndroidPad: + return "Android Pad" + case client.AndroidPhone: + return "Android Phone" + case client.AndroidWatch: + return "Android Watch" + } + return "未知" + }()) cli := client.NewClient(conf.Uin, conf.Password) cli.OnLog(func(c *client.QQClient, e *client.LogEvent) { switch e.Type {