1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-05-06 03:53:50 +08:00

Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
wdvxdr 2020-11-09 21:24:15 +08:00
commit c49c68891b
15 changed files with 441 additions and 71 deletions

View File

@ -68,7 +68,7 @@
| /set_group_leave | [退出群组](https://cqhttp.cc/docs/4.15/#/API?id=set_group_leave-退出群组) |
| /set_group_name | 设置群组名(拓展API) |
| /get_image | 获取图片信息(拓展API) |
| /get_group_msg | 获取群组消息(拓展API) |
| /get_msg | [获取消息]() | <!-- TODO 来人补个链接-->
| /can_send_image | [检查是否可以发送图片](https://cqhttp.cc/docs/4.15/#/API?id=can_send_image-检查是否可以发送图片) |
| /can_send_record | [检查是否可以发送语音](https://cqhttp.cc/docs/4.15/#/API?id=can_send_record-检查是否可以发送语音) |
| /get_status | [获取插件运行状态](https://cqhttp.cc/docs/4.15/#/API?id=get_status-获取插件运行状态) |

View File

@ -102,6 +102,59 @@ func (bot *CQBot) CQGetGroupMemberInfo(groupId, userId int64) MSG {
return OK(convertGroupMemberInfo(groupId, member))
}
func (bot *CQBot) CQGetGroupFileSystemInfo(groupId int64) MSG {
fs, err := bot.Client.GetGroupFileSystem(groupId)
if err != nil {
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
return Failed(100)
}
return OK(fs)
}
func (bot *CQBot) CQGetGroupRootFiles(groupId int64) MSG {
fs, err := bot.Client.GetGroupFileSystem(groupId)
if err != nil {
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
return Failed(100)
}
files, folders, err := fs.Root()
if err != nil {
log.Errorf("获取群 %v 根目录文件失败: %v", groupId, err)
return Failed(100)
}
return OK(MSG{
"files": files,
"folders": folders,
})
}
func (bot *CQBot) CQGetGroupFilesByFolderId(groupId int64, folderId string) MSG {
fs, err := bot.Client.GetGroupFileSystem(groupId)
if err != nil {
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
return Failed(100)
}
files, folders, err := fs.GetFilesByFolder(folderId)
if err != nil {
log.Errorf("获取群 %v 根目录 %v 子文件失败: %v", groupId, folderId, err)
return Failed(100)
}
return OK(MSG{
"files": files,
"folders": folders,
})
}
func (bot *CQBot) CQGetGroupFileUrl(groupId int64, fileId string, busId int32) MSG {
url := bot.Client.GetGroupFileUrl(groupId, fileId, busId)
if url == "" {
return Failed(100)
}
return OK(MSG{
"url": url,
})
}
func (bot *CQBot) CQGetWordSlices(content string) MSG {
slices, err := bot.Client.GetWordSegmentation(content)
if err != nil {
@ -384,29 +437,43 @@ 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 {
if subType == "add" {
req, ok := bot.joinReqCache.Load(flag)
if !ok {
msgs, err := bot.Client.GetGroupSystemMessages()
if err != nil {
log.Errorf("获取群系统消息失败: %v", err)
return Failed(100)
}
if subType == "add" {
for _, req := range msgs.JoinRequests {
if strconv.FormatInt(req.RequestId, 10) == flag {
if req.Checked {
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
return Failed(100)
}
bot.joinReqCache.Delete(flag)
if approve {
req.(*client.UserJoinGroupRequest).Accept()
req.Accept()
} else {
req.(*client.UserJoinGroupRequest).Reject(false, reason)
req.Reject(false, reason)
}
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)
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)
}
}
}
log.Errorf("处理群系统消息失败: 消息 %v 不存在.", flag)
return Failed(100)
}
@ -666,6 +733,15 @@ func (bot *CQBot) CQGetMessage(messageId int32) MSG {
})
}
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})
}

View File

@ -26,8 +26,6 @@ type CQBot struct {
events []func(MSG)
db *leveldb.DB
friendReqCache sync.Map
invitedReqCache sync.Map
joinReqCache sync.Map
tempMsgCache sync.Map
oneWayMsgCache sync.Map
}
@ -211,7 +209,12 @@ func (bot *CQBot) SendGroupMessage(groupId int64, m *message.SendingMessage) int
}
newElem = append(newElem, elem)
}
if len(newElem) == 0 {
log.Warnf("群消息发送失败: 消息为空.")
return -1
}
m.Elements = newElem
bot.checkMedia(newElem)
ret := bot.Client.SendGroupMessage(groupId, m, ForceFragmented)
if ret == nil || ret.Id == -1 {
log.Warnf("群消息发送失败: 账号可能被风控.")
@ -292,7 +295,12 @@ func (bot *CQBot) SendPrivateMessage(target int64, m *message.SendingMessage) in
}
newElem = append(newElem, elem)
}
if len(newElem) == 0 {
log.Warnf("好友消息发送失败: 消息为空.")
return -1
}
m.Elements = newElem
bot.checkMedia(newElem)
var id int32 = -1
if bot.Client.FindFriend(target) != nil { // 双向好友
msg := bot.Client.SendPrivateMessage(target, m)

View File

@ -243,6 +243,10 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st
} else {
r += fmt.Sprintf(`[CQ:image,file=%s,url=%s]`, o.Filename, CQCodeEscapeValue(o.Url))
}
case *message.GroupImageElement:
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
case *message.FriendImageElement:
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
case *message.ServiceElement:
if isOk := strings.Contains(o.Content, "<?xml"); isOk {
r += fmt.Sprintf(`[CQ:xml,data=%s,resid=%d]`, CQCodeEscapeValue(o.Content), o.Id)

View File

@ -167,6 +167,15 @@ func (bot *CQBot) tempMessageEvent(c *client.QQClient, m *message.TempMessage) {
func (bot *CQBot) groupMutedEvent(c *client.QQClient, e *client.GroupMuteEvent) {
g := c.FindGroup(e.GroupCode)
if e.TargetUin == 0 {
if e.Time != 0 {
log.Infof("群 %v 被 %v 开启全员禁言.",
formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin)))
} else {
log.Infof("群 %v 被 %v 解除全员禁言.",
formatGroupName(g), formatMemberName(g.FindMember(e.OperatorUin)))
}
} else {
if e.Time > 0 {
log.Infof("群 %v 内 %v 被 %v 禁言了 %v 秒.",
formatGroupName(g), formatMemberName(g.FindMember(e.TargetUin)), formatMemberName(g.FindMember(e.OperatorUin)), e.Time)
@ -174,6 +183,8 @@ func (bot *CQBot) groupMutedEvent(c *client.QQClient, e *client.GroupMuteEvent)
log.Infof("群 %v 内 %v 被 %v 解除禁言.",
formatGroupName(g), formatMemberName(g.FindMember(e.TargetUin)), formatMemberName(g.FindMember(e.OperatorUin)))
}
}
bot.dispatchEventMessage(MSG{
"post_type": "notice",
"duration": e.Time,
@ -184,10 +195,10 @@ func (bot *CQBot) groupMutedEvent(c *client.QQClient, e *client.GroupMuteEvent)
"user_id": e.TargetUin,
"time": time.Now().Unix(),
"sub_type": func() string {
if e.Time > 0 {
return "ban"
}
if e.Time == 0 {
return "lift_ban"
}
return "ban"
}(),
})
}
@ -271,12 +282,16 @@ 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)
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,
})
@ -392,7 +407,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",
@ -409,7 +423,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",
@ -476,6 +489,26 @@ func (bot *CQBot) checkMedia(e []message.IMessageElement) {
}), 0644)
}
i.Filename = filename
case *message.GroupImageElement:
filename := hex.EncodeToString(i.Md5) + ".image"
if !global.PathExists(path.Join(global.IMAGE_PATH, filename)) {
_ = ioutil.WriteFile(path.Join(global.IMAGE_PATH, filename), binary.NewWriterF(func(w *binary.Writer) {
w.Write(i.Md5)
w.WriteUInt32(uint32(i.Size))
w.WriteString(filename)
w.WriteString(i.Url)
}), 0644)
}
case *message.FriendImageElement:
filename := hex.EncodeToString(i.Md5) + ".image"
if !global.PathExists(path.Join(global.IMAGE_PATH, filename)) {
_ = ioutil.WriteFile(path.Join(global.IMAGE_PATH, filename), binary.NewWriterF(func(w *binary.Writer) {
w.Write(i.Md5)
w.WriteUInt32(uint32(0)) // 发送时会调用url, 大概没事
w.WriteString(filename)
w.WriteString(i.Url)
}), 0644)
}
case *message.VoiceElement:
i.Name = strings.ReplaceAll(i.Name, "{", "")
i.Name = strings.ReplaceAll(i.Name, "}", "")

View File

@ -380,9 +380,9 @@ Type: `tts`
| `filename` | string | 图片文件原名 |
| `url` | string | 图片下载地址 |
### 获取消息
### 获取消息
终结点: `/get_group_msg`
终结点: `/get_msg`
参数
@ -398,7 +398,7 @@ Type: `tts`
| `real_id` | int32 | 消息真实id |
| `sender` | object | 发送者 |
| `time` | int32 | 发送时间 |
| `content` | message | 消息内容 |
| `message` | message | 消息内容 |
### 获取合并转发内容
@ -500,6 +500,147 @@ Type: `tts`
| `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 |
### 获取群文件系统信息
终结点: `/get_group_file_system_info`
**参数**
| 字段 | 类型 | 说明 |
| ------------ | ------ | ------ |
| `group_id` | int64 | 群号 |
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `file_count` | int32 | 文件总数 |
| `limit_count` | int32 | 文件上限 |
| `used_space` | int64 | 已使用空间 |
| `total_space` | int64 | 空间上限 |
### 获取群根目录文件列表
> `File``Folder` 对象信息请参考最下方
终结点: `/get_group_root_files`
**参数**
| 字段 | 类型 | 说明 |
| ------------ | ------ | ------ |
| `group_id` | int64 | 群号 |
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `files` | File[] | 文件列表 |
| `folders` | Folder[] | 文件夹列表 |
### 获取群子目录文件列表
> `File``Folder` 对象信息请参考最下方
终结点: `/get_group_files_by_folder`
**参数**
| 字段 | 类型 | 说明 |
| ------------ | ------ | ------ |
| `group_id` | int64 | 群号 |
| `folder_id` | string | 文件夹ID 参考 `Folder` 对象 |
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `files` | File[] | 文件列表 |
| `folders` | Folder[] | 文件夹列表 |
### 获取群文件资源链接
> `File``Folder` 对象信息请参考最下方
终结点: `/get_group_file_url`
**参数**
| 字段 | 类型 | 说明 |
| ------------ | ------ | ------ |
| `group_id` | int64 | 群号 |
| `file_id` | string | 文件ID 参考 `File` 对象 |
| `busid` | int32 | 文件类型 参考 `File` 对象 |
**响应数据**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `url` | string | 文件下载链接 |
**File**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `file_id` | string | 文件ID |
| `file_name` | string | 文件名 |
| `busid` | int32 | 文件类型 |
| `file_size` | int64 | 文件大小 |
| `upload_time` | int64 | 上传时间 |
| `dead_time` | int64 | 过期时间,永久文件恒为0 |
| `modify_time` | int64 | 最后修改时间 |
| `download_times` | int32 | 下载次数 |
| `uploader` | int64 | 上传者ID |
| `uploader_name` | string | 上传者名字 |
**Folder**
| 字段 | 类型 | 说明 |
| ---------- | ----------------- | -------- |
| `folder_id` | string | 文件夹ID |
| `folder_name` | string | 文件名 |
| `create_time` | int64 | 创建时间 |
| `creator` | int64 | 创建者 |
| `creator_name` | string | 创建者名字 |
| `total_file_count` | int32 | 子文件数量 |
## 事件

View File

@ -131,7 +131,7 @@ func DefaultConfig() *JsonConfig {
},
WebUi: &GoCqWebUi{
Enabled: true,
Host: "0.0.0.0",
Host: "127.0.0.1",
WebInput: false,
WebUiPort: 9999,
},

View 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
}

View File

@ -2,6 +2,9 @@ package global
import (
"github.com/tidwall/gjson"
"math"
"regexp"
"strconv"
"strings"
)
@ -48,3 +51,22 @@ func EnsureBool(p interface{}, defaultVal bool) bool {
}
return defaultVal
}
// VersionNameCompare 检查版本名是否需要更新, 仅适用于 go-cqhttp 的版本命名规则
// 例: v0.9.29-fix2 == v0.9.29-fix2 -> false
// v0.9.29-fix1 < v0.9.29-fix2 -> true
// v0.9.29-fix2 > v0.9.29-fix1 -> false
// v0.9.29-fix2 < v0.9.30 -> true
func VersionNameCompare(current, remote string) bool {
sp := regexp.MustCompile(`[0-9]\d*`)
cur := sp.FindAllStringSubmatch(current, -1)
re := sp.FindAllStringSubmatch(remote, -1)
for i := 0; i < int(math.Min(float64(len(cur)), float64(len(re)))); i++ {
curSub, _ := strconv.Atoi(cur[i][0])
reSub, _ := strconv.Atoi(re[i][0])
if curSub < reSub {
return true
}
}
return len(cur) < len(re)
}

4
go.mod
View File

@ -3,10 +3,10 @@ module github.com/Mrs4s/go-cqhttp
go 1.14
require (
github.com/Mrs4s/MiraiGo v0.0.0-20201017083749-517ddcd50b8d
github.com/Mrs4s/MiraiGo v0.0.0-20201105120358-ca72d542ca72
github.com/gin-gonic/gin v1.6.3
github.com/gorilla/websocket v1.4.2
github.com/guonaihong/gout v0.1.2
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/pkg/errors v0.9.1 // indirect

26
go.sum
View File

@ -1,13 +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-20201013050256-7b392cacdb79 h1:t9PK37mnl5tbilG+FMUY1hZujoDjFr8iO8upwYHww5c=
github.com/Mrs4s/MiraiGo v0.0.0-20201013050256-7b392cacdb79/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
github.com/Mrs4s/MiraiGo v0.0.0-20201016033322-0922b058ff56 h1:vcXOLG+W/c56EWOwA8btrHMEGBMwFgLUZli0Jh1axzg=
github.com/Mrs4s/MiraiGo v0.0.0-20201016033322-0922b058ff56/go.mod h1:cwYPI2uq6nxNbx0nA6YuAKF1V5szSs6FPlGVLQvRUlo=
github.com/Mrs4s/MiraiGo v0.0.0-20201017083749-517ddcd50b8d h1:f59SuqT0RVy6T9nAg6zTNfnzkvdgLdGqkNKu/AfiPU4=
github.com/Mrs4s/MiraiGo v0.0.0-20201017083749-517ddcd50b8d/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/Mrs4s/MiraiGo v0.0.0-20201105120358-ca72d542ca72 h1:aiKVmrgZHXARnO6AYODwFf1JvTZr6OCl2pohepkkYKc=
github.com/Mrs4s/MiraiGo v0.0.0-20201105120358-ca72d542ca72/go.mod h1:pAsWtMIwqkBXr5DkUpTIHoWQJNduVnX9WSBPmPvkuCs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -40,8 +34,8 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -53,8 +47,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/guonaihong/gout v0.1.2 h1:TR2XCRopGgJdj231IayEoeavgbznFXzzzcZVdT/hG10=
github.com/guonaihong/gout v0.1.2/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA=
github.com/guonaihong/gout v0.1.3 h1:BIiV6nnsA+R6dIB1P33uhCM8+TVAG3zHrXGZad7hDc8=
github.com/guonaihong/gout v0.1.3/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@ -108,13 +102,6 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/wdvxdr1123/go-silk v0.0.0-20201007123416-b982fd3d91d6 h1:lX18MCdNzT2zIi7K02x4C5cPkDXpL+wCb1YTAMXjLWQ=
github.com/wdvxdr1123/go-silk v0.0.0-20201007123416-b982fd3d91d6/go.mod h1:5q9LFlBr+yX/J8Jd/9wHdXwkkjFkNyQIS7kX2Lgx/Zs=
github.com/xujiajun/gorouter v1.2.0/go.mod h1:yJrIta+bTNpBM/2UT8hLOaEAFckO+m/qmR3luMIQygM=
github.com/xujiajun/mmap-go v1.0.1 h1:7Se7ss1fLPPRW+ePgqGpCkfGIZzJV6JPq9Wq9iv/WHc=
github.com/xujiajun/mmap-go v1.0.1/go.mod h1:CNN6Sw4SL69Sui00p0zEzcZKbt+5HtEnYUsc6BKKRMg=
github.com/xujiajun/nutsdb v0.5.0 h1:j/jM3Zw7Chg8WK7bAcKR0Xr7Mal47U1oJAMgySfDn9E=
github.com/xujiajun/nutsdb v0.5.0/go.mod h1:owdwN0tW084RxEodABLbO7h4Z2s9WiAjZGZFhRh0/1Q=
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b h1:jKG9OiL4T4xQN3IUrhUpc1tG+HfDXppkgVcrAiiaI/0=
github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b/go.mod h1:AZd87GYJlUzl82Yab2kTjx1EyXSQCAfZDhpTo1SQC4k=
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189 h1:4UJw9if55Fu3HOwbfcaQlJ27p3oeJU2JZqoeT3ITJQk=
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189/go.mod h1:rIrm5geMiBhPQkdfUm8gDFi/WiHneOp1i9KjmJqc+9I=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -135,7 +122,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

29
main.go
View File

@ -7,6 +7,8 @@ import (
"encoding/json"
"fmt"
"github.com/Mrs4s/go-cqhttp/server"
"github.com/guonaihong/gout"
"github.com/tidwall/gjson"
"io"
"io/ioutil"
"os"
@ -245,7 +247,7 @@ func main() {
conf.WebUi.WebUiPort = 9999
}
if conf.WebUi.Host == "" {
conf.WebUi.Host = "0.0.0.0"
conf.WebUi.Host = "127.0.0.1"
}
confErr := conf.Save("config.json")
if confErr != nil {
@ -253,6 +255,7 @@ func main() {
}
b := server.WebServer.Run(fmt.Sprintf("%s:%d", conf.WebUi.Host, conf.WebUi.WebUiPort), cli)
c := server.Console
go checkUpdate()
signal.Notify(c, os.Interrupt, os.Kill)
<-c
b.Release()
@ -282,3 +285,27 @@ func DecryptPwd(ePwd string, key []byte) string {
}
return string(tea.Decrypt(encrypted))
}
func checkUpdate() {
log.Infof("正在检查更新.")
if coolq.Version == "unknown" {
log.Warnf("检查更新失败: 使用的 Actions 测试版或自编译版本.")
return
}
var res string
if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases").BindBody(&res).Do(); err != nil {
log.Warnf("检查更新失败: %v", err)
return
}
detail := gjson.Parse(res)
if len(detail.Array()) < 1 {
return
}
info := detail.Array()[0]
if global.VersionNameCompare(coolq.Version, info.Get("tag_name").Str) {
log.Infof("当前有更新的 go-cqhttp 可供更新, 请前往 https://github.com/Mrs4s/go-cqhttp/releases 下载.")
log.Infof("当前版本: %v 最新版本: %v", coolq.Version, info.Get("tag_name").Str)
return
}
log.Infof("检查更新完成. 当前已运行最新版本.")
}

View File

@ -183,7 +183,11 @@ func (s *webServer) Dologin() {
os.Exit(0)
return
case client.OtherLoginError, client.UnknownLoginError:
log.Warnf("登录失败: %v", rsp.ErrorMessage)
msg := rsp.ErrorMessage
if strings.Contains(msg, "版本") {
msg = "密码错误或账号被冻结"
}
log.Warnf("登录失败: %v", msg)
log.Infof("按 Enter 继续....")
readLine()
os.Exit(0)
@ -225,8 +229,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",

View File

@ -5,6 +5,7 @@ import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"github.com/guonaihong/gout/dataflow"
"net/http"
"os"
"strconv"
@ -132,11 +133,18 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) {
return h
}()).SetTimeout(time.Second * time.Duration(c.timeout)).F().Retry().Attempt(5).
WaitTime(time.Millisecond * 500).MaxWaitTime(time.Second * 5).
Do()
Func(func(con *dataflow.Context) error {
if con.Error != nil {
log.Warnf("上报Event到 HTTP 服务器 %v 时出现错误: %v 将重试.", c.addr, con.Error)
return con.Error
}
return nil
}).Do()
if err != nil {
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))
}
@ -183,6 +191,29 @@ func (s *httpServer) GetGroupMemberInfo(c *gin.Context) {
c.JSON(200, s.bot.CQGetGroupMemberInfo(gid, uid))
}
func (s *httpServer) GetGroupFileSystemInfo(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
c.JSON(200, s.bot.CQGetGroupFileSystemInfo(gid))
}
func (s *httpServer) GetGroupRootFiles(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
c.JSON(200, s.bot.CQGetGroupRootFiles(gid))
}
func (s *httpServer) GetGroupFilesByFolderId(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
folderId := getParam(c, "folder_id")
c.JSON(200, s.bot.CQGetGroupFilesByFolderId(gid, folderId))
}
func (s *httpServer) GetGroupFileUrl(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
fid := getParam(c, "file_id")
busid, _ := strconv.ParseInt(getParam(c, "busid"), 10, 32)
c.JSON(200, s.bot.CQGetGroupFileUrl(gid, fid, int32(busid)))
}
func (s *httpServer) SendMessage(c *gin.Context) {
if getParam(c, "message_type") == "private" {
s.SendPrivateMessage(c)
@ -317,6 +348,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)))
@ -447,6 +482,18 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){
"get_group_member_info": func(s *httpServer, c *gin.Context) {
s.GetGroupMemberInfo(c)
},
"get_group_file_system_info": func(s *httpServer, c *gin.Context) {
s.GetGroupFileSystemInfo(c)
},
"get_group_root_files": func(s *httpServer, c *gin.Context) {
s.GetGroupRootFiles(c)
},
"get_group_files_by_folder": func(s *httpServer, c *gin.Context) {
s.GetGroupFilesByFolderId(c)
},
"get_group_file_url": func(s *httpServer, c *gin.Context) {
s.GetGroupFileUrl(c)
},
"send_msg": func(s *httpServer, c *gin.Context) {
s.SendMessage(c)
},
@ -504,6 +551,9 @@ var httpApi = map[string]func(s *httpServer, c *gin.Context){
"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)
},

View File

@ -495,6 +495,21 @@ 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_group_file_system_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupFileSystemInfo(p.Get("group_id").Int())
},
"get_group_root_files": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupRootFiles(p.Get("group_id").Int())
},
"get_group_files_by_folder": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupFilesByFolderId(p.Get("group_id").Int(), p.Get("folder_id").Str)
},
"get_group_file_url": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetGroupFileUrl(p.Get("group_id").Int(), p.Get("file_id").Str, int32(p.Get("busid").Int()))
},
"_get_vip_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVipInfo(p.Get("user_id").Int())
},