mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-06-30 11:53:25 +00:00
Compare commits
47 Commits
v0.9.31-fi
...
v0.9.33
Author | SHA1 | Date | |
---|---|---|---|
dfeadef1a2 | |||
b23f68e746 | |||
c5a5f71664 | |||
6973a10b4b | |||
3468c38fbc | |||
d76bcfb1f0 | |||
716c38bab4 | |||
03518b4823 | |||
09eeff3ce6 | |||
6599bf6aa6 | |||
ffb2faeae7 | |||
71e3e97aeb | |||
dcb708e3e3 | |||
b9fb833af4 | |||
b93df0250d | |||
33d64b6e27 | |||
7f831cf856 | |||
7a713c9327 | |||
28d536a3af | |||
375fdc8dca | |||
d1c6053df8 | |||
143d5ef8ab | |||
439c3422fb | |||
2c7b56a79c | |||
1549ef4a32 | |||
4ad684061b | |||
c7e6457e9e | |||
9d5842f09b | |||
b6f3c300ab | |||
2057e769da | |||
0ea85e2fab | |||
36b081eeec | |||
2a044a62d2 | |||
e0ffb98665 | |||
861bcf30b1 | |||
56d7815f6a | |||
59934982b9 | |||
09c4801b56 | |||
f1f58b4072 | |||
86c2f3cb11 | |||
03c3340954 | |||
64b1a223cc | |||
b2be595fb8 | |||
22225f2b74 | |||
eb3d7434cc | |||
8f7f207891 | |||
83e0aaa0f8 |
@ -2,14 +2,15 @@ FROM golang:1.15.5-alpine AS builder
|
|||||||
|
|
||||||
RUN go env -w GO111MODULE=auto \
|
RUN go env -w GO111MODULE=auto \
|
||||||
&& go env -w CGO_ENABLED=0 \
|
&& go env -w CGO_ENABLED=0 \
|
||||||
&& mkdir /build
|
&& go env -w GOPROXY=https://goproxy.cn,direct
|
||||||
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
COPY ./ .
|
COPY ./ .
|
||||||
|
|
||||||
RUN cd /build \
|
RUN set -ex \
|
||||||
&& go build -ldflags "-s -w -extldflags '-static'" -o cqhttp
|
&& cd /build \
|
||||||
|
&& go build -ldflags "-s -w -extldflags '-static'" -o cqhttp
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
- [x] 消息撤回事件
|
- [x] 消息撤回事件
|
||||||
- [x] 解析/发送 回复消息
|
- [x] 解析/发送 回复消息
|
||||||
- [x] 解析/发送 合并转发
|
- [x] 解析/发送 合并转发
|
||||||
- [ ] 使用代理请求网络图片
|
- [x] 使用代理请求网络图片
|
||||||
|
|
||||||
#### 实现
|
#### 实现
|
||||||
<details>
|
<details>
|
||||||
|
144
coolq/api.go
144
coolq/api.go
@ -58,7 +58,7 @@ func (bot *CQBot) CQGetGroupList(noCache bool) MSG {
|
|||||||
func (bot *CQBot) CQGetGroupInfo(groupId int64) MSG {
|
func (bot *CQBot) CQGetGroupInfo(groupId int64) MSG {
|
||||||
group := bot.Client.FindGroup(groupId)
|
group := bot.Client.FindGroup(groupId)
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"group_id": group.Code,
|
"group_id": group.Code,
|
||||||
@ -72,13 +72,13 @@ func (bot *CQBot) CQGetGroupInfo(groupId int64) MSG {
|
|||||||
func (bot *CQBot) CQGetGroupMemberList(groupId int64, noCache bool) MSG {
|
func (bot *CQBot) CQGetGroupMemberList(groupId int64, noCache bool) MSG {
|
||||||
group := bot.Client.FindGroup(groupId)
|
group := bot.Client.FindGroup(groupId)
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
if noCache {
|
if noCache {
|
||||||
t, err := bot.Client.GetGroupMembers(group)
|
t, err := bot.Client.GetGroupMembers(group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("刷新群 %v 成员列表失败: %v", groupId, err)
|
log.Warnf("刷新群 %v 成员列表失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "GET_MEMBERS_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
group.Members = t
|
group.Members = t
|
||||||
}
|
}
|
||||||
@ -93,11 +93,11 @@ func (bot *CQBot) CQGetGroupMemberList(groupId int64, noCache bool) MSG {
|
|||||||
func (bot *CQBot) CQGetGroupMemberInfo(groupId, userId int64) MSG {
|
func (bot *CQBot) CQGetGroupMemberInfo(groupId, userId int64) MSG {
|
||||||
group := bot.Client.FindGroup(groupId)
|
group := bot.Client.FindGroup(groupId)
|
||||||
if group == nil {
|
if group == nil {
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
member := group.FindMember(userId)
|
member := group.FindMember(userId)
|
||||||
if member == nil {
|
if member == nil {
|
||||||
return Failed(102)
|
return Failed(100, "MEMBER_NOT_FOUND", "群员不存在")
|
||||||
}
|
}
|
||||||
return OK(convertGroupMemberInfo(groupId, member))
|
return OK(convertGroupMemberInfo(groupId, member))
|
||||||
}
|
}
|
||||||
@ -106,7 +106,7 @@ func (bot *CQBot) CQGetGroupFileSystemInfo(groupId int64) MSG {
|
|||||||
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(fs)
|
return OK(fs)
|
||||||
}
|
}
|
||||||
@ -115,12 +115,12 @@ func (bot *CQBot) CQGetGroupRootFiles(groupId int64) MSG {
|
|||||||
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
files, folders, err := fs.Root()
|
files, folders, err := fs.Root()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群 %v 根目录文件失败: %v", groupId, err)
|
log.Errorf("获取群 %v 根目录文件失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"files": files,
|
"files": files,
|
||||||
@ -132,12 +132,12 @@ func (bot *CQBot) CQGetGroupFilesByFolderId(groupId int64, folderId string) MSG
|
|||||||
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
fs, err := bot.Client.GetGroupFileSystem(groupId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
log.Errorf("获取群 %v 文件系统信息失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
files, folders, err := fs.GetFilesByFolder(folderId)
|
files, folders, err := fs.GetFilesByFolder(folderId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群 %v 根目录 %v 子文件失败: %v", groupId, folderId, err)
|
log.Errorf("获取群 %v 根目录 %v 子文件失败: %v", groupId, folderId, err)
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"files": files,
|
"files": files,
|
||||||
@ -148,7 +148,7 @@ func (bot *CQBot) CQGetGroupFilesByFolderId(groupId int64, folderId string) MSG
|
|||||||
func (bot *CQBot) CQGetGroupFileUrl(groupId int64, fileId string, busId int32) MSG {
|
func (bot *CQBot) CQGetGroupFileUrl(groupId int64, fileId string, busId int32) MSG {
|
||||||
url := bot.Client.GetGroupFileUrl(groupId, fileId, busId)
|
url := bot.Client.GetGroupFileUrl(groupId, fileId, busId)
|
||||||
if url == "" {
|
if url == "" {
|
||||||
return Failed(100)
|
return Failed(100, "FILE_SYSTEM_API_ERROR")
|
||||||
}
|
}
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"url": url,
|
"url": url,
|
||||||
@ -158,7 +158,7 @@ func (bot *CQBot) CQGetGroupFileUrl(groupId int64, fileId string, busId int32) M
|
|||||||
func (bot *CQBot) CQGetWordSlices(content string) MSG {
|
func (bot *CQBot) CQGetWordSlices(content string) MSG {
|
||||||
slices, err := bot.Client.GetWordSegmentation(content)
|
slices, err := bot.Client.GetWordSegmentation(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100)
|
return Failed(100, "WORD_SEGMENTATION_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
for i := 0; i < len(slices); i++ {
|
for i := 0; i < len(slices); i++ {
|
||||||
slices[i] = strings.ReplaceAll(slices[i], "\u0000", "")
|
slices[i] = strings.ReplaceAll(slices[i], "\u0000", "")
|
||||||
@ -188,7 +188,7 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, i interface{}, autoEscape bo
|
|||||||
fixAt(elem)
|
fixAt(elem)
|
||||||
mid := bot.SendGroupMessage(groupId, &message.SendingMessage{Elements: elem})
|
mid := bot.SendGroupMessage(groupId, &message.SendingMessage{Elements: elem})
|
||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考输出")
|
||||||
}
|
}
|
||||||
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, limitedString(m.String()), mid)
|
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, limitedString(m.String()), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
@ -204,7 +204,7 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, i interface{}, autoEscape bo
|
|||||||
}
|
}
|
||||||
if str == "" {
|
if str == "" {
|
||||||
log.Warnf("群消息发送失败: 信息为空. MSG: %v", i)
|
log.Warnf("群消息发送失败: 信息为空. MSG: %v", i)
|
||||||
return Failed(100)
|
return Failed(100, "EMPTY_MSG_ERROR", "消息为空")
|
||||||
}
|
}
|
||||||
var elem []message.IMessageElement
|
var elem []message.IMessageElement
|
||||||
if autoEscape {
|
if autoEscape {
|
||||||
@ -215,7 +215,7 @@ func (bot *CQBot) CQSendGroupMessage(groupId int64, i interface{}, autoEscape bo
|
|||||||
fixAt(elem)
|
fixAt(elem)
|
||||||
mid := bot.SendGroupMessage(groupId, &message.SendingMessage{Elements: elem})
|
mid := bot.SendGroupMessage(groupId, &message.SendingMessage{Elements: elem})
|
||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考输出")
|
||||||
}
|
}
|
||||||
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, limitedString(str), mid)
|
log.Infof("发送群 %v(%v) 的消息: %v (%v)", groupId, groupId, limitedString(str), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
@ -312,7 +312,7 @@ func (bot *CQBot) CQSendPrivateMessage(userId int64, i interface{}, autoEscape b
|
|||||||
elem := bot.ConvertObjectMessage(m, true)
|
elem := bot.ConvertObjectMessage(m, true)
|
||||||
mid := bot.SendPrivateMessage(userId, &message.SendingMessage{Elements: elem})
|
mid := bot.SendPrivateMessage(userId, &message.SendingMessage{Elements: elem})
|
||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考输出")
|
||||||
}
|
}
|
||||||
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, limitedString(m.String()), mid)
|
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, limitedString(m.String()), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
@ -327,7 +327,7 @@ func (bot *CQBot) CQSendPrivateMessage(userId int64, i interface{}, autoEscape b
|
|||||||
str = s
|
str = s
|
||||||
}
|
}
|
||||||
if str == "" {
|
if str == "" {
|
||||||
return Failed(100)
|
return Failed(100, "EMPTY_MSG_ERROR", "消息为空")
|
||||||
}
|
}
|
||||||
var elem []message.IMessageElement
|
var elem []message.IMessageElement
|
||||||
if autoEscape {
|
if autoEscape {
|
||||||
@ -337,7 +337,7 @@ func (bot *CQBot) CQSendPrivateMessage(userId int64, i interface{}, autoEscape b
|
|||||||
}
|
}
|
||||||
mid := bot.SendPrivateMessage(userId, &message.SendingMessage{Elements: elem})
|
mid := bot.SendPrivateMessage(userId, &message.SendingMessage{Elements: elem})
|
||||||
if mid == -1 {
|
if mid == -1 {
|
||||||
return Failed(100)
|
return Failed(100, "SEND_MSG_API_ERROR", "请参考输出")
|
||||||
}
|
}
|
||||||
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, limitedString(str), mid)
|
log.Infof("发送好友 %v(%v) 的消息: %v (%v)", userId, userId, limitedString(str), mid)
|
||||||
return OK(MSG{"message_id": mid})
|
return OK(MSG{"message_id": mid})
|
||||||
@ -351,7 +351,7 @@ func (bot *CQBot) CQSetGroupCard(groupId, userId int64, card string) MSG {
|
|||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_special_title-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E7%BB%84%E4%B8%93%E5%B1%9E%E5%A4%B4%E8%A1%94
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_special_title-%E8%AE%BE%E7%BD%AE%E7%BE%A4%E7%BB%84%E4%B8%93%E5%B1%9E%E5%A4%B4%E8%A1%94
|
||||||
@ -362,7 +362,7 @@ func (bot *CQBot) CQSetGroupSpecialTitle(groupId, userId int64, title string) MS
|
|||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *CQBot) CQSetGroupName(groupId int64, name string) MSG {
|
func (bot *CQBot) CQSetGroupName(groupId int64, name string) MSG {
|
||||||
@ -370,7 +370,7 @@ func (bot *CQBot) CQSetGroupName(groupId int64, name string) MSG {
|
|||||||
g.UpdateName(name)
|
g.UpdateName(name)
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *CQBot) CQSetGroupMemo(groupId int64, msg string) MSG {
|
func (bot *CQBot) CQSetGroupMemo(groupId int64, msg string) MSG {
|
||||||
@ -378,18 +378,18 @@ func (bot *CQBot) CQSetGroupMemo(groupId int64, msg string) MSG {
|
|||||||
g.UpdateMemo(msg)
|
g.UpdateMemo(msg)
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_kick-%E7%BE%A4%E7%BB%84%E8%B8%A2%E4%BA%BA
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_kick-%E7%BE%A4%E7%BB%84%E8%B8%A2%E4%BA%BA
|
||||||
func (bot *CQBot) CQSetGroupKick(groupId, userId int64, msg string) MSG {
|
func (bot *CQBot) CQSetGroupKick(groupId, userId int64, msg string, block bool) MSG {
|
||||||
if g := bot.Client.FindGroup(groupId); g != nil {
|
if g := bot.Client.FindGroup(groupId); g != nil {
|
||||||
if m := g.FindMember(userId); m != nil {
|
if m := g.FindMember(userId); m != nil {
|
||||||
m.Kick(msg)
|
m.Kick(msg, block)
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_ban-%E7%BE%A4%E7%BB%84%E5%8D%95%E4%BA%BA%E7%A6%81%E8%A8%80
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_ban-%E7%BE%A4%E7%BB%84%E5%8D%95%E4%BA%BA%E7%A6%81%E8%A8%80
|
||||||
@ -400,7 +400,7 @@ func (bot *CQBot) CQSetGroupBan(groupId, userId int64, duration uint32) MSG {
|
|||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_whole_ban-%E7%BE%A4%E7%BB%84%E5%85%A8%E5%91%98%E7%A6%81%E8%A8%80
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_whole_ban-%E7%BE%A4%E7%BB%84%E5%85%A8%E5%91%98%E7%A6%81%E8%A8%80
|
||||||
@ -409,7 +409,7 @@ func (bot *CQBot) CQSetGroupWholeBan(groupId int64, enable bool) MSG {
|
|||||||
g.MuteAll(enable)
|
g.MuteAll(enable)
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_leave-%E9%80%80%E5%87%BA%E7%BE%A4%E7%BB%84
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_group_leave-%E9%80%80%E5%87%BA%E7%BE%A4%E7%BB%84
|
||||||
@ -418,14 +418,14 @@ func (bot *CQBot) CQSetGroupLeave(groupId int64) MSG {
|
|||||||
g.Quit()
|
g.Quit()
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82
|
// https://cqhttp.cc/docs/4.15/#/API?id=set_friend_add_request-%E5%A4%84%E7%90%86%E5%8A%A0%E5%A5%BD%E5%8F%8B%E8%AF%B7%E6%B1%82
|
||||||
func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) MSG {
|
func (bot *CQBot) CQProcessFriendRequest(flag string, approve bool) MSG {
|
||||||
req, ok := bot.friendReqCache.Load(flag)
|
req, ok := bot.friendReqCache.Load(flag)
|
||||||
if !ok {
|
if !ok {
|
||||||
return Failed(100)
|
return Failed(100, "FLAG_NOT_FOUND", "FLAG不存在")
|
||||||
}
|
}
|
||||||
if approve {
|
if approve {
|
||||||
req.(*client.NewFriendRequest).Accept()
|
req.(*client.NewFriendRequest).Accept()
|
||||||
@ -440,14 +440,14 @@ func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bo
|
|||||||
msgs, err := bot.Client.GetGroupSystemMessages()
|
msgs, err := bot.Client.GetGroupSystemMessages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("获取群系统消息失败: %v", err)
|
log.Errorf("获取群系统消息失败: %v", err)
|
||||||
return Failed(100)
|
return Failed(100, "SYSTEM_MSG_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
if subType == "add" {
|
if subType == "add" {
|
||||||
for _, req := range msgs.JoinRequests {
|
for _, req := range msgs.JoinRequests {
|
||||||
if strconv.FormatInt(req.RequestId, 10) == flag {
|
if strconv.FormatInt(req.RequestId, 10) == flag {
|
||||||
if req.Checked {
|
if req.Checked {
|
||||||
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
|
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
|
||||||
return Failed(100)
|
return Failed(100, "FLAG_HAS_BEEN_CHECKED", "消息已被处理")
|
||||||
}
|
}
|
||||||
if approve {
|
if approve {
|
||||||
req.Accept()
|
req.Accept()
|
||||||
@ -462,7 +462,7 @@ func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bo
|
|||||||
if strconv.FormatInt(req.RequestId, 10) == flag {
|
if strconv.FormatInt(req.RequestId, 10) == flag {
|
||||||
if req.Checked {
|
if req.Checked {
|
||||||
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
|
log.Errorf("处理群系统消息失败: 无法操作已处理的消息.")
|
||||||
return Failed(100)
|
return Failed(100, "FLAG_HAS_BEEN_CHECKED", "消息已被处理")
|
||||||
}
|
}
|
||||||
if approve {
|
if approve {
|
||||||
req.Accept()
|
req.Accept()
|
||||||
@ -474,23 +474,29 @@ func (bot *CQBot) CQProcessGroupRequest(flag, subType, reason string, approve bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Errorf("处理群系统消息失败: 消息 %v 不存在.", flag)
|
log.Errorf("处理群系统消息失败: 消息 %v 不存在.", flag)
|
||||||
return Failed(100)
|
return Failed(100, "FLAG_NOT_FOUND", "FLAG不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://cqhttp.cc/docs/4.15/#/API?id=delete_msg-%E6%92%A4%E5%9B%9E%E6%B6%88%E6%81%AF
|
// 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 {
|
func (bot *CQBot) CQDeleteMessage(messageId int32) MSG {
|
||||||
msg := bot.GetMessage(messageId)
|
msg := bot.GetMessage(messageId)
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
return Failed(100)
|
return Failed(100, "MESSAGE_NOT_FOUND", "消息不存在")
|
||||||
}
|
}
|
||||||
if _, ok := msg["group"]; ok {
|
if _, ok := msg["group"]; ok {
|
||||||
bot.Client.RecallGroupMessage(msg["group"].(int64), msg["message-id"].(int32), msg["internal-id"].(int32))
|
if err := bot.Client.RecallGroupMessage(msg["group"].(int64), msg["message-id"].(int32), msg["internal-id"].(int32)); err != nil {
|
||||||
|
log.Warnf("撤回 %v 失败: %v", messageId, err)
|
||||||
|
return Failed(100, "RECALL_API_ERROR", err.Error())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if msg["sender"].(message.Sender).Uin != bot.Client.Uin {
|
if msg["sender"].(message.Sender).Uin != bot.Client.Uin {
|
||||||
log.Warnf("撤回 %v 失败: 好友会话无法撤回对方消息.")
|
log.Warnf("撤回 %v 失败: 好友会话无法撤回对方消息.", messageId)
|
||||||
return Failed(100)
|
return Failed(100, "CANNOT_RECALL_FRIEND_MSG", "无法撤回对方消息")
|
||||||
|
}
|
||||||
|
if err := bot.Client.RecallPrivateMessage(msg["target"].(int64), int64(msg["time"].(int32)), msg["message-id"].(int32), msg["internal-id"].(int32)); err != nil {
|
||||||
|
log.Warnf("撤回 %v 失败: %v", messageId, err)
|
||||||
|
return Failed(100, "RECALL_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
bot.Client.RecallPrivateMessage(msg["target"].(int64), int64(msg["time"].(int32)), msg["message-id"].(int32), msg["internal-id"].(int32))
|
|
||||||
}
|
}
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
@ -499,17 +505,17 @@ func (bot *CQBot) CQDeleteMessage(messageId int32) MSG {
|
|||||||
func (bot *CQBot) CQSetGroupAdmin(groupId, userId int64, enable bool) MSG {
|
func (bot *CQBot) CQSetGroupAdmin(groupId, userId int64, enable bool) MSG {
|
||||||
group := bot.Client.FindGroup(groupId)
|
group := bot.Client.FindGroup(groupId)
|
||||||
if group == nil || group.OwnerUin != bot.Client.Uin {
|
if group == nil || group.OwnerUin != bot.Client.Uin {
|
||||||
return Failed(100)
|
return Failed(100, "PERMISSION_DENIED", "群不存在或权限不足")
|
||||||
}
|
}
|
||||||
mem := group.FindMember(userId)
|
mem := group.FindMember(userId)
|
||||||
if mem == nil {
|
if mem == nil {
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_MEMBER_NOT_FOUND", "群成员不存在")
|
||||||
}
|
}
|
||||||
mem.SetAdmin(enable)
|
mem.SetAdmin(enable)
|
||||||
t, err := bot.Client.GetGroupMembers(group)
|
t, err := bot.Client.GetGroupMembers(group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("刷新群 %v 成员列表失败: %v", groupId, err)
|
log.Warnf("刷新群 %v 成员列表失败: %v", groupId, err)
|
||||||
return Failed(100)
|
return Failed(100, "GET_MEMBERS_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
group.Members = t
|
group.Members = t
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
@ -518,7 +524,7 @@ func (bot *CQBot) CQSetGroupAdmin(groupId, userId int64, enable bool) MSG {
|
|||||||
func (bot *CQBot) CQGetVipInfo(userId int64) MSG {
|
func (bot *CQBot) CQGetVipInfo(userId int64) MSG {
|
||||||
vip, err := bot.Client.GetVipInfo(userId)
|
vip, err := bot.Client.GetVipInfo(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100)
|
return Failed(100, "VIP_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
msg := MSG{
|
msg := MSG{
|
||||||
"user_id": vip.Uin,
|
"user_id": vip.Uin,
|
||||||
@ -591,7 +597,7 @@ func (bot *CQBot) CQGetGroupHonorInfo(groupId int64, t string) MSG {
|
|||||||
func (bot *CQBot) CQGetStrangerInfo(userId int64) MSG {
|
func (bot *CQBot) CQGetStrangerInfo(userId int64) MSG {
|
||||||
info, err := bot.Client.GetSummaryInfo(userId)
|
info, err := bot.Client.GetSummaryInfo(userId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Failed(100)
|
return Failed(100, "SUMMARY_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"user_id": info.Uin,
|
"user_id": info.Uin,
|
||||||
@ -639,7 +645,7 @@ func (bot *CQBot) CQHandleQuickOperation(context, operation gjson.Result) MSG {
|
|||||||
bot.CQDeleteMessage(int32(context.Get("message_id").Int()))
|
bot.CQDeleteMessage(int32(context.Get("message_id").Int()))
|
||||||
}
|
}
|
||||||
if operation.Get("kick").Bool() && !isAnonymous {
|
if operation.Get("kick").Bool() && !isAnonymous {
|
||||||
bot.CQSetGroupKick(context.Get("group_id").Int(), context.Get("user_id").Int(), "")
|
bot.CQSetGroupKick(context.Get("group_id").Int(), context.Get("user_id").Int(), "", operation.Get("reject_add_request").Bool())
|
||||||
}
|
}
|
||||||
if operation.Get("ban").Bool() {
|
if operation.Get("ban").Bool() {
|
||||||
var duration uint32 = 30 * 60
|
var duration uint32 = 30 * 60
|
||||||
@ -686,14 +692,15 @@ func (bot *CQBot) CQGetImage(file string) MSG {
|
|||||||
}
|
}
|
||||||
msg["file"] = local
|
msg["file"] = local
|
||||||
return OK(msg)
|
return OK(msg)
|
||||||
|
} else {
|
||||||
|
return Failed(100, "LOAD_FILE_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return Failed(100)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *CQBot) CQGetForwardMessage(resId string) MSG {
|
func (bot *CQBot) CQGetForwardMessage(resId string) MSG {
|
||||||
m := bot.Client.GetForwardMessage(resId)
|
m := bot.Client.GetForwardMessage(resId)
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return Failed(100)
|
return Failed(100, "MSG_NOT_FOUND", "消息不存在")
|
||||||
}
|
}
|
||||||
r := make([]MSG, 0)
|
r := make([]MSG, 0)
|
||||||
for _, n := range m.Nodes {
|
for _, n := range m.Nodes {
|
||||||
@ -715,20 +722,27 @@ func (bot *CQBot) CQGetForwardMessage(resId string) MSG {
|
|||||||
func (bot *CQBot) CQGetMessage(messageId int32) MSG {
|
func (bot *CQBot) CQGetMessage(messageId int32) MSG {
|
||||||
msg := bot.GetMessage(messageId)
|
msg := bot.GetMessage(messageId)
|
||||||
if msg == nil {
|
if msg == nil {
|
||||||
return Failed(100)
|
return Failed(100, "MSG_NOT_FOUND", "消息不存在")
|
||||||
}
|
}
|
||||||
sender := msg["sender"].(message.Sender)
|
sender := msg["sender"].(message.Sender)
|
||||||
_, group := msg["group"]
|
gid, isGroup := msg["group"]
|
||||||
|
raw := msg["message"].(string)
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"message_id": messageId,
|
"message_id": messageId,
|
||||||
"real_id": msg["message-id"],
|
"real_id": msg["message-id"],
|
||||||
"group": group,
|
"group": isGroup,
|
||||||
|
"group_id": gid,
|
||||||
"sender": MSG{
|
"sender": MSG{
|
||||||
"user_id": sender.Uin,
|
"user_id": sender.Uin,
|
||||||
"nickname": sender.Nickname,
|
"nickname": sender.Nickname,
|
||||||
},
|
},
|
||||||
"time": msg["time"],
|
"time": msg["time"],
|
||||||
"message": msg["message"],
|
"message": ToFormattedMessage(bot.ConvertStringMessage(raw, isGroup), func() int64 {
|
||||||
|
if isGroup {
|
||||||
|
return gid.(int64)
|
||||||
|
}
|
||||||
|
return sender.Uin
|
||||||
|
}(), false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,7 +750,7 @@ func (bot *CQBot) CQGetGroupSystemMessages() MSG {
|
|||||||
msg, err := bot.Client.GetGroupSystemMessages()
|
msg, err := bot.Client.GetGroupSystemMessages()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("获取群系统消息失败: %v", err)
|
log.Warnf("获取群系统消息失败: %v", err)
|
||||||
return Failed(100)
|
return Failed(100, "SYSTEM_MSG_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(msg)
|
return OK(msg)
|
||||||
}
|
}
|
||||||
@ -753,12 +767,12 @@ func (bot *CQBot) CQOcrImage(imageId string) MSG {
|
|||||||
img, err := bot.makeImageElem(map[string]string{"file": imageId}, true)
|
img, err := bot.makeImageElem(map[string]string{"file": imageId}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("load image error: %v", err)
|
log.Warnf("load image error: %v", err)
|
||||||
return Failed(100)
|
return Failed(100, "LOAD_FILE_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
rsp, err := bot.Client.ImageOcr(img)
|
rsp, err := bot.Client.ImageOcr(img)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("ocr image error: %v", err)
|
log.Warnf("ocr image error: %v", err)
|
||||||
return Failed(100)
|
return Failed(100, "OCR_API_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
return OK(rsp)
|
return OK(rsp)
|
||||||
}
|
}
|
||||||
@ -773,14 +787,15 @@ func (bot *CQBot) CQSetGroupPortrait(groupId int64, file, cache string) MSG {
|
|||||||
img, err := global.FindFile(file, cache, global.IMAGE_PATH)
|
img, err := global.FindFile(file, cache, global.IMAGE_PATH)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("set group portrait error: %v", err)
|
log.Warnf("set group portrait error: %v", err)
|
||||||
return Failed(100)
|
return Failed(100, "LOAD_FILE_ERROR", err.Error())
|
||||||
}
|
}
|
||||||
g.UpdateGroupHeadPortrait(img)
|
g.UpdateGroupHeadPortrait(img)
|
||||||
return OK(nil)
|
return OK(nil)
|
||||||
}
|
}
|
||||||
return Failed(100)
|
return Failed(100, "GROUP_NOT_FOUND", "群聊不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_status-%E8%8E%B7%E5%8F%96%E8%BF%90%E8%A1%8C%E7%8A%B6%E6%80%81
|
||||||
func (bot *CQBot) CQGetStatus() MSG {
|
func (bot *CQBot) CQGetStatus() MSG {
|
||||||
return OK(MSG{
|
return OK(MSG{
|
||||||
"app_initialized": true,
|
"app_initialized": true,
|
||||||
@ -788,7 +803,8 @@ func (bot *CQBot) CQGetStatus() MSG {
|
|||||||
"plugins_good": nil,
|
"plugins_good": nil,
|
||||||
"app_good": true,
|
"app_good": true,
|
||||||
"online": bot.Client.Online,
|
"online": bot.Client.Online,
|
||||||
"good": true,
|
"good": bot.Client.Online,
|
||||||
|
"stat": bot.Client.GetStatistics(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,6 +828,8 @@ func (bot *CQBot) CQGetVersionInfo() MSG {
|
|||||||
return 1
|
return 1
|
||||||
case client.AndroidWatch:
|
case client.AndroidWatch:
|
||||||
return 2
|
return 2
|
||||||
|
case client.MacOS:
|
||||||
|
return 3
|
||||||
default:
|
default:
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
@ -823,8 +841,16 @@ func OK(data interface{}) MSG {
|
|||||||
return MSG{"data": data, "retcode": 0, "status": "ok"}
|
return MSG{"data": data, "retcode": 0, "status": "ok"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Failed(code int) MSG {
|
func Failed(code int, msg ...string) MSG {
|
||||||
return MSG{"data": nil, "retcode": code, "status": "failed"}
|
m := ""
|
||||||
|
w := ""
|
||||||
|
if len(msg) > 0 {
|
||||||
|
m = msg[0]
|
||||||
|
}
|
||||||
|
if len(msg) > 1 {
|
||||||
|
w = msg[1]
|
||||||
|
}
|
||||||
|
return MSG{"data": nil, "retcode": code, "msg": m, "wording": w, "status": "failed"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertGroupMemberInfo(groupId int64, m *client.GroupMemberInfo) MSG {
|
func convertGroupMemberInfo(groupId int64, m *client.GroupMemberInfo) MSG {
|
||||||
|
@ -3,7 +3,6 @@ package coolq
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/gob"
|
"encoding/gob"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"path"
|
"path"
|
||||||
@ -17,10 +16,13 @@ import (
|
|||||||
"github.com/Mrs4s/MiraiGo/message"
|
"github.com/Mrs4s/MiraiGo/message"
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
|
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
type CQBot struct {
|
type CQBot struct {
|
||||||
Client *client.QQClient
|
Client *client.QQClient
|
||||||
|
|
||||||
|
161
coolq/cqcode.go
161
coolq/cqcode.go
@ -1,6 +1,7 @@
|
|||||||
package coolq
|
package coolq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
@ -9,9 +10,9 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"math"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -23,9 +24,11 @@ import (
|
|||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/*
|
||||||
var matchReg = regexp.MustCompile(`\[CQ:\w+?.*?]`)
|
var matchReg = regexp.MustCompile(`\[CQ:\w+?.*?]`)
|
||||||
var typeReg = regexp.MustCompile(`\[CQ:(\w+)`)
|
var typeReg = regexp.MustCompile(`\[CQ:(\w+)`)
|
||||||
var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
|
var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
|
||||||
|
*/
|
||||||
|
|
||||||
var IgnoreInvalidCQCode = false
|
var IgnoreInvalidCQCode = false
|
||||||
|
|
||||||
@ -183,13 +186,37 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
|
|||||||
"data": map[string]string{"file": o.Filename, "url": o.Url},
|
"data": map[string]string{"file": o.Filename, "url": o.Url},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case *message.GroupImageElement:
|
||||||
|
if ur {
|
||||||
|
m = MSG{
|
||||||
|
"type": "image",
|
||||||
|
"data": map[string]string{"file": hex.EncodeToString(o.Md5) + ".image"},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = MSG{
|
||||||
|
"type": "image",
|
||||||
|
"data": map[string]string{"file": hex.EncodeToString(o.Md5) + ".image", "url": CQCodeEscapeText(o.Url)},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *message.FriendImageElement:
|
||||||
|
if ur {
|
||||||
|
m = MSG{
|
||||||
|
"type": "image",
|
||||||
|
"data": map[string]string{"file": hex.EncodeToString(o.Md5) + ".image"},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m = MSG{
|
||||||
|
"type": "image",
|
||||||
|
"data": map[string]string{"file": hex.EncodeToString(o.Md5) + ".image", "url": CQCodeEscapeText(o.Url)},
|
||||||
|
}
|
||||||
|
}
|
||||||
case *message.GroupFlashImgElement:
|
case *message.GroupFlashImgElement:
|
||||||
return []MSG{MSG{
|
return []MSG{{
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"data": map[string]string{"file": o.Filename, "type": "flash"},
|
"data": map[string]string{"file": o.Filename, "type": "flash"},
|
||||||
}}
|
}}
|
||||||
case *message.FriendFlashImgElement:
|
case *message.FriendFlashImgElement:
|
||||||
return []MSG{MSG{
|
return []MSG{{
|
||||||
"type": "image",
|
"type": "image",
|
||||||
"data": map[string]string{"file": o.Filename, "type": "flash"},
|
"data": map[string]string{"file": o.Filename, "type": "flash"},
|
||||||
}}
|
}}
|
||||||
@ -262,9 +289,17 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st
|
|||||||
r += fmt.Sprintf(`[CQ:image,file=%s,url=%s]`, o.Filename, CQCodeEscapeValue(o.Url))
|
r += fmt.Sprintf(`[CQ:image,file=%s,url=%s]`, o.Filename, CQCodeEscapeValue(o.Url))
|
||||||
}
|
}
|
||||||
case *message.GroupImageElement:
|
case *message.GroupImageElement:
|
||||||
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
|
if ur {
|
||||||
|
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
|
||||||
|
} else {
|
||||||
|
r += fmt.Sprintf("[CQ:image,file=%s,url=%s]", hex.EncodeToString(o.Md5)+".image", CQCodeEscapeText(o.Url))
|
||||||
|
}
|
||||||
case *message.FriendImageElement:
|
case *message.FriendImageElement:
|
||||||
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
|
if ur {
|
||||||
|
r += fmt.Sprintf("[CQ:image,file=%s]", hex.EncodeToString(o.Md5)+".image")
|
||||||
|
} else {
|
||||||
|
r += fmt.Sprintf("[CQ:image,file=%s,url=%s]", hex.EncodeToString(o.Md5)+".image", CQCodeEscapeText(o.Url))
|
||||||
|
}
|
||||||
case *message.GroupFlashImgElement:
|
case *message.GroupFlashImgElement:
|
||||||
return fmt.Sprintf("[CQ:image,type=flash,file=%s]", o.Filename)
|
return fmt.Sprintf("[CQ:image,type=flash,file=%s]", o.Filename)
|
||||||
case *message.FriendFlashImgElement:
|
case *message.FriendFlashImgElement:
|
||||||
@ -283,30 +318,70 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bot *CQBot) ConvertStringMessage(m string, group bool) (r []message.IMessageElement) {
|
func (bot *CQBot) ConvertStringMessage(msg string, group bool) (r []message.IMessageElement) {
|
||||||
i := matchReg.FindAllStringSubmatchIndex(m, -1)
|
index := 0
|
||||||
si := 0
|
stat := 0
|
||||||
for _, idx := range i {
|
rMsg := []rune(msg)
|
||||||
if idx[0] > si {
|
var tempText, cqCode []rune
|
||||||
text := m[si:idx[0]]
|
hasNext := func() bool {
|
||||||
r = append(r, message.NewText(CQCodeUnescapeText(text)))
|
return index < len(rMsg)
|
||||||
|
}
|
||||||
|
next := func() rune {
|
||||||
|
r := rMsg[index]
|
||||||
|
index++
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
move := func(steps int) {
|
||||||
|
index += steps
|
||||||
|
}
|
||||||
|
peekN := func(count int) string {
|
||||||
|
lastIdx := int(math.Min(float64(index+count), float64(len(rMsg))))
|
||||||
|
return string(rMsg[index:lastIdx])
|
||||||
|
}
|
||||||
|
isCQCodeBegin := func(r rune) bool {
|
||||||
|
return r == '[' && peekN(3) == "CQ:"
|
||||||
|
}
|
||||||
|
saveTempText := func() {
|
||||||
|
if len(tempText) != 0 {
|
||||||
|
r = append(r, message.NewText(CQCodeUnescapeValue(string(tempText))))
|
||||||
}
|
}
|
||||||
code := m[idx[0]:idx[1]]
|
tempText = []rune{}
|
||||||
si = idx[1]
|
cqCode = []rune{}
|
||||||
t := typeReg.FindAllStringSubmatch(code, -1)[0][1]
|
}
|
||||||
ps := paramReg.FindAllStringSubmatch(code, -1)
|
saveCQCode := func() {
|
||||||
d := make(map[string]string)
|
defer func() {
|
||||||
for _, p := range ps {
|
cqCode = []rune{}
|
||||||
d[p[1]] = CQCodeUnescapeValue(p[2])
|
tempText = []rune{}
|
||||||
|
}()
|
||||||
|
reader := strings.NewReader(string(cqCode))
|
||||||
|
buf := bufio.NewReader(reader)
|
||||||
|
t, _ := buf.ReadString(',')
|
||||||
|
t = t[0 : len(t)-1]
|
||||||
|
params := make(map[string]string)
|
||||||
|
for buf.Buffered() > 0 {
|
||||||
|
p, _ := buf.ReadString(',')
|
||||||
|
if strings.HasSuffix(p, ",") {
|
||||||
|
p = p[0 : len(p)-1]
|
||||||
|
}
|
||||||
|
p = strings.TrimSpace(p)
|
||||||
|
if p == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
data := strings.SplitN(p, "=", 2)
|
||||||
|
if len(data) == 2 {
|
||||||
|
params[data[0]] = data[1]
|
||||||
|
} else {
|
||||||
|
params[p] = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if t == "reply" {
|
if t == "reply" { // reply 特殊处理
|
||||||
if len(r) > 0 {
|
if len(r) > 0 {
|
||||||
if _, ok := r[0].(*message.ReplyElement); ok {
|
if _, ok := r[0].(*message.ReplyElement); ok {
|
||||||
log.Warnf("警告: 一条信息只能包含一个 Reply 元素.")
|
log.Warnf("警告: 一条信息只能包含一个 Reply 元素.")
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mid, err := strconv.Atoi(d["id"])
|
mid, err := strconv.Atoi(params["id"])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
org := bot.GetMessage(int32(mid))
|
org := bot.GetMessage(int32(mid))
|
||||||
if org != nil {
|
if org != nil {
|
||||||
@ -318,19 +393,20 @@ func (bot *CQBot) ConvertStringMessage(m string, group bool) (r []message.IMessa
|
|||||||
Elements: bot.ConvertStringMessage(org["message"].(string), group),
|
Elements: bot.ConvertStringMessage(org["message"].(string), group),
|
||||||
},
|
},
|
||||||
}, r...)
|
}, r...)
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elem, err := bot.ToElement(t, d, group)
|
elem, err := bot.ToElement(t, params, group)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
org := "[" + string(cqCode) + "]"
|
||||||
if !IgnoreInvalidCQCode {
|
if !IgnoreInvalidCQCode {
|
||||||
log.Warnf("转换CQ码 %v 到MiraiGo Element时出现错误: %v 将原样发送.", code, err)
|
log.Warnf("转换CQ码 %v 时出现错误: %v 将原样发送.", org, err)
|
||||||
r = append(r, message.NewText(code))
|
r = append(r, message.NewText(org))
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("转换CQ码 %v 到MiraiGo Element时出现错误: %v 将忽略.", code, err)
|
log.Warnf("转换CQ码 %v 时出现错误: %v 将忽略.", org, err)
|
||||||
}
|
}
|
||||||
continue
|
return
|
||||||
}
|
}
|
||||||
switch i := elem.(type) {
|
switch i := elem.(type) {
|
||||||
case message.IMessageElement:
|
case message.IMessageElement:
|
||||||
@ -339,9 +415,32 @@ func (bot *CQBot) ConvertStringMessage(m string, group bool) (r []message.IMessa
|
|||||||
r = append(r, i...)
|
r = append(r, i...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if si != len(m) {
|
for hasNext() {
|
||||||
r = append(r, message.NewText(CQCodeUnescapeText(m[si:])))
|
ch := next()
|
||||||
|
switch stat {
|
||||||
|
case 0:
|
||||||
|
if isCQCodeBegin(ch) {
|
||||||
|
saveTempText()
|
||||||
|
tempText = append(tempText, []rune("[CQ:")...)
|
||||||
|
move(3)
|
||||||
|
stat = 1
|
||||||
|
} else {
|
||||||
|
tempText = append(tempText, ch)
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if isCQCodeBegin(ch) {
|
||||||
|
move(-1)
|
||||||
|
stat = 0
|
||||||
|
} else if ch == ']' {
|
||||||
|
saveCQCode()
|
||||||
|
stat = 0
|
||||||
|
} else {
|
||||||
|
cqCode = append(cqCode, ch)
|
||||||
|
tempText = append(tempText, ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
saveTempText()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,14 +697,12 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (m interf
|
|||||||
case "xml":
|
case "xml":
|
||||||
resId := d["resid"]
|
resId := d["resid"]
|
||||||
template := CQCodeEscapeValue(d["data"])
|
template := CQCodeEscapeValue(d["data"])
|
||||||
//println(template)
|
|
||||||
i, _ := strconv.ParseInt(resId, 10, 64)
|
i, _ := strconv.ParseInt(resId, 10, 64)
|
||||||
msg := message.NewRichXml(template, i)
|
msg := message.NewRichXml(template, i)
|
||||||
return msg, nil
|
return msg, nil
|
||||||
case "json":
|
case "json":
|
||||||
resId := d["resid"]
|
resId := d["resid"]
|
||||||
i, _ := strconv.ParseInt(resId, 10, 64)
|
i, _ := strconv.ParseInt(resId, 10, 64)
|
||||||
log.Warnf("json msg=%s", d["data"])
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
//默认情况下走小程序通道
|
//默认情况下走小程序通道
|
||||||
msg := message.NewLightApp(CQCodeUnescapeValue(d["data"]))
|
msg := message.NewLightApp(CQCodeUnescapeValue(d["data"]))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
| 参数名 | 类型 | 说明 |
|
| 参数名 | 类型 | 说明 |
|
||||||
| ------------ | ------ | --------------------------- |
|
| ------------ | ------ | --------------------------- |
|
||||||
| access_token | string | 校验口令,config.json中配置 |
|
| access_token | string | 校验口令,config.hjson中配置 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ method: `POST` formdata
|
|||||||
|
|
||||||
### admin/do_config_json
|
### admin/do_config_json
|
||||||
|
|
||||||
> 直接修改 config.json配置
|
> 直接修改 config.hjson配置
|
||||||
|
|
||||||
method: `POST` formdata
|
method: `POST` formdata
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ method: `POST` formdata
|
|||||||
|
|
||||||
| 参数名 | 类型 | 说明 |
|
| 参数名 | 类型 | 说明 |
|
||||||
| ------ | ------ | ----------------------------------- |
|
| ------ | ------ | ----------------------------------- |
|
||||||
| json | string | 完整的config.json的配合,json字符串 |
|
| json | string | 完整的config.hjson的配合,json字符串 |
|
||||||
|
|
||||||
|
|
||||||
返回:
|
返回:
|
||||||
@ -228,7 +228,7 @@ method: `POST` formdata
|
|||||||
|
|
||||||
### admin/get_config_json
|
### admin/get_config_json
|
||||||
|
|
||||||
> 获取当前 config.json配置
|
> 获取当前 config.hjson配置
|
||||||
|
|
||||||
method: `GET`
|
method: `GET`
|
||||||
|
|
||||||
@ -247,5 +247,5 @@ method: `GET`
|
|||||||
|
|
||||||
| 参数名 | 类型 | 说明 |
|
| 参数名 | 类型 | 说明 |
|
||||||
| ------ | ------ | ----------------------------------- |
|
| ------ | ------ | ----------------------------------- |
|
||||||
| config | string | 完整的config.json的配合,json字符串 |
|
| config | string | 完整的config.hjson的配合,json字符串 |
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# 配置
|
# 配置
|
||||||
|
|
||||||
go-cqhttp 包含 `config.json` 和 `device.json` 两个配置文件, 其中 `config.json` 为运行配置 `device.json` 为虚拟设备信息.
|
go-cqhttp 包含 `config.hjson` 和 `device.json` 两个配置文件, 其中 `config.json` 为运行配置 `device.json` 为虚拟设备信息.
|
||||||
|
|
||||||
## 从原CQHTTP导入配置
|
## 从原CQHTTP导入配置
|
||||||
|
|
||||||
|
205
docs/cqhttp.md
205
docs/cqhttp.md
@ -486,24 +486,24 @@ Type: `tts`
|
|||||||
|
|
||||||
**参数**
|
**参数**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ------- | ------ | ------ |
|
| ------- | ------ | ------ |
|
||||||
| `image` | string | 图片ID |
|
| `image` | string | 图片ID |
|
||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------- | --------------- | ------- |
|
| ---------- | --------------- | ------- |
|
||||||
| `texts` | TextDetection[] | OCR结果 |
|
| `texts` | TextDetection[] | OCR结果 |
|
||||||
| `language` | string | 语言 |
|
| `language` | string | 语言 |
|
||||||
|
|
||||||
**TextDetection**
|
**TextDetection**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ------------- | ------- | ------ |
|
| ------------- | ------- | ------ |
|
||||||
| `text` | string | 文本 |
|
| `text` | string | 文本 |
|
||||||
| `confidence` | int32 | 置信度 |
|
| `confidence` | int32 | 置信度 |
|
||||||
| `coordinates` | vector2 | 坐标 |
|
| `coordinates` | vector2 | 坐标 |
|
||||||
|
|
||||||
|
|
||||||
### 获取群系统消息
|
### 获取群系统消息
|
||||||
@ -512,37 +512,37 @@ Type: `tts`
|
|||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ------------------ | ---------------- | ------------ |
|
| ------------------ | ---------------- | ------------ |
|
||||||
| `invited_requests` | InvitedRequest[] | 邀请消息列表 |
|
| `invited_requests` | InvitedRequest[] | 邀请消息列表 |
|
||||||
| `join_requests` | JoinRequest[] | 进群消息列表 |
|
| `join_requests` | JoinRequest[] | 进群消息列表 |
|
||||||
|
|
||||||
> 注意: 如果列表不存在任何消息, 将返回 `null`
|
> 注意: 如果列表不存在任何消息, 将返回 `null`
|
||||||
|
|
||||||
**InvitedRequest**
|
**InvitedRequest**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| -------------- | ------ | ----------------- |
|
| -------------- | ------ | ----------------- |
|
||||||
| `request_id` | int64 | 请求ID |
|
| `request_id` | int64 | 请求ID |
|
||||||
| `invitor_uin` | int64 | 邀请者 |
|
| `invitor_uin` | int64 | 邀请者 |
|
||||||
| `invitor_nick` | string | 邀请者昵称 |
|
| `invitor_nick` | string | 邀请者昵称 |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
| `group_name` | string | 群名 |
|
| `group_name` | string | 群名 |
|
||||||
| `checked` | bool | 是否已被处理 |
|
| `checked` | bool | 是否已被处理 |
|
||||||
| `actor` | int64 | 处理者, 未处理为0 |
|
| `actor` | int64 | 处理者, 未处理为0 |
|
||||||
|
|
||||||
**JoinRequest**
|
**JoinRequest**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------------- | ------ | ----------------- |
|
| ---------------- | ------ | ----------------- |
|
||||||
| `request_id` | int64 | 请求ID |
|
| `request_id` | int64 | 请求ID |
|
||||||
| `requester_uin` | int64 | 请求者ID |
|
| `requester_uin` | int64 | 请求者ID |
|
||||||
| `requester_nick` | string | 请求者昵称 |
|
| `requester_nick` | string | 请求者昵称 |
|
||||||
| `message` | string | 验证消息 |
|
| `message` | string | 验证消息 |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
| `group_name` | string | 群名 |
|
| `group_name` | string | 群名 |
|
||||||
| `checked` | bool | 是否已被处理 |
|
| `checked` | bool | 是否已被处理 |
|
||||||
| `actor` | int64 | 处理者, 未处理为0 |
|
| `actor` | int64 | 处理者, 未处理为0 |
|
||||||
|
|
||||||
### 获取群文件系统信息
|
### 获取群文件系统信息
|
||||||
|
|
||||||
@ -550,18 +550,18 @@ Type: `tts`
|
|||||||
|
|
||||||
**参数**
|
**参数**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------- | ----- | ---- |
|
| ---------- | ----- | ---- |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ------------- | ----- | ---------- |
|
| ------------- | ----- | ---------- |
|
||||||
| `file_count` | int32 | 文件总数 |
|
| `file_count` | int32 | 文件总数 |
|
||||||
| `limit_count` | int32 | 文件上限 |
|
| `limit_count` | int32 | 文件上限 |
|
||||||
| `used_space` | int64 | 已使用空间 |
|
| `used_space` | int64 | 已使用空间 |
|
||||||
| `total_space` | int64 | 空间上限 |
|
| `total_space` | int64 | 空间上限 |
|
||||||
|
|
||||||
### 获取群根目录文件列表
|
### 获取群根目录文件列表
|
||||||
|
|
||||||
@ -571,16 +571,16 @@ Type: `tts`
|
|||||||
|
|
||||||
**参数**
|
**参数**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------- | ----- | ---- |
|
| ---------- | ----- | ---- |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| --------- | -------- | ---------- |
|
| --------- | -------- | ---------- |
|
||||||
| `files` | File[] | 文件列表 |
|
| `files` | File[] | 文件列表 |
|
||||||
| `folders` | Folder[] | 文件夹列表 |
|
| `folders` | Folder[] | 文件夹列表 |
|
||||||
|
|
||||||
### 获取群子目录文件列表
|
### 获取群子目录文件列表
|
||||||
|
|
||||||
@ -590,17 +590,17 @@ Type: `tts`
|
|||||||
|
|
||||||
**参数**
|
**参数**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ----------- | ------ | --------------------------- |
|
| ----------- | ------ | --------------------------- |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
| `folder_id` | string | 文件夹ID 参考 `Folder` 对象 |
|
| `folder_id` | string | 文件夹ID 参考 `Folder` 对象 |
|
||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| --------- | -------- | ---------- |
|
| --------- | -------- | ---------- |
|
||||||
| `files` | File[] | 文件列表 |
|
| `files` | File[] | 文件列表 |
|
||||||
| `folders` | Folder[] | 文件夹列表 |
|
| `folders` | Folder[] | 文件夹列表 |
|
||||||
|
|
||||||
### 获取群文件资源链接
|
### 获取群文件资源链接
|
||||||
|
|
||||||
@ -610,43 +610,74 @@ Type: `tts`
|
|||||||
|
|
||||||
**参数**
|
**参数**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------- | ------ | ------------------------- |
|
| ---------- | ------ | ------------------------- |
|
||||||
| `group_id` | int64 | 群号 |
|
| `group_id` | int64 | 群号 |
|
||||||
| `file_id` | string | 文件ID 参考 `File` 对象 |
|
| `file_id` | string | 文件ID 参考 `File` 对象 |
|
||||||
| `busid` | int32 | 文件类型 参考 `File` 对象 |
|
| `busid` | int32 | 文件类型 参考 `File` 对象 |
|
||||||
|
|
||||||
**响应数据**
|
**响应数据**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ----- | ------ | ------------ |
|
| ----- | ------ | ------------ |
|
||||||
| `url` | string | 文件下载链接 |
|
| `url` | string | 文件下载链接 |
|
||||||
|
|
||||||
**File**
|
**File**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ---------------- | ------ | ---------------------- |
|
| ---------------- | ------ | ---------------------- |
|
||||||
| `file_id` | string | 文件ID |
|
| `file_id` | string | 文件ID |
|
||||||
| `file_name` | string | 文件名 |
|
| `file_name` | string | 文件名 |
|
||||||
| `busid` | int32 | 文件类型 |
|
| `busid` | int32 | 文件类型 |
|
||||||
| `file_size` | int64 | 文件大小 |
|
| `file_size` | int64 | 文件大小 |
|
||||||
| `upload_time` | int64 | 上传时间 |
|
| `upload_time` | int64 | 上传时间 |
|
||||||
| `dead_time` | int64 | 过期时间,永久文件恒为0 |
|
| `dead_time` | int64 | 过期时间,永久文件恒为0 |
|
||||||
| `modify_time` | int64 | 最后修改时间 |
|
| `modify_time` | int64 | 最后修改时间 |
|
||||||
| `download_times` | int32 | 下载次数 |
|
| `download_times` | int32 | 下载次数 |
|
||||||
| `uploader` | int64 | 上传者ID |
|
| `uploader` | int64 | 上传者ID |
|
||||||
| `uploader_name` | string | 上传者名字 |
|
| `uploader_name` | string | 上传者名字 |
|
||||||
|
|
||||||
**Folder**
|
**Folder**
|
||||||
|
|
||||||
| 字段 | 类型 | 说明 |
|
| 字段 | 类型 | 说明 |
|
||||||
| ------------------ | ------ | ---------- |
|
| ------------------ | ------ | ---------- |
|
||||||
| `folder_id` | string | 文件夹ID |
|
| `folder_id` | string | 文件夹ID |
|
||||||
| `folder_name` | string | 文件名 |
|
| `folder_name` | string | 文件名 |
|
||||||
| `create_time` | int64 | 创建时间 |
|
| `create_time` | int64 | 创建时间 |
|
||||||
| `creator` | int64 | 创建者 |
|
| `creator` | int64 | 创建者 |
|
||||||
| `creator_name` | string | 创建者名字 |
|
| `creator_name` | string | 创建者名字 |
|
||||||
| `total_file_count` | int32 | 子文件数量 |
|
| `total_file_count` | int32 | 子文件数量 |
|
||||||
|
|
||||||
|
### 获取状态
|
||||||
|
|
||||||
|
终结点: `/get_status`
|
||||||
|
|
||||||
|
**响应数据**
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
| --------------- | ---------- | ------------------------------- |
|
||||||
|
| app_initialized | bool | 原 `CQHTTP` 字段, 恒定为 `true` |
|
||||||
|
| app_enabled | bool | 原 `CQHTTP` 字段, 恒定为 `true` |
|
||||||
|
| plugins_good | bool | 原 `CQHTTP` 字段, 恒定为 `true` |
|
||||||
|
| app_good | bool | 原 `CQHTTP` 字段, 恒定为 `true` |
|
||||||
|
| online | bool | 表示BOT是否在线 |
|
||||||
|
| goold | bool | 同 `online` |
|
||||||
|
| stat | Statistics | 运行统计 |
|
||||||
|
|
||||||
|
**Statistics**
|
||||||
|
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
| ---------------- | ------ | ---------------- |
|
||||||
|
| packet_received | uint64 | 收到的数据包总数 |
|
||||||
|
| packet_sent | uint64 | 发送的数据包总数 |
|
||||||
|
| packet_lost | uint32 | 数据包丢失总数 |
|
||||||
|
| message_received | uint64 | 接受信息总数 |
|
||||||
|
| message_sent | uint64 | 发送信息总数 |
|
||||||
|
| disconnect_times | uint32 | TCP链接断开次数 |
|
||||||
|
| lost_times | uint32 | 账号掉线次数 |
|
||||||
|
|
||||||
|
> 注意: 所有统计信息都将在重启后重制
|
||||||
|
|
||||||
## 事件
|
## 事件
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ go-cqhttp 默认生成的文件树如下所示:
|
|||||||
````
|
````
|
||||||
.
|
.
|
||||||
├── go-cqhttp
|
├── go-cqhttp
|
||||||
├── config.json
|
├── config.hjson
|
||||||
├── device.json
|
├── device.json
|
||||||
├── logs
|
├── logs
|
||||||
│ └── xx-xx-xx.log
|
│ └── xx-xx-xx.log
|
||||||
@ -18,7 +18,7 @@ go-cqhttp 默认生成的文件树如下所示:
|
|||||||
| 文件 | 用途 |
|
| 文件 | 用途 |
|
||||||
| ----------- | ------------------- |
|
| ----------- | ------------------- |
|
||||||
| go-cqhttp | go-cqhttp可执行文件 |
|
| go-cqhttp | go-cqhttp可执行文件 |
|
||||||
| config.json | 运行配置文件 |
|
| config.hjson | 运行配置文件 |
|
||||||
| device.json | 虚拟设备配置文件 |
|
| device.json | 虚拟设备配置文件 |
|
||||||
| logs | 日志存放目录 |
|
| logs | 日志存放目录 |
|
||||||
| data | 数据目录 |
|
| data | 数据目录 |
|
||||||
|
@ -28,8 +28,8 @@
|
|||||||
|
|
||||||
1. 双击`go-cqhttp.exe`此时将提示
|
1. 双击`go-cqhttp.exe`此时将提示
|
||||||
```
|
```
|
||||||
[WARNING]: 尝试加载配置文件 config.json 失败: 文件不存在
|
[WARNING]: 尝试加载配置文件 config.hjson 失败: 文件不存在
|
||||||
[INFO]: 默认配置文件已生成,请编辑 config.json 后重启程序.
|
[INFO]: 默认配置文件已生成,请编辑 config.hjson 后重启程序.
|
||||||
```
|
```
|
||||||
2. 参照[config.md](https://github.com/Mrs4s/go-cqhttp/blob/master/docs/config.md)和你所用到的插件的 `README` 填入参数
|
2. 参照[config.md](https://github.com/Mrs4s/go-cqhttp/blob/master/docs/config.md)和你所用到的插件的 `README` 填入参数
|
||||||
3. 再次双击`go-cqhttp.exe`
|
3. 再次双击`go-cqhttp.exe`
|
||||||
@ -79,8 +79,8 @@ enable ws?(Y/n)
|
|||||||
2. `cd`到解压目录
|
2. `cd`到解压目录
|
||||||
3. 输入 `./go-cqhttp`,`Enter`运行 ,此时将提示
|
3. 输入 `./go-cqhttp`,`Enter`运行 ,此时将提示
|
||||||
```
|
```
|
||||||
[WARNING]: 尝试加载配置文件 config.json 失败: 文件不存在
|
[WARNING]: 尝试加载配置文件 config.hjson 失败: 文件不存在
|
||||||
[INFO]: 默认配置文件已生成,请编辑 config.json 后重启程序.
|
[INFO]: 默认配置文件已生成,请编辑 config.hjson 后重启程序.
|
||||||
```
|
```
|
||||||
|
|
||||||
4. 参照[config.md](https://github.com/Mrs4s/go-cqhttp/blob/master/docs/config.md)和你所用到的插件的 `README` 填入参数
|
4. 参照[config.md](https://github.com/Mrs4s/go-cqhttp/blob/master/docs/config.md)和你所用到的插件的 `README` 填入参数
|
||||||
@ -103,6 +103,8 @@ enable ws?(Y/n)
|
|||||||
|
|
||||||
如果出现`{"data":{"message_id":balabala},"retcode":0,"status":"ok"}`则证明已经成功配置HTTP
|
如果出现`{"data":{"message_id":balabala},"retcode":0,"status":"ok"}`则证明已经成功配置HTTP
|
||||||
|
|
||||||
|
*注:请 连 中括号 也替换掉,就像这样:*`http://127.0.0.1:5700/send_private_msg?user_id=10001&message=ffeecoishp`
|
||||||
|
|
||||||
# 进阶指南
|
# 进阶指南
|
||||||
|
|
||||||
## 如何自己构建
|
## 如何自己构建
|
||||||
@ -117,13 +119,11 @@ enable ws?(Y/n)
|
|||||||
|
|
||||||
*注:可以使用*`go env -w GOPROXY=https://goproxy.cn,direct`*来加速国内依赖安装速度*
|
*注:可以使用*`go env -w GOPROXY=https://goproxy.cn,direct`*来加速国内依赖安装速度*
|
||||||
|
|
||||||
*注:此时构建后的文件名为*`go-cqhttp`(Linux)或`go-cqhttp.exe`(Windows)
|
|
||||||
|
|
||||||
## 更新
|
## 更新
|
||||||
|
|
||||||
### 方法一
|
### 方法一
|
||||||
|
|
||||||
从[release] (https://github.com/Mrs4s/go-cqhttp/releases)界面下载最新版本的go-cqhttp
|
从[release](https://github.com/Mrs4s/go-cqhttp/releases)界面下载最新版本的go-cqhttp
|
||||||
并替换之前的版本
|
并替换之前的版本
|
||||||
|
|
||||||
### 方法二
|
### 方法二
|
||||||
|
148
global/config.go
148
global/config.go
@ -1,14 +1,139 @@
|
|||||||
package global
|
package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/hjson/hjson-go"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
|
var DefaultConfigWithComments = `
|
||||||
|
/*
|
||||||
|
go-cqhttp 默认配置文件
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
// QQ号
|
||||||
|
uin: 0
|
||||||
|
// QQ密码
|
||||||
|
password: ""
|
||||||
|
// 是否启用密码加密
|
||||||
|
encrypt_password: false
|
||||||
|
// 加密后的密码, 如未启用密码加密将为空, 请勿随意修改.
|
||||||
|
password_encrypted: ""
|
||||||
|
// 是否启用内置数据库
|
||||||
|
// 启用将会增加10-20MB的内存占用和一定的磁盘空间
|
||||||
|
// 关闭将无法使用 撤回 回复 get_msg 等上下文相关功能
|
||||||
|
enable_db: true
|
||||||
|
// 访问密钥, 强烈推荐在公网的服务器设置
|
||||||
|
access_token: ""
|
||||||
|
// 重连设置
|
||||||
|
relogin: {
|
||||||
|
// 是否启用自动重连
|
||||||
|
// 如不启用掉线后将不会自动重连
|
||||||
|
enabled: true
|
||||||
|
// 重连延迟, 单位秒
|
||||||
|
relogin_delay: 3
|
||||||
|
// 最大重连次数, 0为无限制
|
||||||
|
max_relogin_times: 0
|
||||||
|
}
|
||||||
|
// API限速设置
|
||||||
|
// 该设置为全局生效
|
||||||
|
// 原 cqhttp 虽然启用了 rate_limit 后缀, 但是基本没插件适配
|
||||||
|
// 目前该限速设置为令牌桶算法, 请参考:
|
||||||
|
// https://baike.baidu.com/item/%E4%BB%A4%E7%89%8C%E6%A1%B6%E7%AE%97%E6%B3%95/6597000?fr=aladdin
|
||||||
|
_rate_limit: {
|
||||||
|
// 是否启用限速
|
||||||
|
enabled: false
|
||||||
|
// 令牌回复频率, 单位秒
|
||||||
|
frequency: 1
|
||||||
|
// 令牌桶大小
|
||||||
|
bucket_size: 1
|
||||||
|
}
|
||||||
|
// 是否忽略无效的CQ码
|
||||||
|
// 如果为假将原样发送
|
||||||
|
ignore_invalid_cqcode: false
|
||||||
|
// 是否强制分片发送消息
|
||||||
|
// 分片发送将会带来更快的速度
|
||||||
|
// 但是兼容性会有些问题
|
||||||
|
force_fragmented: false
|
||||||
|
// 心跳频率, 单位秒
|
||||||
|
// -1 为关闭心跳
|
||||||
|
heartbeat_interval: 0
|
||||||
|
// HTTP设置
|
||||||
|
http_config: {
|
||||||
|
// 是否启用正向HTTP服务器
|
||||||
|
enabled: true
|
||||||
|
// 服务端监听地址
|
||||||
|
host: 0.0.0.0
|
||||||
|
// 服务端监听端口
|
||||||
|
port: 5700
|
||||||
|
// 反向HTTP超时时间, 单位秒
|
||||||
|
// 最小值为5,小于5将会忽略本项设置
|
||||||
|
timeout: 0
|
||||||
|
// 反向HTTP POST地址列表
|
||||||
|
// 格式:
|
||||||
|
// {
|
||||||
|
// 地址: secret
|
||||||
|
// }
|
||||||
|
post_urls: {}
|
||||||
|
}
|
||||||
|
// 正向WS设置
|
||||||
|
ws_config: {
|
||||||
|
// 是否启用正向WS服务器
|
||||||
|
enabled: true
|
||||||
|
// 正向WS服务器监听地址
|
||||||
|
host: 0.0.0.0
|
||||||
|
// 正向WS服务器监听端口
|
||||||
|
port: 6700
|
||||||
|
}
|
||||||
|
// 反向WS设置
|
||||||
|
ws_reverse_servers: [
|
||||||
|
// 可以添加多个反向WS推送
|
||||||
|
{
|
||||||
|
// 是否启用该推送
|
||||||
|
enabled: false
|
||||||
|
// 反向WS Universal 地址
|
||||||
|
// 注意 设置了此项地址后下面两项将会被忽略
|
||||||
|
// 留空请使用 ""
|
||||||
|
reverse_url: ws://you_websocket_universal.server
|
||||||
|
// 反向WS API 地址
|
||||||
|
reverse_api_url: ws://you_websocket_api.server
|
||||||
|
// 反向WS Event 地址
|
||||||
|
reverse_event_url: ws://you_websocket_event.server
|
||||||
|
// 重连间隔 单位毫秒
|
||||||
|
reverse_reconnect_interval: 3000
|
||||||
|
}
|
||||||
|
]
|
||||||
|
// 上报数据类型
|
||||||
|
// 可选: string array
|
||||||
|
post_message_format: string
|
||||||
|
// 是否使用服务器下发的新地址进行重连
|
||||||
|
// 注意, 此设置可能导致在海外服务器上连接情况更差
|
||||||
|
use_sso_address: false
|
||||||
|
// 是否启用 DEBUG
|
||||||
|
debug: false
|
||||||
|
// 日志等级
|
||||||
|
log_level: ""
|
||||||
|
// WebUi 设置
|
||||||
|
web_ui: {
|
||||||
|
// 是否启用 WebUi
|
||||||
|
enabled: true
|
||||||
|
// 监听地址
|
||||||
|
host: 127.0.0.1
|
||||||
|
// 监听端口
|
||||||
|
web_ui_port: 9999
|
||||||
|
// 是否接收来自web的输入
|
||||||
|
web_input: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
type JsonConfig struct {
|
type JsonConfig struct {
|
||||||
Uin int64 `json:"uin"`
|
Uin int64 `json:"uin"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@ -28,6 +153,7 @@ type JsonConfig struct {
|
|||||||
} `json:"_rate_limit"`
|
} `json:"_rate_limit"`
|
||||||
IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"`
|
IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"`
|
||||||
ForceFragmented bool `json:"force_fragmented"`
|
ForceFragmented bool `json:"force_fragmented"`
|
||||||
|
ProxyRewrite string `json:"proxy_rewrite"`
|
||||||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||||
HttpConfig *GoCQHttpConfig `json:"http_config"`
|
HttpConfig *GoCQHttpConfig `json:"http_config"`
|
||||||
WSConfig *GoCQWebsocketConfig `json:"ws_config"`
|
WSConfig *GoCQWebsocketConfig `json:"ws_config"`
|
||||||
@ -144,22 +270,30 @@ func Load(p string) *JsonConfig {
|
|||||||
log.Warnf("尝试加载配置文件 %v 失败: 文件不存在", p)
|
log.Warnf("尝试加载配置文件 %v 失败: 文件不存在", p)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
c := JsonConfig{}
|
var dat map[string]interface{}
|
||||||
err := json.Unmarshal([]byte(ReadAllText(p)), &c)
|
var c = JsonConfig{}
|
||||||
|
err := hjson.Unmarshal([]byte(ReadAllText(p)), &dat)
|
||||||
|
if err == nil {
|
||||||
|
b, _ := json.Marshal(dat)
|
||||||
|
err = json.Unmarshal(b, &c)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", p, err)
|
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", p, err)
|
||||||
log.Infoln("原文件已备份")
|
log.Infoln("原文件已备份")
|
||||||
os.Rename(p, p+".backup"+strconv.FormatInt(time.Now().Unix(), 10))
|
_ = os.Rename(p, p+".backup"+strconv.FormatInt(time.Now().Unix(), 10))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *JsonConfig) Save(p string) error {
|
func (c *JsonConfig) Save(p string) error {
|
||||||
data, err := json.MarshalIndent(c, "", "\t")
|
data, err := hjson.MarshalWithOptions(c, hjson.EncoderOptions{
|
||||||
|
Eol: "\n",
|
||||||
|
BracesSameLine: true,
|
||||||
|
IndentBy: " ",
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
WriteAllText(p, string(data))
|
return WriteAllText(p, string(data))
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
@ -43,8 +43,8 @@ func ReadAllText(path string) string {
|
|||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func WriteAllText(path, text string) {
|
func WriteAllText(path, text string) error {
|
||||||
_ = ioutil.WriteFile(path, []byte(text), 0644)
|
return ioutil.WriteFile(path, []byte(text), 0644)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Check(err error) {
|
func Check(err error) {
|
||||||
|
@ -5,7 +5,9 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -14,8 +16,28 @@ import (
|
|||||||
|
|
||||||
var client = &http.Client{
|
var client = &http.Client{
|
||||||
Timeout: time.Second * 15,
|
Timeout: time.Second * 15,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Proxy: func(request *http.Request) (u *url.URL, e error) {
|
||||||
|
if Proxy == "" {
|
||||||
|
return http.ProxyFromEnvironment(request)
|
||||||
|
}
|
||||||
|
return url.Parse(Proxy)
|
||||||
|
},
|
||||||
|
DialContext: (&net.Dialer{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
KeepAlive: 30 * time.Second,
|
||||||
|
DualStack: true,
|
||||||
|
}).DialContext,
|
||||||
|
ForceAttemptHTTP2: true,
|
||||||
|
MaxIdleConns: 100,
|
||||||
|
IdleConnTimeout: 90 * time.Second,
|
||||||
|
TLSHandshakeTimeout: 10 * time.Second,
|
||||||
|
ExpectContinueTimeout: 1 * time.Second,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Proxy string
|
||||||
|
|
||||||
func GetBytes(url string) ([]byte, error) {
|
func GetBytes(url string) ([]byte, error) {
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
6
go.mod
6
go.mod
@ -1,15 +1,17 @@
|
|||||||
module github.com/Mrs4s/go-cqhttp
|
module github.com/Mrs4s/go-cqhttp
|
||||||
|
|
||||||
go 1.14
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20201117154121-989187125900
|
github.com/Mrs4s/MiraiGo v0.0.0-20201202140458-0eb4eb738d31
|
||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/getlantern/go-update v0.0.0-20190510022740-79c495ab728c
|
github.com/getlantern/go-update v0.0.0-20190510022740-79c495ab728c
|
||||||
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 // indirect
|
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9 // indirect
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/guonaihong/gout v0.1.3
|
github.com/guonaihong/gout v0.1.3
|
||||||
|
github.com/hjson/hjson-go v3.1.0+incompatible
|
||||||
|
github.com/json-iterator/go v1.1.10
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||||
github.com/kr/binarydist v0.1.0 // indirect
|
github.com/kr/binarydist v0.1.0 // indirect
|
||||||
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
|
||||||
|
11
go.sum
11
go.sum
@ -1,7 +1,7 @@
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
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/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20201117154121-989187125900 h1:xnx3dH7hgZ/Z4k33EhKzBmQhwASJ5bvsorqPhO0DWbc=
|
github.com/Mrs4s/MiraiGo v0.0.0-20201202140458-0eb4eb738d31 h1:jClElKWovoOzDYmVd16UQc8638d0FvyKCtVj7qF+ej4=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20201117154121-989187125900/go.mod h1:pAsWtMIwqkBXr5DkUpTIHoWQJNduVnX9WSBPmPvkuCs=
|
github.com/Mrs4s/MiraiGo v0.0.0-20201202140458-0eb4eb738d31/go.mod h1:J1zaJWyeX7hQIPpOobqb8opxTNPbguotudPPrHJMoDM=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -67,9 +67,13 @@ github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0U
|
|||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/guonaihong/gout v0.1.3 h1:BIiV6nnsA+R6dIB1P33uhCM8+TVAG3zHrXGZad7hDc8=
|
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/guonaihong/gout v0.1.3/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA=
|
||||||
|
github.com/hjson/hjson-go v3.1.0+incompatible h1:DY/9yE8ey8Zv22bY+mHV1uk2yRy0h8tKhZ77hEdi0Aw=
|
||||||
|
github.com/hjson/hjson-go v3.1.0+incompatible/go.mod h1:qsetwF8NlsTsOTwZTApNlTCerV+b2GjYRRcIk4JMFio=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||||
|
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -86,7 +90,9 @@ github.com/lestrrat-go/strftime v1.0.3/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR7
|
|||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||||
@ -114,7 +120,6 @@ github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFd
|
|||||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
|
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk=
|
||||||
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA=
|
||||||
github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
|
||||||
github.com/tidwall/gjson v1.6.3 h1:aHoiiem0dr7GHkW001T1SMTJ7X5PvyekH5WX0whWGnI=
|
github.com/tidwall/gjson v1.6.3 h1:aHoiiem0dr7GHkW001T1SMTJ7X5PvyekH5WX0whWGnI=
|
||||||
github.com/tidwall/gjson v1.6.3/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
github.com/tidwall/gjson v1.6.3/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
|
||||||
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||||
|
41
main.go
41
main.go
@ -2,10 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -29,12 +27,15 @@ import (
|
|||||||
"github.com/Mrs4s/go-cqhttp/coolq"
|
"github.com/Mrs4s/go-cqhttp/coolq"
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
"github.com/getlantern/go-update"
|
"github.com/getlantern/go-update"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
||||||
"github.com/rifflock/lfshook"
|
"github.com/rifflock/lfshook"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFormatter(&easy.Formatter{
|
log.SetFormatter(&easy.Formatter{
|
||||||
TimestampFormat: "2006-01-02 15:04:05",
|
TimestampFormat: "2006-01-02 15:04:05",
|
||||||
@ -66,7 +67,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
if global.PathExists("cqhttp.json") {
|
if global.PathExists("cqhttp.json") {
|
||||||
log.Info("发现 cqhttp.json 将在五秒后尝试导入配置,按 Ctrl+C 取消.")
|
log.Info("发现 cqhttp.json 将在五秒后尝试导入配置,按 Ctrl+C 取消.")
|
||||||
log.Warn("警告: 该操作会删除 cqhttp.json 并覆盖 config.json 文件.")
|
log.Warn("警告: 该操作会删除 cqhttp.json 并覆盖 config.hjson 文件.")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
conf := global.CQHttpApiConfig{}
|
conf := global.CQHttpApiConfig{}
|
||||||
if err := json.Unmarshal([]byte(global.ReadAllText("cqhttp.json")), &conf); err != nil {
|
if err := json.Unmarshal([]byte(global.ReadAllText("cqhttp.json")), &conf); err != nil {
|
||||||
@ -88,8 +89,8 @@ func init() {
|
|||||||
goConf.ReverseServers[0].ReverseEventUrl = conf.WSReverseEventUrl
|
goConf.ReverseServers[0].ReverseEventUrl = conf.WSReverseEventUrl
|
||||||
goConf.ReverseServers[0].ReverseReconnectInterval = conf.WSReverseReconnectInterval
|
goConf.ReverseServers[0].ReverseReconnectInterval = conf.WSReverseReconnectInterval
|
||||||
}
|
}
|
||||||
if err := goConf.Save("config.json"); err != nil {
|
if err := goConf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
}
|
}
|
||||||
_ = os.Remove("cqhttp.json")
|
_ = os.Remove("cqhttp.json")
|
||||||
}
|
}
|
||||||
@ -122,8 +123,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var conf *global.JsonConfig
|
var conf *global.JsonConfig
|
||||||
if global.PathExists("config.json") || os.Getenv("UIN") == "" {
|
if global.PathExists("config.json") {
|
||||||
conf = global.Load("config.json")
|
conf = global.Load("config.json")
|
||||||
|
_ = conf.Save("config.hjson")
|
||||||
|
_ = os.Remove("config.json")
|
||||||
} else if os.Getenv("UIN") != "" {
|
} else if os.Getenv("UIN") != "" {
|
||||||
log.Infof("将从环境变量加载配置.")
|
log.Infof("将从环境变量加载配置.")
|
||||||
uin, _ := strconv.ParseInt(os.Getenv("UIN"), 10, 64)
|
uin, _ := strconv.ParseInt(os.Getenv("UIN"), 10, 64)
|
||||||
@ -149,19 +152,21 @@ func main() {
|
|||||||
if post != "" {
|
if post != "" {
|
||||||
conf.HttpConfig.PostUrls[post] = os.Getenv("HTTP_SECRET")
|
conf.HttpConfig.PostUrls[post] = os.Getenv("HTTP_SECRET")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
conf = global.Load("config.hjson")
|
||||||
}
|
}
|
||||||
if conf == nil {
|
if conf == nil {
|
||||||
err := global.DefaultConfig().Save("config.json")
|
err := global.WriteAllText("config.hjson", global.DefaultConfigWithComments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("创建默认配置文件时出现错误: %v", err)
|
log.Fatalf("创建默认配置文件时出现错误: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("默认配置文件已生成, 请编辑 config.json 后重启程序.")
|
log.Infof("默认配置文件已生成, 请编辑 config.hjson 后重启程序.")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if conf.Uin == 0 || (conf.Password == "" && conf.PasswordEncrypted == "") {
|
if conf.Uin == 0 || (conf.Password == "" && conf.PasswordEncrypted == "") {
|
||||||
log.Warnf("请修改 config.json 以添加账号密码.")
|
log.Warnf("请修改 config.hjson 以添加账号密码.")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -228,7 +233,7 @@ func main() {
|
|||||||
if encrypted := EncryptPwd(conf.Password, key[:]); encrypted != "" {
|
if encrypted := EncryptPwd(conf.Password, key[:]); encrypted != "" {
|
||||||
conf.Password = ""
|
conf.Password = ""
|
||||||
conf.PasswordEncrypted = encrypted
|
conf.PasswordEncrypted = encrypted
|
||||||
_ = conf.Save("config.json")
|
_ = conf.Save("config.hjson")
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("加密时出现问题.")
|
log.Warnf("加密时出现问题.")
|
||||||
}
|
}
|
||||||
@ -236,19 +241,19 @@ func main() {
|
|||||||
if conf.PasswordEncrypted != "" {
|
if conf.PasswordEncrypted != "" {
|
||||||
if strKey == "" {
|
if strKey == "" {
|
||||||
log.Infof("密码加密已启用, 请输入Key对密码进行解密以继续: (Enter 提交)")
|
log.Infof("密码加密已启用, 请输入Key对密码进行解密以继续: (Enter 提交)")
|
||||||
ctx := context.Background()
|
cancel := make(chan struct{}, 1)
|
||||||
go func(ctx context.Context) {
|
go func() {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-cancel:
|
||||||
return
|
return
|
||||||
case <-time.After(time.Second * 45):
|
case <-time.After(time.Second * 45):
|
||||||
log.Infof("解密key输入超时")
|
log.Infof("解密key输入超时")
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}(ctx)
|
}()
|
||||||
strKey, _ = console.ReadString('\n')
|
strKey, _ = console.ReadString('\n')
|
||||||
ctx.Done()
|
cancel <- struct{}{}
|
||||||
} else {
|
} else {
|
||||||
log.Infof("密码加密已启用, 使用运行时传递的参数进行解密,按 Ctrl+C 取消.")
|
log.Infof("密码加密已启用, 使用运行时传递的参数进行解密,按 Ctrl+C 取消.")
|
||||||
}
|
}
|
||||||
@ -314,10 +319,7 @@ func main() {
|
|||||||
if conf.WebUi.Host == "" {
|
if conf.WebUi.Host == "" {
|
||||||
conf.WebUi.Host = "127.0.0.1"
|
conf.WebUi.Host = "127.0.0.1"
|
||||||
}
|
}
|
||||||
confErr := conf.Save("config.json")
|
global.Proxy = conf.ProxyRewrite
|
||||||
if confErr != nil {
|
|
||||||
log.Error("保存配置文件失败")
|
|
||||||
}
|
|
||||||
b := server.WebServer.Run(fmt.Sprintf("%s:%d", conf.WebUi.Host, conf.WebUi.WebUiPort), cli)
|
b := server.WebServer.Run(fmt.Sprintf("%s:%d", conf.WebUi.Host, conf.WebUi.WebUiPort), cli)
|
||||||
c := server.Console
|
c := server.Console
|
||||||
r := server.Restart
|
r := server.Restart
|
||||||
@ -328,7 +330,6 @@ func main() {
|
|||||||
b.Release()
|
b.Release()
|
||||||
case <-r:
|
case <-r:
|
||||||
log.Info("正在重启中...")
|
log.Info("正在重启中...")
|
||||||
server.HttpServer.ShutDown()
|
|
||||||
defer b.Release()
|
defer b.Release()
|
||||||
restart(arg)
|
restart(arg)
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -19,11 +18,14 @@ import (
|
|||||||
"github.com/Mrs4s/go-cqhttp/coolq"
|
"github.com/Mrs4s/go-cqhttp/coolq"
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
asciiart "github.com/yinghau76/go-ascii-art"
|
asciiart "github.com/yinghau76/go-ascii-art"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||||
|
|
||||||
var WebInput = make(chan string, 1) //长度1,用于阻塞
|
var WebInput = make(chan string, 1) //长度1,用于阻塞
|
||||||
|
|
||||||
var Console = make(chan os.Signal, 1)
|
var Console = make(chan os.Signal, 1)
|
||||||
@ -75,7 +77,7 @@ func (s *webServer) Run(addr string, cli *client.QQClient) *coolq.CQBot {
|
|||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
//开启端口监听
|
//开启端口监听
|
||||||
if s.Conf.WebUi.Enabled {
|
if s.Conf.WebUi != nil && s.Conf.WebUi.Enabled {
|
||||||
log.Infof("Admin API 服务器已启动: %v", addr)
|
log.Infof("Admin API 服务器已启动: %v", addr)
|
||||||
err := s.engine.Run(addr)
|
err := s.engine.Run(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -110,6 +112,7 @@ func (s *webServer) Dologin() {
|
|||||||
cli := s.Cli
|
cli := s.Cli
|
||||||
cli.AllowSlider = true
|
cli.AllowSlider = true
|
||||||
rsp, err := cli.Login()
|
rsp, err := cli.Login()
|
||||||
|
count := 0
|
||||||
for {
|
for {
|
||||||
global.Check(err)
|
global.Check(err)
|
||||||
var text string
|
var text string
|
||||||
@ -130,7 +133,7 @@ func (s *webServer) Dologin() {
|
|||||||
_ = ioutil.WriteFile("captcha.jpg", rsp.CaptchaImage, 0644)
|
_ = ioutil.WriteFile("captcha.jpg", rsp.CaptchaImage, 0644)
|
||||||
img, _, _ := image.Decode(bytes.NewReader(rsp.CaptchaImage))
|
img, _, _ := image.Decode(bytes.NewReader(rsp.CaptchaImage))
|
||||||
fmt.Println(asciiart.New("image", img).Art)
|
fmt.Println(asciiart.New("image", img).Art)
|
||||||
if conf.WebUi.WebInput {
|
if conf.WebUi != nil && conf.WebUi.WebInput {
|
||||||
log.Warnf("请输入验证码 (captcha.jpg): (http://%s:%d/admin/do_web_write 输入)", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
log.Warnf("请输入验证码 (captcha.jpg): (http://%s:%d/admin/do_web_write 输入)", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
||||||
text = <-WebInput
|
text = <-WebInput
|
||||||
} else {
|
} else {
|
||||||
@ -176,7 +179,7 @@ func (s *webServer) Dologin() {
|
|||||||
return
|
return
|
||||||
case client.UnsafeDeviceError:
|
case client.UnsafeDeviceError:
|
||||||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
||||||
if conf.WebUi.WebInput {
|
if conf.WebUi != nil && conf.WebUi.WebInput {
|
||||||
log.Infof(" (http://%s:%d/admin/do_web_write 确认后继续)....", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
log.Infof(" (http://%s:%d/admin/do_web_write 确认后继续)....", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
||||||
text = <-WebInput
|
text = <-WebInput
|
||||||
} else {
|
} else {
|
||||||
@ -191,6 +194,12 @@ func (s *webServer) Dologin() {
|
|||||||
if strings.Contains(msg, "版本") {
|
if strings.Contains(msg, "版本") {
|
||||||
msg = "密码错误或账号被冻结"
|
msg = "密码错误或账号被冻结"
|
||||||
}
|
}
|
||||||
|
if strings.Contains(msg, "上网环境") && count < 5 {
|
||||||
|
cli.Disconnect()
|
||||||
|
rsp, err = cli.Login()
|
||||||
|
count++
|
||||||
|
continue
|
||||||
|
}
|
||||||
log.Warnf("登录失败: %v", msg)
|
log.Warnf("登录失败: %v", msg)
|
||||||
log.Infof("按 Enter 继续....")
|
log.Infof("按 Enter 继续....")
|
||||||
readLine()
|
readLine()
|
||||||
@ -283,7 +292,7 @@ func GetConf() *global.JsonConfig {
|
|||||||
if JsonConfig != nil {
|
if JsonConfig != nil {
|
||||||
return JsonConfig
|
return JsonConfig
|
||||||
}
|
}
|
||||||
conf := global.Load("config.json")
|
conf := global.Load("config.hjson")
|
||||||
return conf
|
return conf
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -475,9 +484,9 @@ func AdminDoConfigBase(s *webServer, c *gin.Context) {
|
|||||||
conf.EnableDB = false
|
conf.EnableDB = false
|
||||||
}
|
}
|
||||||
conf.AccessToken = c.PostForm("access_token")
|
conf.AccessToken = c.PostForm("access_token")
|
||||||
if err := conf.Save("config.json"); err != nil {
|
if err := conf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
} else {
|
} else {
|
||||||
JsonConfig = nil
|
JsonConfig = nil
|
||||||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||||||
@ -500,9 +509,9 @@ func AdminDoConfigHttp(s *webServer, c *gin.Context) {
|
|||||||
if c.PostForm("post_url") != "" {
|
if c.PostForm("post_url") != "" {
|
||||||
conf.HttpConfig.PostUrls[c.PostForm("post_url")] = c.PostForm("post_secret")
|
conf.HttpConfig.PostUrls[c.PostForm("post_url")] = c.PostForm("post_secret")
|
||||||
}
|
}
|
||||||
if err := conf.Save("config.json"); err != nil {
|
if err := conf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
} else {
|
} else {
|
||||||
JsonConfig = nil
|
JsonConfig = nil
|
||||||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||||||
@ -520,9 +529,9 @@ func AdminDoConfigWs(s *webServer, c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
conf.WSConfig.Enabled = false
|
conf.WSConfig.Enabled = false
|
||||||
}
|
}
|
||||||
if err := conf.Save("config.json"); err != nil {
|
if err := conf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
} else {
|
} else {
|
||||||
JsonConfig = nil
|
JsonConfig = nil
|
||||||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||||||
@ -542,9 +551,9 @@ func AdminDoConfigReverse(s *webServer, c *gin.Context) {
|
|||||||
} else {
|
} else {
|
||||||
conf.ReverseServers[0].Enabled = false
|
conf.ReverseServers[0].Enabled = false
|
||||||
}
|
}
|
||||||
if err := conf.Save("config.json"); err != nil {
|
if err := conf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
} else {
|
} else {
|
||||||
JsonConfig = nil
|
JsonConfig = nil
|
||||||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||||||
@ -557,13 +566,13 @@ func AdminDoConfigJson(s *webServer, c *gin.Context) {
|
|||||||
Json := c.PostForm("json")
|
Json := c.PostForm("json")
|
||||||
err := json.Unmarshal([]byte(Json), &conf)
|
err := json.Unmarshal([]byte(Json), &conf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", "config.json", err)
|
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", "config.hjson", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := conf.Save("config.json"); err != nil {
|
if err := conf.Save("config.hjson"); err != nil {
|
||||||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
log.Fatalf("保存 config.hjson 时出现错误: %v", err)
|
||||||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
c.JSON(200, Failed(502, "保存 config.hjson 时出现错误:"+fmt.Sprintf("%v", err)))
|
||||||
} else {
|
} else {
|
||||||
JsonConfig = nil
|
JsonConfig = nil
|
||||||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||||||
|
@ -308,7 +308,8 @@ func SetGroupKick(s *httpServer, c *gin.Context) {
|
|||||||
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
||||||
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
||||||
msg := getParam(c, "message")
|
msg := getParam(c, "message")
|
||||||
c.JSON(200, s.bot.CQSetGroupKick(gid, uid, msg))
|
block := getParamOrDefault(c, "reject_add_request", "false")
|
||||||
|
c.JSON(200, s.bot.CQSetGroupKick(gid, uid, msg, block == "true"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetGroupBan(s *httpServer, c *gin.Context) {
|
func SetGroupBan(s *httpServer, c *gin.Context) {
|
||||||
|
@ -433,7 +433,7 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
|
|||||||
return bot.CQSetGroupSpecialTitle(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("special_title").Str)
|
return bot.CQSetGroupSpecialTitle(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("special_title").Str)
|
||||||
},
|
},
|
||||||
"set_group_kick": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
"set_group_kick": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQSetGroupKick(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("message").Str)
|
return bot.CQSetGroupKick(p.Get("group_id").Int(), p.Get("user_id").Int(), p.Get("message").Str, p.Get("reject_add_request").Bool())
|
||||||
},
|
},
|
||||||
"set_group_ban": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
"set_group_ban": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
|
||||||
return bot.CQSetGroupBan(p.Get("group_id").Int(), p.Get("user_id").Int(), func() uint32 {
|
return bot.CQSetGroupBan(p.Get("group_id").Int(), p.Get("user_id").Int(), func() uint32 {
|
||||||
|
Reference in New Issue
Block a user