Commit fa6263e7 authored by nanahira's avatar nanahira

Merge branch 'master' of github.com:Mrs4s/go-cqhttp

parents 75e2e368 3d81777e
......@@ -14,12 +14,14 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/386, darwin/amd64
# build and publish in parallel: linux/386, linux/amd64, windows/386, windows/amd64, darwin/amd64
goos: [linux, windows, darwin]
goarch: ["386", amd64, arm]
exclude:
- goos: darwin
goarch: arm
- goos: darwin
goarch: "386"
fail-fast: true
steps:
......@@ -28,7 +30,7 @@ jobs:
- name: Setup Go environment
uses: actions/setup-go@v2.1.1
with:
go-version: 1.14
go-version: 1.15
- name: Build binary file
env:
......
......@@ -14,6 +14,8 @@ jobs:
exclude:
- goos: darwin
goarch: arm
- goos: darwin
goarch: "386"
steps:
- uses: actions/checkout@v2
......@@ -26,5 +28,6 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
goversion: "https://golang.org/dl/go1.15.3.linux-amd64.tar.gz"
ldflags: -w -s -X "github.com/Mrs4s/go-cqhttp/coolq.Version=${{ env.RELEASE_VERSION }}"
\ No newline at end of file
......@@ -35,6 +35,10 @@
- [CQ:reply]
- [CQ:forward]
- [CQ:node]
- [CQ:gift]
- [CQ:redbag]
- [CQ:tts]
- [CQ:music]
</details>
......
......@@ -189,7 +189,7 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupId int64, m gjson.Result) MSG {
ts.Add(time.Second)
if e.Get("data.id").Exists() {
i, _ := strconv.Atoi(e.Get("data.id").Str)
m := bot.GetGroupMessage(int32(i))
m := bot.GetMessage(int32(i))
if m != nil {
sender := m["sender"].(message.Sender)
nodes = append(nodes, &message.ForwardNode{
......@@ -384,39 +384,61 @@ func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) MSG {
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E7%BE%A4%E8%AF%B7%E6%B1%82%EF%BC%8F%E9%82%80%E8%AF%B7
func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bool) MSG {
msgs, err := bot.Client.GetGroupSystemMessages()
if err != nil {
log.Errorf("获取群系统消息失败: %v", err)
return Failed(100)
}
if subType == "add" {
req, ok := bot.joinReqCache.Load(flag)
if !ok {
return Failed(100)
}
bot.joinReqCache.Delete(flag)
if approve {
req.(*client.UserJoinGroupRequest).Accept()
} else {
req.(*client.UserJoinGroupRequest).Reject(false, reason)
for _, req := range msgs.JoinRequests {
if strconv.FormatInt(req.RequestId, 10) == flag {
if req.Checked {
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
return Failed(100)
}
if approve {
req.Accept()
} else {
req.Reject(false, reason)
}
return OK(nil)
}
}
return OK(nil)
}
req, ok := bot.invitedReqCache.Load(flag)
if ok {
bot.invitedReqCache.Delete(flag)
if approve {
req.(*client.GroupInvitedRequest).Accept()
} else {
req.(*client.GroupInvitedRequest).Reject(false, reason)
} else {
for _, req := range msgs.InvitedRequests {
if strconv.FormatInt(req.RequestId, 10) == flag {
if req.Checked {
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
return Failed(100)
}
if approve {
req.Accept()
} else {
req.Reject(false, reason)
}
return OK(nil)
}
}
return OK(nil)
}
log.Errorf("处理群系统消息失败: 消息 %v 不存在.", flag)
return Failed(100)
}
// https://cqhttp.cc/docs/4.15/#/API?id=delete_msg-%E6%92%A4%E5%9B%9E%E6%B6%88%E6%81%AF
func (bot *CQBot) CQDeleteMessage(messageId int32) MSG {
msg := bot.GetGroupMessage(messageId)
msg := bot.GetMessage(messageId)
if msg == nil {
return Failed(100)
}
bot.Client.RecallGroupMessage(msg["group"].(int64), msg["message-id"].(int32), msg["internal-id"].(int32))
if _, ok := msg["group"]; ok {
bot.Client.RecallGroupMessage(msg["group"].(int64), msg["message-id"].(int32), msg["internal-id"].(int32))
} else {
if msg["sender"].(message.Sender).Uin != bot.Client.Uin {
log.Warnf("撤回 %v 失败: 好友会话无法撤回对方消息.")
return Failed(100)
}
bot.Client.RecallPrivateMessage(msg["target"].(int64), int64(msg["time"].(int32)), msg["message-id"].(int32), msg["internal-id"].(int32))
}
return OK(nil)
}
......@@ -638,24 +660,35 @@ func (bot *CQBot) CQGetForwardMessage(resId string) MSG {
})
}
func (bot *CQBot) CQGetGroupMessage(messageId int32) MSG {
msg := bot.GetGroupMessage(messageId)
func (bot *CQBot) CQGetMessage(messageId int32) MSG {
msg := bot.GetMessage(messageId)
if msg == nil {
return Failed(100)
}
sender := msg["sender"].(message.Sender)
_, group := msg["group"]
return OK(MSG{
"message_id": messageId,
"real_id": msg["message-id"],
"group": group,
"sender": MSG{
"user_id": sender.Uin,
"nickname": sender.Nickname,
},
"time": msg["time"],
"content": msg["message"],
"message": msg["message"],
})
}
func (bot *CQBot) CQGetGroupSystemMessages() MSG {
msg, err := bot.Client.GetGroupSystemMessages()
if err != nil {
log.Warnf("获取群系统消息失败: %v", err)
return Failed(100)
}
return OK(msg)
}
func (bot *CQBot) CQCanSendImage() MSG {
return OK(MSG{"yes": true})
}
......@@ -665,7 +698,7 @@ func (bot *CQBot) CQCanSendRecord() MSG {
}
func (bot *CQBot) CQOcrImage(imageId string) MSG {
img, err := bot.makeImageElem("image", map[string]string{"file": imageId}, true)
img, err := bot.makeImageElem(map[string]string{"file": imageId}, true)
if err != nil {
log.Warnf("load image error: %v", err)
return Failed(100)
......
......@@ -5,6 +5,7 @@ import (
"encoding/gob"
"encoding/json"
"fmt"
"github.com/syndtr/goleveldb/leveldb"
"hash/crc32"
"path"
"sync"
......@@ -17,19 +18,16 @@ import (
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"github.com/xujiajun/nutsdb"
)
type CQBot struct {
Client *client.QQClient
events []func(MSG)
db *nutsdb.DB
friendReqCache sync.Map
invitedReqCache sync.Map
joinReqCache sync.Map
tempMsgCache sync.Map
oneWayMsgCache sync.Map
events []func(MSG)
db *leveldb.DB
friendReqCache sync.Map
tempMsgCache sync.Map
oneWayMsgCache sync.Map
}
type MSG map[string]interface{}
......@@ -41,10 +39,8 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
Client: cli,
}
if conf.EnableDB {
opt := nutsdb.DefaultOptions
opt.Dir = path.Join("data", "db")
opt.EntryIdxMode = nutsdb.HintBPTSparseIdxMode
db, err := nutsdb.Open(opt)
p := path.Join("data", "leveldb")
db, err := leveldb.OpenFile(p, nil)
if err != nil {
log.Fatalf("打开数据库失败, 如果频繁遇到此问题请清理 data/db 文件夹或关闭数据库功能。")
}
......@@ -61,6 +57,7 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
bot.Client.OnGroupMessageRecalled(bot.groupRecallEvent)
bot.Client.OnGroupNotify(bot.groupNotifyEvent)
bot.Client.OnFriendMessageRecalled(bot.friendRecallEvent)
bot.Client.OnReceivedOfflineFile(bot.offlineFileEvent)
bot.Client.OnJoinGroup(bot.joinGroupEvent)
bot.Client.OnLeaveGroup(bot.leaveGroupEvent)
bot.Client.OnGroupMemberJoined(bot.memberJoinEvent)
......@@ -99,20 +96,17 @@ func (bot *CQBot) OnEventPush(f func(m MSG)) {
bot.events = append(bot.events, f)
}
func (bot *CQBot) GetGroupMessage(mid int32) MSG {
func (bot *CQBot) GetMessage(mid int32) MSG {
if bot.db != nil {
m := MSG{}
err := bot.db.View(func(tx *nutsdb.Tx) error {
e, err := tx.Get("group-messages", binary.ToBytes(mid))
if err != nil {
return err
}
buff := new(bytes.Buffer)
buff.Write(binary.GZipUncompress(e.Value))
return gob.NewDecoder(buff).Decode(&m)
})
data, err := bot.db.Get(binary.ToBytes(mid), nil)
if err == nil {
return m
buff := new(bytes.Buffer)
buff.Write(binary.GZipUncompress(data))
err = gob.NewDecoder(buff).Decode(&m)
if err == nil {
return m
}
}
log.Warnf("获取信息时出现错误: %v id: %v", err, mid)
}
......@@ -153,7 +147,11 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int
return 0
}
if i, ok := elem.(*QQMusicElement); ok {
ret, err := bot.Client.SendGroupRichMessage(groupId, 100497308, 1, 4, client.RichClientInfo{
var msgStyle uint32 = 4
if i.MusicUrl == "" {
msgStyle = 0 // fix vip song
}
ret, err := bot.Client.SendGroupRichMessage(groupId, 100497308, 1, msgStyle, client.RichClientInfo{
Platform: 1,
SdkVersion: "0.0.0",
PackageName: "com.tencent.qqmusic",
......@@ -190,8 +188,31 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int
}
return bot.InsertGroupMessage(ret)
}
if i, ok := elem.(*MiguMusicElement); ok {
ret, err := bot.Client.SendGroupRichMessage(groupId, 1101053067, 1, 4, client.RichClientInfo{
Platform: 1,
SdkVersion: "0.0.0",
PackageName: "cmccwm.mobilemusic",
Signature: "6cdc72a439cef99a3418d2a78aa28c73",
}, &message.RichMessage{
Title: i.Title,
Summary: i.Summary,
Url: i.Url,
PictureUrl: i.PictureUrl,
MusicUrl: i.MusicUrl,
})
if err != nil {
log.Warnf("警告: 群 %v 富文本消息发送失败: %v", groupId, err)
return -1
}
return bot.InsertGroupMessage(ret)
}
newElem = append(newElem, elem)
}
if len(newElem) == 0 {
log.Warnf("群消息发送失败: 消息为空.")
return -1
}
m.Elements = newElem
ret := bot.Client.SendGroupMessage(groupId, m, ForceFragmented)
if ret == nil || ret.Id == -1 {
......@@ -213,30 +234,88 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in
newElem = append(newElem, fm)
continue
}
if i, ok := elem.(*message.VoiceElement); ok {
fv, err := bot.Client.UploadPrivatePtt(target, i.Data)
if err != nil {
log.Warnf("警告: 好友 %v 消息语音上传失败: %v", target, err)
continue
}
newElem = append(newElem, fv)
continue
}
if i, ok := elem.(*QQMusicElement); ok {
var msgStyle uint32 = 4
if i.MusicUrl == "" {
msgStyle = 0 // fix vip song
}
bot.Client.SendFriendRichMessage(target, 100497308, 1, msgStyle, client.RichClientInfo{
Platform: 1,
SdkVersion: "0.0.0",
PackageName: "com.tencent.qqmusic",
Signature: "cbd27cd7c861227d013a25b2d10f0799",
}, &message.RichMessage{
Title: i.Title,
Summary: i.Summary,
Url: i.Url,
PictureUrl: i.PictureUrl,
MusicUrl: i.MusicUrl,
})
return 0
}
if i, ok := elem.(*CloudMusicElement); ok {
bot.Client.SendFriendRichMessage(target, 100495085, 1, 4, client.RichClientInfo{
Platform: 1,
SdkVersion: "0.0.0",
PackageName: "com.netease.cloudmusic",
Signature: "da6b069da1e2982db3e386233f68d76d",
}, &message.RichMessage{
Title: i.Title,
Summary: i.Summary,
Url: i.Url,
PictureUrl: i.PictureUrl,
MusicUrl: i.MusicUrl,
})
return 0
}
if i, ok := elem.(*MiguMusicElement); ok {
bot.Client.SendFriendRichMessage(target, 1101053067, 1, 4, client.RichClientInfo{
Platform: 1,
SdkVersion: "0.0.0",
PackageName: "cmccwm.mobilemusic",
Signature: "6cdc72a439cef99a3418d2a78aa28c73",
}, &message.RichMessage{
Title: i.Title,
Summary: i.Summary,
Url: i.Url,
PictureUrl: i.PictureUrl,
MusicUrl: i.MusicUrl,
})
return 0
}
newElem = append(newElem, elem)
}
m.Elements = newElem
var id int32 = -1
if bot.Client.FindFriend(target) != nil {
if bot.Client.FindFriend(target) != nil { // 双向好友
msg := bot.Client.SendPrivateMessage(target, m)
if msg != nil {
id = msg.Id
id = bot.InsertPrivateMessage(msg)
}
} else if code, ok := bot.tempMsgCache.Load(target); ok {
} else if code, ok := bot.tempMsgCache.Load(target); ok { // 临时会话
msg := bot.Client.SendTempMessage(code.(int64), target, m)
if msg != nil {
id = msg.Id
}
} else if _, ok := bot.oneWayMsgCache.Load(target); ok {
} else if _, ok := bot.oneWayMsgCache.Load(target); ok { // 单向好友
msg := bot.Client.SendPrivateMessage(target, m)
if msg != nil {
id = msg.Id
id = bot.InsertPrivateMessage(msg)
}
}
if id == -1 {
return -1
}
return ToGlobalId(target, id)
return id
}
func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
......@@ -251,14 +330,36 @@ func (bot *CQBot) InsertGroupMessage(m *message.GroupMessage) int32 {
}
id := ToGlobalId(m.GroupCode, m.Id)
if bot.db != nil {
err := bot.db.Update(func(tx *nutsdb.Tx) error {
buf := new(bytes.Buffer)
if err := gob.NewEncoder(buf).Encode(val); err != nil {
return err
}
return tx.Put("group-messages", binary.ToBytes(id), binary.GZipCompress(buf.Bytes()), 0)
})
if err != nil {
buf := new(bytes.Buffer)
if err := gob.NewEncoder(buf).Encode(val); err != nil {
log.Warnf("记录聊天数据时出现错误: %v", err)
return -1
}
if err := bot.db.Put(binary.ToBytes(id), binary.GZipCompress(buf.Bytes()), nil); err != nil {
log.Warnf("记录聊天数据时出现错误: %v", err)
return -1
}
}
return id
}
func (bot *CQBot) InsertPrivateMessage(m *message.PrivateMessage) int32 {
val := MSG{
"message-id": m.Id,
"internal-id": m.InternalId,
"target": m.Target,
"sender": m.Sender,
"time": m.Time,
"message": ToStringMessage(m.Elements, m.Sender.Uin, true),
}
id := ToGlobalId(m.Sender.Uin, m.Id)
if bot.db != nil {
buf := new(bytes.Buffer)
if err := gob.NewEncoder(buf).Encode(val); err != nil {
log.Warnf("记录聊天数据时出现错误: %v", err)
return -1
}
if err := bot.db.Put(binary.ToBytes(id), binary.GZipCompress(buf.Bytes()), nil); err != nil {
log.Warnf("记录聊天数据时出现错误: %v", err)
return -1
}
......
This diff is collapsed.
......@@ -31,18 +31,22 @@ func ToFormattedMessage(e []message.IMessageElement, code int64, raw ...bool) (r
func (bot *CQBot) privateMessageEvent(c *client.QQClient, m *message.PrivateMessage) {
bot.checkMedia(m.Elements)
cqm := ToStringMessage(m.Elements, 0, true)
cqm := ToStringMessage(m.Elements, m.Sender.Uin, true)
if !m.Sender.IsFriend {
bot.oneWayMsgCache.Store(m.Sender.Uin, "")
}
log.Infof("收到好友 %v(%v) 的消息: %v", m.Sender.DisplayName(), m.Sender.Uin, cqm)
id := m.Id
if bot.db != nil {
id = bot.InsertPrivateMessage(m)
}
log.Infof("收到好友 %v(%v) 的消息: %v (%v)", m.Sender.DisplayName(), m.Sender.Uin, cqm, id)
fm := MSG{
"post_type": "message",
"message_type": "private",
"sub_type": "friend",
"message_id": ToGlobalId(m.Sender.Uin, m.Id),
"message_id": id,
"user_id": m.Sender.Uin,
"message": ToFormattedMessage(m.Elements, 0, false),
"message": ToFormattedMessage(m.Elements, m.Sender.Uin, false),
"raw_message": cqm,
"font": 0,
"self_id": c.Uin,
......@@ -267,17 +271,41 @@ func (bot *CQBot) groupNotifyEvent(c *client.QQClient, e client.IGroupNotifyEven
func (bot *CQBot) friendRecallEvent(c *client.QQClient, e *client.FriendMessageRecalledEvent) {
f := c.FindFriend(e.FriendUin)
gid := ToGlobalId(e.FriendUin, e.MessageId)
log.Infof("好友 %v(%v) 撤回了消息: %v", f.Nickname, f.Uin, gid)
if f != nil {
log.Infof("好友 %v(%v) 撤回了消息: %v", f.Nickname, f.Uin, gid)
} else {
log.Infof("好友 %v 撤回了消息: %v", e.FriendUin, gid)
}
bot.dispatchEventMessage(MSG{
"post_type": "notice",
"notice_type": "friend_recall",
"self_id": c.Uin,
"user_id": f.Uin,
"user_id": e.FriendUin,
"time": e.Time,
"message_id": gid,
})
}
func (bot *CQBot) offlineFileEvent(c *client.QQClient, e *client.OfflineFileEvent) {
f := c.FindFriend(e.Sender)
if f == nil {
return
}
log.Infof("好友 %v(%v) 发送了离线文件 %v", f.Nickname, f.Uin, e.FileName)
bot.dispatchEventMessage(MSG{
"post_type": "notice",
"notice_type": "offline_file",
"user_id": e.Sender,
"file": MSG{
"name": e.FileName,
"size": e.FileSize,
"url": e.DownloadUrl,
},
"self_id": c.Uin,
"time": time.Now().Unix(),
})
}
func (bot *CQBot) joinGroupEvent(c *client.QQClient, group *client.GroupInfo) {
log.Infof("Bot进入了群 %v.", formatGroupName(group))
bot.dispatchEventMessage(bot.groupIncrease(group.Code, 0, c.Uin))
......@@ -368,7 +396,6 @@ func (bot *CQBot) friendAddedEvent(c *client.QQClient, e *client.NewFriendEvent)
func (bot *CQBot) groupInvitedEvent(c *client.QQClient, e *client.GroupInvitedRequest) {
log.Infof("收到来自群 %v(%v) 内用户 %v(%v) 的加群邀请.", e.GroupName, e.GroupCode, e.InvitorNick, e.InvitorUin)
flag := strconv.FormatInt(e.RequestId, 10)
bot.invitedReqCache.Store(flag, e)
bot.dispatchEventMessage(MSG{
"post_type": "request",
"request_type": "group",
......@@ -385,7 +412,6 @@ func (bot *CQBot) groupInvitedEvent(c *client.QQClient, e *client.GroupInvitedRe
func (bot *CQBot) groupJoinReqEvent(c *client.QQClient, e *client.UserJoinGroupRequest) {
log.Infof("群 %v(%v) 收到来自用户 %v(%v) 的加群请求.", e.GroupName, e.GroupCode, e.RequesterNick, e.RequesterUin)
flag := strconv.FormatInt(e.RequestId, 10)
bot.joinReqCache.Store(flag, e)
bot.dispatchEventMessage(MSG{
"post_type": "request",
"request_type": "group",
......
# 常见问题
### Q: 为什么登录的时候出现 `客户端版本过低 请升级客户端`?
### A: 此问题是因为密码输入错误导致的, 信息为服务器返回, 很可能是TX相关的错误, 请检查密码
### Q: 为什么登录的时候出现 `为了您的帐号安全,请使用QQ一键登录`?
### A: 因为目前手机协议不支持图片验证码,切换成平板协议登录成功后,再切换回手机协议即可
### Q: 为什么挂一段时间后就会出现 `消息发送失败,账号可能被风控`?
### A: 如果你刚开始使用 go-cqhttp 建议挂机3-7天,即可解除风控
......@@ -4,6 +4,28 @@
## CQCode
### 图片
| 参数名 | 可能的值 | 说明 |
| --- | --- | --- |
| `file` | - | 图片文件名 |
| `type` | `flash``show` | 图片类型,`flash` 表示闪照,`show` 表示秀图,默认普通图片 |
| `url` | - | 图片 URL |
| `cache` | `0` `1` | 只在通过网络 URL 发送时有效,表示是否使用已缓存的文件,默认 `1` |
| `id` | - | 发送秀图时的特效id,默认为40000 |
可用的特效ID:
| id |类型 |
| --- |-------|
| 40000 | 普通 |
| 40001 | 幻影 |
| 40002 | 抖动 |
| 40003 | 生日 |
| 40004 | 爱你 |
| 40005 | 征友 |
### 回复
Type : `reply`
......@@ -358,9 +380,9 @@ Type: `tts`
| `filename` | string | 图片文件原名 |
| `url` | string | 图片下载地址 |
### 获取消息
### 获取消息
终结点: `/get_group_msg`
终结点: `/get_msg`
参数
......@@ -376,7 +398,7 @@ Type: `tts`
| `real_id` | int32 | 消息真实id |
| `sender` | object | 发送者 |
| `time` | int32 | 发送时间 |
| `content` | message | 消息内容 |
| `message` | message | 消息内容 |
### 获取合并转发内容
......@@ -450,6 +472,74 @@ Type: `tts`
| ---------- | ----------------- | -------- |
| `slices` | string[] | 词组 |
### 图片OCR
> 注意: 目前图片OCR接口仅支持接受的图片
终结点: `/.ocr_image`
**参数**
| 字段 | 类型 | 说明 |
| ------------ | ------ | ------ |
| `image` | string | 图片ID |
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `texts` | TextDetection[] | OCR结果 |
| `language` | string | 语言 |
**TextDetection**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `text` | string | 文本 |
| `confidence`| int32 | 置信度 |
| `coordinates` | vector2 | 坐标 |
### 获取群系统消息
终结点: `/get_group_system_msg`
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `invited_requests` | InvitedRequest[] | 邀请消息列表 |
| `join_requests` | JoinRequest[] | 进群消息列表 |
> 注意: 如果列表不存在任何消息, 将返回 `null`
**InvitedRequest**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `request_id` | int64 | 请求ID |
| `invitor_uin` | int64 | 邀请者 |
| `invitor_nick` | string | 邀请者昵称 |
| `group_id` | int64 | 群号 |
| `group_name` | string | 群名 |
| `checked` | bool | 是否已被处理|
| `actor` | int64 | 处理者, 未处理为0 |
**JoinRequest**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `request_id` | int64 | 请求ID |
| `requester_uin` | int64 | 请求者ID |
| `requester_nick` | string | 请求者昵称 |
| `message` | string | 验证消息 |
| `group_id` | int64 | 群号 |
| `group_name` | string | 群名 |
| `checked` | bool | 是否已被处理|
| `actor` | int64 | 处理者, 未处理为0 |
## 事件
#### 群消息撤回
......@@ -536,4 +626,23 @@ Type: `tts`
| `card_new` | int64 | | 新名片 |
| `card_old` | int64 | | 旧名片 |
> PS: 当名片为空时 `card_xx` 字段为空字符串, 并不是昵称
\ No newline at end of file
> PS: 当名片为空时 `card_xx` 字段为空字符串, 并不是昵称
#### 接收到离线文件
**上报数据**
| 字段 | 类型 | 可能的值 | 说明 |
| ------------- | ------ | -------------- | -------------- |
| `post_type` | string | `notice` | 上报类型 |
| `notice_type` | string | `offline_file` | 消息类型 |
| `user_id` | int64 | | 发送者id |
| `file` | object | | 文件数据 |
**file object**
| 字段 | 类型 | 可能的值 | 说明 |
| ------------- | ------ | -------------- | -------------- |
| `name` | string | | 文件名 |
| `size` | int64 | | 文件大小 |
| `url` | string | | 下载链接 |
\ No newline at end of file
......@@ -8,15 +8,20 @@ import (
"io/ioutil"
"net/http"
"strings"
"time"
)
var client = &http.Client{
Timeout: time.Second * 15,
}
func GetBytes(url string) ([]byte, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
req.Header["User-Agent"] = []string{"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.61"}
resp, err := http.DefaultClient.Do(req)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
......
......@@ -3,32 +3,19 @@ module github.com/Mrs4s/go-cqhttp
go 1.14
require (
github.com/Mrs4s/MiraiGo v0.0.0-20201008134448-b53aaceaa1b4
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
github.com/Mrs4s/MiraiGo v0.0.0-20201027102621-5fa25a7f7434
github.com/gin-gonic/gin v1.6.3
github.com/go-playground/validator/v10 v10.4.0 // indirect
github.com/gorilla/websocket v1.4.2
github.com/guonaihong/gout v0.1.2
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/jonboulle/clockwork v0.2.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/guonaihong/gout v0.1.3
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github.com/lestrrat-go/strftime v1.0.3 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.7.0
github.com/syndtr/goleveldb v1.0.0
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/tebeka/strftime v0.1.5 // indirect
github.com/tidwall/gjson v1.6.1
github.com/ugorji/go v1.1.10 // indirect
github.com/wdvxdr1123/go-silk v0.0.0-20201007123416-b982fd3d91d6
github.com/xujiajun/nutsdb v0.5.0
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 // indirect
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c // indirect
golang.org/x/sys v0.0.0-20201005172224-997123666555 // indirect
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e
gopkg.in/yaml.v2 v2.3.0 // indirect
)
This diff is collapsed.
......@@ -77,7 +77,9 @@ func (s *webServer) Run(addr string, cli *client.QQClient) *coolq.CQBot {
if err != nil {
log.Error(err)
log.Infof("请检查端口是否被占用.")
time.Sleep(time.Second * 5)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
<-c
os.Exit(1)
}
} else {
......@@ -96,6 +98,10 @@ func (s *webServer) Run(addr string, cli *client.QQClient) *coolq.CQBot {
func (s *webServer) Dologin() {
s.Console = bufio.NewReader(os.Stdin)
readLine := func() (str string) {
str, _ = s.Console.ReadString('\n')
return
}
conf := GetConf()
cli := s.Cli
cli.AllowSlider = true
......@@ -109,7 +115,7 @@ func (s *webServer) Dologin() {
if client.SystemDeviceInfo.Protocol == client.AndroidPhone {
log.Warnf("警告: Android Phone 强制要求暂不支持的滑条验证码, 请开启设备锁或切换到Watch协议验证通过后再使用.")
log.Infof("按 Enter 继续....")
_, _ = s.Console.ReadString('\n')
readLine()
os.Exit(0)
}
cli.AllowSlider = false
......@@ -125,21 +131,21 @@ func (s *webServer) Dologin() {
text = <-WebInput
} else {
log.Warn("请输入验证码 (captcha.jpg): (Enter 提交)")
text, _ = s.Console.ReadString('\n')
text = readLine()
}
rsp, err = cli.SubmitCaptcha(strings.ReplaceAll(text, "\n", ""), rsp.CaptchaSign)
global.DelFile("captcha.jpg")
continue
case client.SMSNeededError:
log.Warnf("账号已开启设备锁, 按下 Enter 向手机 %v 发送短信验证码.", rsp.SMSPhone)
_, _ = s.Console.ReadString('\n')
readLine()
if !cli.RequestSMS() {
log.Warnf("发送验证码失败,可能是请求过于频繁.")
time.Sleep(time.Second * 5)
os.Exit(0)
}
log.Warn("请输入短信验证码: (Enter 提交)")
text, _ = s.Console.ReadString('\n')
text = readLine()
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
continue
case client.SMSOrVerifyNeededError:
......@@ -147,7 +153,7 @@ func (s *webServer) Dologin() {
log.Warnf("1. 向手机 %v 发送短信验证码", rsp.SMSPhone)
log.Warnf("2. 使用手机QQ扫码验证.")
log.Warn("请输入(1 - 2): ")
text, _ = s.Console.ReadString('\n')
text = readLine()
if strings.Contains(text, "1") {
if !cli.RequestSMS() {
log.Warnf("发送验证码失败,可能是请求过于频繁.")
......@@ -155,13 +161,13 @@ func (s *webServer) Dologin() {
os.Exit(0)
}
log.Warn("请输入短信验证码: (Enter 提交)")
text, _ = s.Console.ReadString('\n')
text = readLine()
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
continue
}
log.Warnf("请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
log.Infof("按 Enter 继续....")
_, _ = s.Console.ReadString('\n')
readLine()
os.Exit(0)
return
case client.UnsafeDeviceError:
......@@ -171,7 +177,7 @@ func (s *webServer) Dologin() {
text = <-WebInput
} else {
log.Infof("按 Enter 继续....")
_, _ = s.Console.ReadString('\n')
readLine()
}
log.Info(text)
os.Exit(0)
......@@ -179,7 +185,7 @@ func (s *webServer) Dologin() {
case client.OtherLoginError, client.UnknownLoginError:
log.Warnf("登录失败: %v", rsp.ErrorMessage)
log.Infof("按 Enter 继续....")
_, _ = s.Console.ReadString('\n')
readLine()
os.Exit(0)
return
}
......@@ -219,8 +225,7 @@ func (s *webServer) Dologin() {
log.Warn("Bot已登录")
return
}
if conf.ReLogin.MaxReloginTimes == 0 {
} else if times > conf.ReLogin.MaxReloginTimes {
if times > conf.ReLogin.MaxReloginTimes && conf.ReLogin.MaxReloginTimes != 0 {
break
}
log.Warnf("Bot已离线 (%v),将在 %v 秒后尝试重连. 重连次数:%v",
......
......@@ -137,6 +137,7 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) {
log.Warnf("上报Event数据 %v 到 %v 失败: %v", m.ToJson(), c.addr, err)
return
}
log.Debugf("上报Event数据 %v 到 %v", m.ToJson(), c.addr)
if gjson.Valid(res) {
c.bot.CQHandleQuickOperation(gjson.Parse(m.ToJson()), gjson.Parse(res))
}
......@@ -234,9 +235,9 @@ func (s *httpServer) GetImage(c *gin.Context) {
c.JSON(200, s.bot.CQGetImage(file))
}
func (s *httpServer) GetGroupMessage(c *gin.Context) {
func (s *httpServer) GetMessage(c *gin.Context) {
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 32)
c.JSON(200, s.bot.CQGetGroupMessage(int32(mid)))
c.JSON(200, s.bot.CQGetMessage(int32(mid)))
}
func (s *httpServer) GetGroupHonorInfo(c *gin.Context) {
......@@ -317,6 +318,10 @@ func (s *httpServer) GetForwardMessage(c *gin.Context) {
c.JSON(200, s.bot.CQGetForwardMessage(resId))
}
func (s *httpServer) GetGroupSystemMessage(c *gin.Context) {
c.JSON(200, s.bot.CQGetGroupSystemMessages())
}
func (s *httpServer) DeleteMessage(c *gin.Context) {
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 32)
c.JSON(200, s.bot.CQDeleteMessage(int32(mid)))
......@@ -501,8 +506,11 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){
"get_forward_msg": func(s *httpServer, c *gin.Context) {
s.GetForwardMessage(c)
},
"get_group_msg": func(s *httpServer, c *gin.Context) {
s.GetGroupMessage(c)
"get_msg": func(s *httpServer, c *gin.Context) {
s.GetMessage(c)
},
"get_group_system_msg": func(s *httpServer, c *gin.Context) {
s.GetGroupSystemMessage(c)
},
"get_group_honor_info": func(s *httpServer, c *gin.Context) {
s.GetGroupHonorInfo(c)
......
......@@ -474,8 +474,8 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"get_forward_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetForwardMessage(p.Get("message_id").Str)
},
"get_group_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupMessage(int32(p.Get("message_id").Int()))
"get_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetMessage(int32(p.Get("message_id").Int()))
},
"get_group_honor_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupHonorInfo(p.Get("group_id").Int(), p.Get("type").Str)
......@@ -495,6 +495,9 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"get_version_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVersionInfo()
},
"get_group_system_msg": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupSystemMessages()
},
"_get_vip_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVipInfo(p.Get("user_id").Int())
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment