1
0
mirror of https://github.com/Mrs4s/go-cqhttp.git synced 2025-06-30 11:53:25 +00:00

Compare commits

...

72 Commits

Author SHA1 Message Date
a26681a4d9 update post error. 2020-09-07 05:13:38 +08:00
a417ff0881 Merge pull request #245 from scjtqs/master
cq码 添加 cardimage 类型,一种xml的 特殊图片格式,json和xml的格式上报
2020-09-07 05:10:46 +08:00
845b483242 Merge pull request #244 from wdvxdr1123/master
add: api _get_vip_info
2020-09-07 05:10:29 +08:00
da8b0931f1 默认最小宽高调整到 200*200 2020-09-06 14:57:08 +08:00
3dc436b534 docs : EventFilter 2020-09-06 14:47:46 +08:00
6a0f44f6cc add _send_group_notice 2020-09-06 11:53:31 +08:00
5501c6192f Update MiraiGo 2020-09-06 11:12:23 +08:00
ca62f6f591 修改对应的 文档范围 2020-09-06 10:42:18 +08:00
ac5803a539 xml和json消息以及cq码上报支持.
富文本的xml和json的消息识别,依赖miraigo的pr
2020-09-06 10:39:46 +08:00
828ca2ec3c 修复 ios 支持 2020-09-06 01:38:41 +08:00
514f93b527 调整 xml 2020-09-06 01:28:31 +08:00
4d260be76a 调整 xml 2020-09-06 01:19:26 +08:00
793cf2e2b9 修复下Log 2020-09-06 00:27:24 +08:00
2a56475daf 去掉一个调试日志 2020-09-06 00:24:04 +08:00
f9e2130b9f 修复 对本地文件格式的支持 2020-09-06 00:21:24 +08:00
e2073f5371 Merge branch 'master-Mrs4s' into master
* master-Mrs4s:
  feature: send netease with json
  fix: fit onebot
2020-09-05 23:40:24 +08:00
b1fcfc6f97 添加 说明文档 2020-09-05 23:30:43 +08:00
6a14998928 添加 说明文档 2020-09-05 23:29:41 +08:00
24dad3d6f9 fix 2020-09-05 23:19:24 +08:00
b104b21ab9 add: api _get_vip_info 2020-09-05 23:03:08 +08:00
5024cc08a7 暂存 2020-09-05 22:22:57 +08:00
3c73769db3 Merge pull request #243 from wdvxdr1123/master
send netease music with json
2020-09-05 22:08:32 +08:00
d79cb0b536 feature: send netease with json 2020-09-05 18:49:32 +08:00
2b00b49755 fix: fit onebot
适配onebot标准
2020-09-05 17:47:30 +08:00
a77977b12e Merge pull request #7 from Mrs4s/master
2
2020-09-05 11:17:26 +08:00
6565a19aaa fix #238. 2020-09-05 08:16:50 +08:00
a9001d5c9e fix ci. 2020-09-05 08:10:45 +08:00
a991add799 update default heartbeat value. close #232 2020-09-05 08:09:07 +08:00
42434956d9 fix light app. 2020-09-05 08:06:52 +08:00
49e3995129 move reply pos. close #220 2020-09-05 08:02:31 +08:00
8c1770318c Merge pull request #6 from Mrs4s/master
1
2020-09-03 22:57:01 +08:00
7d3265b6d4 Merge pull request #221 from scjtqs/master
初步支持 `[CQ:json]` .
2020-09-03 22:05:05 +08:00
4c65859608 Merge branch 'master' of https://github.com/Mrs4s/go-cqhttp
# Conflicts:
#	coolq/cqcode.go
2020-09-03 20:31:53 +08:00
0100b85fb1 update qq music content. 2020-09-03 18:05:31 +08:00
3bd557d7a0 fmt 2020-09-03 00:37:57 +08:00
05d8e773f2 配合 最新的MiraiGo调整代码 2020-09-03 00:34:20 +08:00
b2f46b4bbe Merge branch 'master' of https://github.com/Mrs4s/go-cqhttp into master 2020-09-03 00:09:14 +08:00
9fa1b7727e Merge pull request #235 from wdvxdr1123/master
feature [cq:music] send qqmusic share with json
2020-09-02 23:18:29 +08:00
9e43d9c2bb change into NewLightApp 2020-09-02 22:52:57 +08:00
ad5e87c4c7 Revert "Auto stash before merge of "master" and "origin/master""
This reverts commit ff8fd92a26.
2020-09-02 22:50:01 +08:00
ff8fd92a26 Auto stash before merge of "master" and "origin/master" 2020-09-02 22:45:17 +08:00
0f96950757 Merge branch 'master' into master 2020-09-02 22:39:17 +08:00
993f05bfa6 feature [cq:music] send qqmusic share with json
用json代替qq音乐的分享
2020-09-02 22:26:56 +08:00
d309a10fba Merge pull request #229 from rMuchan/master
反向WS连接时发送connect元事件
2020-09-02 15:26:24 +08:00
755949fb33 反向WS连接时发送connect元事件 2020-09-02 14:22:56 +08:00
7f103a7f9a Merge pull request #227 from shitianshiwa/master
补充关于“是否强制分片发送群长消息”开关说明
2020-09-01 22:34:05 +08:00
f487d12b83 Update config.md 2020-09-01 21:12:45 +09:00
df1cb3de87 Merge pull request #1 from Mrs4s/master
跟进
2020-09-01 20:55:33 +09:00
7d62db2ec0 Merge pull request #223 from F0ur/master
feat(api): make json response [] instead of null(empty list)
2020-08-31 23:46:27 +08:00
9b5358351f feat(api): make GetFriendList/GetGroupList/GetGroupMemberList/GetForwardMessage json response data as [] instead of null 2020-08-31 22:58:03 +08:00
a048353067 json cq 码 添加 说明 2020-08-31 00:45:36 +08:00
a455aeea39 去掉不需要的方法 2020-08-31 00:36:42 +08:00
710a8588b7 cq:json 消息的初步支持 2020-08-31 00:34:38 +08:00
d25674a9ef json 初步支持 2020-08-30 03:00:18 +08:00
0133944c0b Merge remote-tracking branch 'upstream/master' into master
# Conflicts:
#	global/net.go
2020-08-30 02:43:26 +08:00
bcdbefb355 go fmt 2020-08-30 02:29:29 +08:00
fc18b84d4b 添加 [CQ:json,data={json代码}]的支持 2020-08-30 02:28:01 +08:00
e55b7d846f Merge pull request #219 from Ink-33/master
Fix #218
2020-08-29 22:30:48 +08:00
1f7c4cab50 Update 2020-08-29 22:24:53 +08:00
d35ad66adf 拒绝空Token 2020-08-29 20:24:11 +08:00
047b5208f4 Builder更换为1.14.7 2020-08-29 17:55:08 +08:00
804bd9a711 升级依赖 2020-08-29 17:54:39 +08:00
f569225305 加载配置失败后备份源配置文件
配置结构升级不备份,我配置没了
2020-08-29 17:49:40 +08:00
9c65ff4dcd 尝试修复正向WebSocket下的鉴权panic 2020-08-29 17:24:09 +08:00
d0398f30c6 Revert "Update websocket.go"
This reverts commit 33120b2496.

revert
2020-08-29 17:06:25 +08:00
517e2ea3d4 Merge pull request #1 from Ink-33/patch-1
Update websocket.go
2020-08-29 16:46:14 +08:00
33120b2496 Update websocket.go 2020-08-29 16:44:31 +08:00
38b6fab496 Merge pull request #4 from Mrs4s/master
pull
2020-08-29 16:15:19 +08:00
304b38f6af Merge pull request #213 from ceerRep/patch-1
Fix indent
2020-08-29 02:40:18 +08:00
e8fd57d477 Merge pull request #216 from qianjunakasumi/master
新增多次自动重连 #154
2020-08-29 02:39:27 +08:00
4d376c0518 新增多次自动重连 2020-08-28 23:46:29 +08:00
027aeca622 Fix indent 2020-08-28 15:02:53 +08:00
14 changed files with 701 additions and 233 deletions

View File

@ -1,4 +1,4 @@
FROM golang:1.14.2-alpine AS builder FROM golang:1.14.7-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 \

View File

@ -25,7 +25,7 @@ func (bot *CQBot) CQGetLoginInfo() MSG {
// https://cqhttp.cc/docs/4.15/#/API?id=get_friend_list-%E8%8E%B7%E5%8F%96%E5%A5%BD%E5%8F%8B%E5%88%97%E8%A1%A8 // https://cqhttp.cc/docs/4.15/#/API?id=get_friend_list-%E8%8E%B7%E5%8F%96%E5%A5%BD%E5%8F%8B%E5%88%97%E8%A1%A8
func (bot *CQBot) CQGetFriendList() MSG { func (bot *CQBot) CQGetFriendList() MSG {
var fs []MSG fs := make([]MSG, 0)
for _, f := range bot.Client.FriendList { for _, f := range bot.Client.FriendList {
fs = append(fs, MSG{ fs = append(fs, MSG{
"nickname": f.Nickname, "nickname": f.Nickname,
@ -38,7 +38,7 @@ func (bot *CQBot) CQGetFriendList() MSG {
// https://cqhttp.cc/docs/4.15/#/API?id=get_group_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E5%88%97%E8%A1%A8 // https://cqhttp.cc/docs/4.15/#/API?id=get_group_list-%E8%8E%B7%E5%8F%96%E7%BE%A4%E5%88%97%E8%A1%A8
func (bot *CQBot) CQGetGroupList(noCache bool) MSG { func (bot *CQBot) CQGetGroupList(noCache bool) MSG {
var gs []MSG gs := make([]MSG, 0)
if noCache { if noCache {
_ = bot.Client.ReloadGroupList() _ = bot.Client.ReloadGroupList()
} }
@ -73,7 +73,7 @@ func (bot *CQBot) CQGetGroupMemberList(groupId int64) MSG {
if group == nil { if group == nil {
return Failed(100) return Failed(100)
} }
var members []MSG members := make([]MSG, 0)
for _, m := range group.Members { for _, m := range group.Members {
members = append(members, convertGroupMemberInfo(groupId, m)) members = append(members, convertGroupMemberInfo(groupId, m))
} }
@ -198,11 +198,24 @@ func (bot *CQBot) CQSendGroupForwardMessage(groupId int64, m gjson.Result) MSG {
name := e.Get("data.name").Str name := e.Get("data.name").Str
content := bot.ConvertObjectMessage(e.Get("data.content"), true) content := bot.ConvertObjectMessage(e.Get("data.content"), true)
if uin != 0 && name != "" && len(content) > 0 { if uin != 0 && name != "" && len(content) > 0 {
var newElem []message.IMessageElement
for _, elem := range content {
if img, ok := elem.(*message.ImageElement); ok {
gm, err := bot.Client.UploadGroupImage(groupId, img.Data)
if err != nil {
log.Warnf("警告:群 %v 图片上传失败: %v", groupId, err)
continue
}
newElem = append(newElem, gm)
continue
}
newElem = append(newElem, elem)
}
nodes = append(nodes, &message.ForwardNode{ nodes = append(nodes, &message.ForwardNode{
SenderId: uin, SenderId: uin,
SenderName: name, SenderName: name,
Time: int32(ts.Unix()), Time: int32(ts.Unix()),
Message: content, Message: newElem,
}) })
return return
} }
@ -291,6 +304,14 @@ func (bot *CQBot) CQSetGroupName(groupId int64, name string) MSG {
return Failed(100) return Failed(100)
} }
func (bot *CQBot) CQSetGroupMemo(groupId int64, msg string) MSG {
if g := bot.Client.FindGroup(groupId); g != nil {
g.UpdateMemo(msg)
return OK(nil)
}
return Failed(100)
}
// 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) MSG {
if g := bot.Client.FindGroup(groupId); g != nil { if g := bot.Client.FindGroup(groupId); g != nil {
@ -383,6 +404,24 @@ func (bot *CQBot) CQDeleteMessage(messageId int32) MSG {
return OK(nil) return OK(nil)
} }
func (bot *CQBot) CQGetVipInfo(userId int64) MSG {
msg := MSG{}
vip, err := bot.Client.GetVipInfo(userId)
if err != nil {
return Failed(100)
}
msg = MSG{
"user_id": vip.Uin,
"nickname": vip.Name,
"level": vip.Level,
"level_speed": vip.LevelSpeed,
"vip_level": vip.VipLevel,
"vip_growth_speed": vip.VipGrowthSpeed,
"vip_growth_total": vip.VipGrowthTotal,
}
return OK(msg)
}
// https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_honor_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E8%8D%A3%E8%AA%89%E4%BF%A1%E6%81%AF // https://github.com/howmanybots/onebot/blob/master/v11/specs/api/public.md#get_group_honor_info-%E8%8E%B7%E5%8F%96%E7%BE%A4%E8%8D%A3%E8%AA%89%E4%BF%A1%E6%81%AF
func (bot *CQBot) CQGetGroupHonorInfo(groupId int64, t string) MSG { func (bot *CQBot) CQGetGroupHonorInfo(groupId int64, t string) MSG {
msg := MSG{"group_id": groupId} msg := MSG{"group_id": groupId}
@ -525,7 +564,7 @@ func (bot *CQBot) CQGetForwardMessage(resId string) MSG {
if m == nil { if m == nil {
return Failed(100) return Failed(100)
} }
var r []MSG r := make([]MSG, 0)
for _, n := range m.Nodes { for _, n := range m.Nodes {
bot.checkMedia(n.Message) bot.checkMedia(n.Message)
r = append(r, MSG{ r = append(r, MSG{

View File

@ -71,10 +71,13 @@ func NewQQBot(cli *client.QQClient, conf *global.JsonConfig) *CQBot {
bot.Client.OnUserWantJoinGroup(bot.groupJoinReqEvent) bot.Client.OnUserWantJoinGroup(bot.groupJoinReqEvent)
go func() { go func() {
i := conf.HeartbeatInterval i := conf.HeartbeatInterval
if i < 1 { if i < 0 {
log.Warn("警告: 心跳功能已关闭,若非预期,请检查配置文件。") log.Warn("警告: 心跳功能已关闭,若非预期,请检查配置文件。")
return return
} }
if i == 0 {
i = 5
}
for { for {
time.Sleep(time.Second * i) time.Sleep(time.Second * i)
bot.dispatchEventMessage(MSG{ bot.dispatchEventMessage(MSG{

View File

@ -6,6 +6,11 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/go-cqhttp/global"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
"io/ioutil" "io/ioutil"
"net/url" "net/url"
"path" "path"
@ -13,12 +18,6 @@ import (
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/message"
"github.com/Mrs4s/go-cqhttp/global"
log "github.com/sirupsen/logrus"
"github.com/tidwall/gjson"
) )
var matchReg = regexp.MustCompile(`\[CQ:\w+?.*?]`) var matchReg = regexp.MustCompile(`\[CQ:\w+?.*?]`)
@ -32,6 +31,17 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
if len(raw) != 0 { if len(raw) != 0 {
ur = raw[0] ur = raw[0]
} }
m := &message.SendingMessage{Elements: e}
reply := m.FirstOrNil(func(e message.IMessageElement) bool {
_, ok := e.(*message.ReplyElement)
return ok
})
if reply != nil {
r = append(r, MSG{
"type": "reply",
"data": map[string]string{"id": fmt.Sprint(ToGlobalId(code, reply.(*message.ReplyElement).ReplySeq))},
})
}
for _, elem := range e { for _, elem := range e {
m := MSG{} m := MSG{}
switch o := elem.(type) { switch o := elem.(type) {
@ -40,6 +50,15 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
"type": "text", "type": "text",
"data": map[string]string{"text": o.Content}, "data": map[string]string{"text": o.Content},
} }
case *message.LightAppElement:
//m = MSG{
// "type": "text",
// "data": map[string]string{"text": o.Content},
//}
m = MSG{
"type": "json",
"data": map[string]string{"data": o.Content},
}
case *message.AtElement: case *message.AtElement:
if o.Target == 0 { if o.Target == 0 {
m = MSG{ m = MSG{
@ -52,11 +71,6 @@ func ToArrayMessage(e []message.IMessageElement, code int64, raw ...bool) (r []M
"data": map[string]string{"qq": fmt.Sprint(o.Target)}, "data": map[string]string{"qq": fmt.Sprint(o.Target)},
} }
} }
case *message.ReplyElement:
m = MSG{
"type": "reply",
"data": map[string]string{"id": fmt.Sprint(ToGlobalId(code, o.ReplySeq))},
}
case *message.ForwardElement: case *message.ForwardElement:
m = MSG{ m = MSG{
"type": "forward", "type": "forward",
@ -103,6 +117,18 @@ 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.ServiceElement:
if isOk := strings.Contains(o.Content, "<?xml"); isOk {
m = MSG{
"type": "xml",
"data": map[string]string{"data": o.Content, "resid": fmt.Sprintf("%d", o.Id)},
}
} else {
m = MSG{
"type": "json",
"data": map[string]string{"data": o.Content, "resid": fmt.Sprintf("%d", o.Id)},
}
}
} }
r = append(r, m) r = append(r, m)
} }
@ -155,6 +181,15 @@ func ToStringMessage(e []message.IMessageElement, code int64, raw ...bool) (r st
} else { } else {
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.ServiceElement:
if isOk := strings.Contains(o.Content, "<?xml"); isOk {
r += fmt.Sprintf(`[CQ:xml,data=%s,resid=%d]`, CQCodeEscapeValue(o.Content), o.Id)
} else {
r += fmt.Sprintf(`[CQ:json,data=%s,resid=%d]`, CQCodeEscapeValue(o.Content), o.Id)
}
case *message.LightAppElement:
r += fmt.Sprintf(`[CQ:json,data=%s]`, CQCodeEscapeValue(o.Content))
//r += CQCodeEscapeText(o.Content)
} }
} }
return return
@ -274,116 +309,7 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (message.
case "text": case "text":
return message.NewText(d["text"]), nil return message.NewText(d["text"]), nil
case "image": case "image":
f := d["file"] return bot.makeImageElem(t, d, group)
if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") {
cache := d["cache"]
if cache == "" {
cache = "1"
}
hash := md5.Sum([]byte(f))
cacheFile := path.Join(global.CACHE_PATH, hex.EncodeToString(hash[:])+".cache")
if global.PathExists(cacheFile) && cache == "1" {
b, err := ioutil.ReadFile(cacheFile)
if err == nil {
return message.NewImage(b), nil
}
}
b, err := global.GetBytes(f)
if err != nil {
return nil, err
}
_ = ioutil.WriteFile(cacheFile, b, 0644)
return message.NewImage(b), nil
}
if strings.HasPrefix(f, "base64") {
b, err := base64.StdEncoding.DecodeString(strings.ReplaceAll(f, "base64://", ""))
if err != nil {
return nil, err
}
return message.NewImage(b), nil
}
if strings.HasPrefix(f, "file") {
fu, err := url.Parse(f)
if err != nil {
return nil, err
}
if strings.HasPrefix(fu.Path, "/") && runtime.GOOS == `windows` {
fu.Path = fu.Path[1:]
}
b, err := ioutil.ReadFile(fu.Path)
if err != nil {
return nil, err
}
return message.NewImage(b), nil
}
rawPath := path.Join(global.IMAGE_PATH, f)
if !global.PathExists(rawPath) && global.PathExists(rawPath+".cqimg") {
rawPath += ".cqimg"
}
if !global.PathExists(rawPath) && d["url"] != "" {
return bot.ToElement(t, map[string]string{"file": d["url"]}, group)
}
if global.PathExists(rawPath) {
b, err := ioutil.ReadFile(rawPath)
if err != nil {
return nil, err
}
if path.Ext(rawPath) != ".image" && path.Ext(rawPath) != ".cqimg" {
return message.NewImage(b), nil
}
if len(b) < 20 {
return nil, errors.New("invalid local file")
}
var size int32
var hash []byte
var url string
if path.Ext(rawPath) == ".cqimg" {
for _, line := range strings.Split(global.ReadAllText(rawPath), "\n") {
kv := strings.SplitN(line, "=", 2)
switch kv[0] {
case "md5":
hash, _ = hex.DecodeString(strings.ReplaceAll(kv[1], "\r", ""))
case "size":
t, _ := strconv.Atoi(strings.ReplaceAll(kv[1], "\r", ""))
size = int32(t)
}
}
} else {
r := binary.NewReader(b)
hash = r.ReadBytes(16)
size = r.ReadInt32()
r.ReadString()
url = r.ReadString()
}
if size == 0 {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, errors.New("img size is 0")
}
if len(hash) != 16 {
return nil, errors.New("invalid hash")
}
if group {
rsp, err := bot.Client.QueryGroupImage(1, hash, size)
if err != nil {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, err
}
return rsp, nil
}
rsp, err := bot.Client.QueryFriendImage(1, hash, size)
if err != nil {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, err
}
return rsp, nil
}
return nil, errors.New("invalid image")
case "record": case "record":
if !group { if !group {
return nil, errors.New("private voice unsupported now") return nil, errors.New("private voice unsupported now")
@ -454,17 +380,22 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (message.
return nil, errors.New("song not found") return nil, errors.New("song not found")
} }
aid := strconv.FormatInt(info.Get("track_info.album.id").Int(), 10) aid := strconv.FormatInt(info.Get("track_info.album.id").Int(), 10)
name := info.Get("track_info.name").Str name := info.Get("track_info.name").Str + " - " + info.Get("track_info.singer.0.name").Str
mid := info.Get("track_info.mid").Str
albumMid := info.Get("track_info.album.mid").Str
pinfo, _ := global.GetBytes("http://u.y.qq.com/cgi-bin/musicu.fcg?g_tk=2034008533&uin=0&format=json&data={\"comm\":{\"ct\":23,\"cv\":0},\"url_mid\":{\"module\":\"vkey.GetVkeyServer\",\"method\":\"CgiGetVkey\",\"param\":{\"guid\":\"4311206557\",\"songmid\":[\"" + mid + "\"],\"songtype\":[0],\"uin\":\"0\",\"loginflag\":1,\"platform\":\"23\"}}}&_=1599039471576")
jumpUrl := "https://i.y.qq.com/v8/playsong.html?platform=11&appshare=android_qq&appversion=10030010&hosteuin=oKnlNenz7i-s7c**&songmid=" + mid + "&type=0&appsongtype=1&_wv=1&source=qq&ADTAG=qfshare"
purl := gjson.ParseBytes(pinfo).Get("url_mid.data.midurlinfo.0.purl").Str
preview := "http://y.gtimg.cn/music/photo_new/T002R180x180M000" + albumMid + ".jpg"
if len(aid) < 2 { if len(aid) < 2 {
return nil, errors.New("song error") return nil, errors.New("song error")
} }
xml := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="https://i.y.qq.com/v8/playsong.html?_wv=1&amp;songid=%s&amp;souce=qqshare&amp;source=qqshare&amp;ADTAG=qqshare" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="http://imgcache.qq.com/music/photo/album_500/%s/500_albumpic_%s_0.jpg" src="%s" /><title>%s</title><summary>%s</summary></item><source name="QQ音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>`, content := "来自go-cqhttp"
name, d["id"], aid[:len(aid)-2], aid, name, "", info.Get("track_info.singer.name").Str) if d["content"] != "" {
return &message.ServiceElement{ content = d["content"]
Id: 60, }
Content: xml, json := fmt.Sprintf("{\"app\": \"com.tencent.structmsg\",\"desc\": \"音乐\",\"meta\": {\"music\": {\"desc\": \"%s\",\"jumpUrl\": \"%s\",\"musicUrl\": \"%s\",\"preview\": \"%s\",\"tag\": \"QQ音乐\",\"title\": \"%s\"}},\"prompt\": \"[分享]%s\",\"ver\": \"0.0.0.1\",\"view\": \"music\"}", content, jumpUrl, purl, preview, name, name)
SubType: "music", return message.NewLightApp(json), nil
}, nil
} }
if d["type"] == "163" { if d["type"] == "163" {
info, err := global.NeteaseMusicSongInfo(d["id"]) info, err := global.NeteaseMusicSongInfo(d["id"])
@ -475,17 +406,15 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (message.
return nil, errors.New("song not found") return nil, errors.New("song not found")
} }
name := info.Get("name").Str name := info.Get("name").Str
jumpUrl := "https://y.music.163.com/m/song/" + d["id"]
musicUrl := "http://music.163.com/song/media/outer/url?id=" + d["id"]
picUrl := info.Get("album.picUrl").Str
artistName := "" artistName := ""
if info.Get("artists.0").Exists() { if info.Get("artists.0").Exists() {
artistName = info.Get("artists.0.name").Str artistName = info.Get("artists.0.name").Str
} }
xml := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="http://music.163.com/m/song/%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="%s?param=90y90" src="https://music.163.com/song/media/outer/url?id=%s.mp3" /><title>%s</title><summary>%s</summary></item><source name="网易云音乐" icon="https://pic.rmb.bdstatic.com/911423bee2bef937975b29b265d737b3.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=100495085" action="app" a_actionData="com.netease.cloudmusic" i_actionData="tencent100495085://" appid="100495085" /></msg>`, json := fmt.Sprintf("{\"app\": \"com.tencent.structmsg\",\"desc\":\"音乐\",\"view\":\"music\",\"prompt\":\"[分享]%s\",\"ver\":\"0.0.0.1\",\"meta\":{ \"music\": { \"desc\": \"%s\", \"jumpUrl\": \"%s\", \"musicUrl\": \"%s\", \"preview\": \"%s\", \"tag\": \"网易云音乐\", \"title\":\"%s\"}}}", name, artistName, jumpUrl, musicUrl, picUrl, name)
name, d["id"], info.Get("album.picUrl").Str, d["id"], name, artistName) return message.NewLightApp(json), nil
return &message.ServiceElement{
Id: 60,
Content: xml,
SubType: "music",
}, nil
} }
if d["type"] == "custom" { if d["type"] == "custom" {
xml := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="%s" src="%s"/><title>%s</title><summary>%s</summary></item><source name="音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>`, xml := fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="[分享] %s" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="2"><audio cover="%s" src="%s"/><title>%s</title><summary>%s</summary></item><source name="音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>`,
@ -502,8 +431,44 @@ func (bot *CQBot) ToElement(t string, d map[string]string, group bool) (message.
template := CQCodeEscapeValue(d["data"]) template := CQCodeEscapeValue(d["data"])
//println(template) //println(template)
i, _ := strconv.ParseInt(resId, 10, 64) i, _ := strconv.ParseInt(resId, 10, 64)
msg := global.NewXmlMsg(template, i) msg := message.NewRichXml(template, i)
return msg, nil return msg, nil
case "json":
resId := d["resid"]
i, _ := strconv.ParseInt(resId, 10, 64)
log.Warnf("json msg=%s", d["data"])
if i == 0 {
//默认情况下走小程序通道
msg := message.NewLightApp(CQCodeUnescapeValue(d["data"]))
return msg, nil
}
//resid不为0的情况下走富文本通道后续补全透传service Id此处暂时不处理 TODO
msg := message.NewRichJson(CQCodeUnescapeValue(d["data"]))
return msg, nil
case "cardimage":
source := d["source"]
icon := d["icon"]
minwidth, _ := strconv.ParseInt(d["minwidth"], 10, 64)
if minwidth == 0 {
minwidth = 200
}
minheight, _ := strconv.ParseInt(d["minheight"], 10, 64)
if minheight == 0 {
minheight = 200
}
maxwidth, _ := strconv.ParseInt(d["maxwidth"], 10, 64)
if maxwidth == 0 {
maxwidth = 500
}
maxheight, _ := strconv.ParseInt(d["maxheight"], 10, 64)
if maxheight == 0 {
maxheight = 1000
}
img, err := bot.makeImageElem(t, d, group)
if err != nil {
return nil, errors.New("send cardimage faild")
}
return bot.SendNewPic(img, source, icon, minwidth, minheight, maxwidth, maxheight, group)
default: default:
return nil, errors.New("unsupported cq code: " + t) return nil, errors.New("unsupported cq code: " + t)
} }
@ -536,3 +501,153 @@ func CQCodeUnescapeValue(content string) string {
ret = CQCodeUnescapeText(ret) ret = CQCodeUnescapeText(ret)
return ret return ret
} }
// 图片 elem 生成器,单独拎出来,用于公用
func (bot *CQBot) makeImageElem(t string, d map[string]string, group bool) (message.IMessageElement, error) {
f := d["file"]
if strings.HasPrefix(f, "http") || strings.HasPrefix(f, "https") {
cache := d["cache"]
if cache == "" {
cache = "1"
}
hash := md5.Sum([]byte(f))
cacheFile := path.Join(global.CACHE_PATH, hex.EncodeToString(hash[:])+".cache")
if global.PathExists(cacheFile) && cache == "1" {
b, err := ioutil.ReadFile(cacheFile)
if err == nil {
return message.NewImage(b), nil
}
}
b, err := global.GetBytes(f)
if err != nil {
return nil, err
}
_ = ioutil.WriteFile(cacheFile, b, 0644)
return message.NewImage(b), nil
}
if strings.HasPrefix(f, "base64") {
b, err := base64.StdEncoding.DecodeString(strings.ReplaceAll(f, "base64://", ""))
if err != nil {
return nil, err
}
return message.NewImage(b), nil
}
if strings.HasPrefix(f, "file") {
fu, err := url.Parse(f)
if err != nil {
return nil, err
}
if strings.HasPrefix(fu.Path, "/") && runtime.GOOS == `windows` {
fu.Path = fu.Path[1:]
}
b, err := ioutil.ReadFile(fu.Path)
if err != nil {
return nil, err
}
return message.NewImage(b), nil
}
rawPath := path.Join(global.IMAGE_PATH, f)
if !global.PathExists(rawPath) && global.PathExists(rawPath+".cqimg") {
rawPath += ".cqimg"
}
if !global.PathExists(rawPath) && d["url"] != "" {
return bot.ToElement(t, map[string]string{"file": d["url"]}, group)
}
if global.PathExists(rawPath) {
b, err := ioutil.ReadFile(rawPath)
if err != nil {
return nil, err
}
if path.Ext(rawPath) != ".image" && path.Ext(rawPath) != ".cqimg" {
return message.NewImage(b), nil
}
if len(b) < 20 {
return nil, errors.New("invalid local file")
}
var size int32
var hash []byte
var url string
if path.Ext(rawPath) == ".cqimg" {
for _, line := range strings.Split(global.ReadAllText(rawPath), "\n") {
kv := strings.SplitN(line, "=", 2)
switch kv[0] {
case "md5":
hash, _ = hex.DecodeString(strings.ReplaceAll(kv[1], "\r", ""))
case "size":
t, _ := strconv.Atoi(strings.ReplaceAll(kv[1], "\r", ""))
size = int32(t)
}
}
} else {
r := binary.NewReader(b)
hash = r.ReadBytes(16)
size = r.ReadInt32()
r.ReadString()
url = r.ReadString()
}
if size == 0 {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, errors.New("img size is 0")
}
if len(hash) != 16 {
return nil, errors.New("invalid hash")
}
if group {
rsp, err := bot.Client.QueryGroupImage(1, hash, size)
if err != nil {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, err
}
return rsp, nil
}
rsp, err := bot.Client.QueryFriendImage(1, hash, size)
if err != nil {
if url != "" {
return bot.ToElement(t, map[string]string{"file": url}, group)
}
return nil, err
}
return rsp, nil
}
return nil, errors.New("invalid image")
}
//SendNewPic 一种xml 方式发送的群消息图片
func (bot *CQBot) SendNewPic(elem message.IMessageElement, source string, icon string, minwidth int64, minheigt int64, maxwidth int64, maxheight int64, group bool) (*message.ServiceElement, error) {
var xml string
xml = ""
if i, ok := elem.(*message.ImageElement); ok {
if group == false {
gm, err := bot.Client.UploadPrivateImage(1, i.Data)
if err != nil {
log.Warnf("警告: 好友消息 %v 消息图片上传失败: %v", 1, err)
return nil, err
}
xml = fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="5" templateID="12345" action="" brief="&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="0" advertiser_id="0" aid="0"><image uuid="%x" md5="%x" GroupFiledid="0" filesize="%d" local_path="%s" minWidth="%d" minHeight="%d" maxWidth="%d" maxHeight="%d" /></item><source name="%s" icon="%s" action="" appid="-1" /></msg>`, "", gm.Md5, gm.Md5, len(i.Data), "", minwidth, minheigt, maxwidth, maxheight, source, icon)
} else {
gm, err := bot.Client.UploadGroupImage(1, i.Data)
if err != nil {
log.Warnf("警告: 群 %v 消息图片上传失败: %v", 1, err)
return nil, err
}
xml = fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="5" templateID="12345" action="" brief="&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="0" advertiser_id="0" aid="0"><image uuid="%x" md5="%x" GroupFiledid="0" filesize="%d" local_path="%s" minWidth="%d" minHeight="%d" maxWidth="%d" maxHeight="%d" /></item><source name="%s" icon="%s" action="" appid="-1" /></msg>`, "", gm.Md5, gm.Md5, len(i.Data), "", minwidth, minheigt, maxwidth, maxheight, source, icon)
}
}
if i, ok := elem.(*message.GroupImageElement); ok {
xml = fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="5" templateID="12345" action="" brief="&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="0" advertiser_id="0" aid="0"><image uuid="%x" md5="%x" GroupFiledid="0" filesize="%d" local_path="%s" minWidth="%d" minHeight="%d" maxWidth="%d" maxHeight="%d" /></item><source name="%s" icon="%s" action="" appid="-1" /></msg>`, "", i.Md5, i.Md5, 0, "", minwidth, minheigt, maxwidth, maxheight, source, icon)
}
if i, ok := elem.(*message.FriendImageElement); ok {
xml = fmt.Sprintf(`<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="5" templateID="12345" action="" brief="&#91;分享&#93;我看到一张很赞的图片,分享给你,快来看!" sourceMsgId="0" url="%s" flag="0" adverSign="0" multiMsgFlag="0"><item layout="0" advertiser_id="0" aid="0"><image uuid="%x" md5="%x" GroupFiledid="0" filesize="%d" local_path="%s" minWidth="%d" minHeight="%d" maxWidth="%d" maxHeight="%d" /></item><source name="%s" icon="%s" action="" appid="-1" /></msg>`, "", i.Md5, i.Md5, 0, "", minwidth, minheigt, maxwidth, maxheight, source, icon)
}
if xml != "" {
log.Warn(xml)
XmlMsg := message.NewRichXml(xml, 5)
return XmlMsg, nil
}
return nil, errors.New("发送xml图片消息失败")
}

132
docs/EventFilter.md Normal file
View File

@ -0,0 +1,132 @@
# 事件过滤器
在go-cqhttp同级目录下新建`filter.json`文件即可开启事件过滤器,启动时会读取该文件中定义的过滤规则(使用 JSON 编写),若文件不存在,或过滤规则语法错误,则会暂停所有上报。
事件过滤器会处理所有事件(包括心跳事件在内的元事件),请谨慎使用!!
## 示例
这节首先给出一些示例,演示过滤器的基本用法,下一节将给出具体语法说明。
### 只上报以「!!」开头的消息
```json
{
"raw_message": {
".regex": "^!!"
}
}
```
### 只上报群组的非匿名消息
```json
{
"message_type": "group",
"anonymous": {
".eq": null
}
}
```
### 只上报私聊或特定群组的非匿名消息
```json
{
".or": [
{
"message_type": "private"
},
{
"message_type": "group",
"group_id": {
".in": [
123456
]
},
"anonymous": {
".eq": null
}
}
]
}
```
### 只上报群组 11111、22222、33333 中不是用户 12345 发送的消息,以及用户 66666 发送的所有消息
```json
{
".or": [
{
"group_id": {
".in": [11111, 22222, 33333]
},
"user_id": {
".neq": 12345
}
},
{
"user_id": 66666
}
]
}
```
### 一个更复杂的例子
```json
{
".or": [
{
"message_type": "private",
"user_id": {
".not": {
".in": [11111, 22222, 33333]
},
".neq": 44444
}
},
{
"message_type": {
".regex": "group|discuss"
},
".or": [
{
"group_id": 12345
},
{
"raw_message": {
".contains": "通知"
}
}
]
}
]
}
```
## 语法说明
过滤规则最外层是一个 JSON 对象,其中的键,如果以 `.`(点号)开头,则表示运算符,其值为运算符的参数,如果不以 `.` 开头,则表示对事件数据对象中相应键的过滤。过滤规则中任何一个对象,只有在它的所有项都匹配的情况下,才会让事件通过(等价于一个 `and` 运算);其中,不以 `.` 开头的键,若其值不是对象,则只有在这个值和事件数据相应值相等的情况下,才会通过(等价于一个 `eq` 运算符)。
下面列出所有运算符(「要求的参数类型」是指运算符的键所对应的值的类型,「可作用于的类型」是指在过滤时事件对象相应值的类型):
| 运算符 | 要求的参数类型 | 可作用于的类型 |
| ----- | ------------ | ----------- |
| `.not` | object | 任何 |
| `.and` | object | 若参数中全为运算符,则任何;若不全为运算符,则 object |
| `.or` | array数组元素为 object | 任何 |
| `.eq` | 任何 | 任何 |
| `.neq` | 任何 | 任何 |
| `.in` | string/array | 若参数为 string则 string若参数为 array则任何 |
| `.contains` | string | string |
| `.regex` | string | string |
## 过滤时的事件数据对象
过滤器在go-cqhttp构建好事件数据后运行各事件的数据字段见[OneBot标准]( https://github.com/howmanybots/onebot/blob/master/v11/specs/event/README.md )。
这里有几点需要注意:
- `message` 字段在运行过滤器时是消息段数组的形式(见 [消息格式]( https://github.com/howmanybots/onebot/blob/master/v11/specs/message/array.md )
- `raw_message` 字段为未经**CQ码**处理的原始消息字符串,这意味着其中可能会出现形如 `[CQ:face,id=123]` 的 CQ 码

View File

@ -22,12 +22,15 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
"password_encrypted": "", "password_encrypted": "",
"enable_db": true, "enable_db": true,
"access_token": "", "access_token": "",
"relogin": false, "relogin": {
"relogin_delay": 0, "enabled": true,
"relogin_delay": 3,
"max_relogin_times": 0
},
"post_message_format": "string", "post_message_format": "string",
"ignore_invalid_cqcode": false, "ignore_invalid_cqcode": false,
"force_fragmented": true, "force_fragmented": true,
"heartbeat_interval": 5, "heartbeat_interval": 5,
"http_config": { "http_config": {
"enabled": true, "enabled": true,
"host": "0.0.0.0", "host": "0.0.0.0",
@ -62,6 +65,7 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
| access_token | string | 同CQHTTP的 `access_token` 用于身份验证 | | access_token | string | 同CQHTTP的 `access_token` 用于身份验证 |
| relogin | bool | 是否自动重新登录 | | relogin | bool | 是否自动重新登录 |
| relogin_delay | int | 重登录延时(秒) | | relogin_delay | int | 重登录延时(秒) |
| max_relogin_times | uint | 最大重登录次数若0则不设置上限 |
| post_message_format | string | 上报信息类型 | | post_message_format | string | 上报信息类型 |
| ignore_invalid_cqcode| bool | 是否忽略错误的CQ码 | | ignore_invalid_cqcode| bool | 是否忽略错误的CQ码 |
| force_fragmented | bool | 是否强制分片发送群长消息 | | force_fragmented | bool | 是否强制分片发送群长消息 |
@ -75,6 +79,6 @@ go-cqhttp 支持导入CQHTTP的配置文件, 具体步骤为:
> 解密后密码将储存在内存中,用于自动重连等功能. 所以此加密并不能防止内存读取. > 解密后密码将储存在内存中,用于自动重连等功能. 所以此加密并不能防止内存读取.
> 解密密钥在使用完成后并不会留存在内存中, 所以可用相对简单的字符串作为密钥 > 解密密钥在使用完成后并不会留存在内存中, 所以可用相对简单的字符串作为密钥
> 注2: 分片发送为原酷Q发送长消息的老方案, 发送速度更优/兼容性更好。关闭后将优先使用新方案, 能发送更长的消息, 但发送速度更慢,在部分老客户端将无法解析. > 注2: 分片发送为原酷Q发送长消息的老方案, 发送速度更优/兼容性更好,但在有发言频率限制的群里,可能无法发送。关闭后将优先使用新方案, 能发送更长的消息, 但发送速度更慢,在部分老客户端将无法解析.
> 注3关闭心跳服务可能引起断线请谨慎关闭 > 注3关闭心跳服务可能引起断线请谨慎关闭

View File

@ -123,7 +123,7 @@ Type: `node`
Type: `xml` Type: `xml`
范围: **发送** 范围: **发送/接收**
参数: 参数:
@ -135,8 +135,11 @@ Type: `xml`
示例: `[CQ:xml,data=xxxx]` 示例: `[CQ:xml,data=xxxx]`
####一些xml样例 ####一些xml样例
####ps:重要xml中的value部分记得html实体化处理后再打加入到cq码中 ####ps:重要xml中的value部分记得html实体化处理后再打加入到cq码中
#### qq音乐 #### qq音乐
```xml ```xml
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="&#91;分享&#93; 十年" sourceMsgId="0" url="https://i.y.qq.com/v8/playsong.html?_wv=1&amp;songid=4830342&amp;souce=qqshare&amp;source=qqshare&amp;ADTAG=qqshare" flag="0" adverSign="0" multiMsgFlag="0" ><item layout="2"><audio cover="http://imgcache.qq.com/music/photo/album_500/26/500_albumpic_89526_0.jpg" src="http://ws.stream.qqmusic.qq.com/C400003mAan70zUy5O.m4a?guid=1535153710&amp;vkey=D5315B8C0603653592AD4879A8A3742177F59D582A7A86546E24DD7F282C3ACF81526C76E293E57EA1E42CF19881C561275D919233333ADE&amp;uin=&amp;fromtag=3" /><title>十年</title><summary>陈奕迅</summary></item><source name="QQ音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg> <?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID="2" templateID="1" action="web" brief="&#91;分享&#93; 十年" sourceMsgId="0" url="https://i.y.qq.com/v8/playsong.html?_wv=1&amp;songid=4830342&amp;souce=qqshare&amp;source=qqshare&amp;ADTAG=qqshare" flag="0" adverSign="0" multiMsgFlag="0" ><item layout="2"><audio cover="http://imgcache.qq.com/music/photo/album_500/26/500_albumpic_89526_0.jpg" src="http://ws.stream.qqmusic.qq.com/C400003mAan70zUy5O.m4a?guid=1535153710&amp;vkey=D5315B8C0603653592AD4879A8A3742177F59D582A7A86546E24DD7F282C3ACF81526C76E293E57EA1E42CF19881C561275D919233333ADE&amp;uin=&amp;fromtag=3" /><title>十年</title><summary>陈奕迅</summary></item><source name="QQ音乐" icon="https://i.gtimg.cn/open/app_icon/01/07/98/56/1101079856_100_m.png" url="http://web.p.qq.com/qqmpmobile/aio/app.html?id=1101079856" action="app" a_actionData="com.tencent.qqmusic" i_actionData="tencent1101079856://" appid="1101079856" /></msg>
``` ```
@ -165,6 +168,62 @@ Type: `xml`
</msg> </msg>
``` ```
### json消息支持
Type: `json`
范围: **发送/接收**
参数:
| 参数名 | 类型 | 说明 |
| ------ | ------ | ------------------------------------------------------------ |
| data | string | json内容json的所有字符串记得实体化处理|
| resid | int32 | 默认不填为0走小程序通道填了走富文本通道发送|
json中的字符串需要进行转义
>","=>`&#44;`、
>"&"=> `&amp;`、
>"["=>`&#91;`、
>"]"=>`&#93;`、
否则无法正确得到解析
示例json 的cq码
```test
[CQ:json,data={"app":"com.tencent.miniapp"&#44;"desc":""&#44;"view":"notification"&#44;"ver":"0.0.0.1"&#44;"prompt":"&#91;应用&#93;"&#44;"appID":""&#44;"sourceName":""&#44;"actionData":""&#44;"actionData_A":""&#44;"sourceUrl":""&#44;"meta":{"notification":{"appInfo":{"appName":"全国疫情数据统计"&#44;"appType":4&#44;"appid":1109659848&#44;"iconUrl":"http:\/\/gchat.qpic.cn\/gchatpic_new\/719328335\/-2010394141-6383A777BEB79B70B31CE250142D740F\/0"}&#44;"data":&#91;{"title":"确诊"&#44;"value":"80932"}&#44;{"title":"今日确诊"&#44;"value":"28"}&#44;{"title":"疑似"&#44;"value":"72"}&#44;{"title":"今日疑似"&#44;"value":"5"}&#44;{"title":"治愈"&#44;"value":"60197"}&#44;{"title":"今日治愈"&#44;"value":"1513"}&#44;{"title":"死亡"&#44;"value":"3140"}&#44;{"title":"今**亡"&#44;"value":"17"}&#93;&#44;"title":"中国加油,武汉加油"&#44;"button":&#91;{"name":"病毒SARS-CoV-2其导致疾病命名 COVID-19"&#44;"action":""}&#44;{"name":"传染源:新冠肺炎的患者。无症状感染者也可能成为传染源。"&#44;"action":""}&#93;&#44;"emphasis_keyword":""}}&#44;"text":""&#44;"sourceAd":""}]
```
### cardimage 一种xml的图片消息装逼大图
ps: xml 接口的消息都存在风控风险,请自行兼容发送失败后的处理(可以失败后走普通图片模式)
Type: `cardimage`
范围: **发送**
参数:
| 参数名 | 类型 | 说明 |
| ------ | ------ | ------------------------------------------------------------ |
| file | string | 和image的file字段对齐支持也是一样的|
| minwidth | int64 | 默认不填为400最小width|
| minheight | int64 | 默认不填为400最小height|
| maxwidth | int64 | 默认不填为500最大width|
| maxheight | int64 | 默认不填为1000最大height|
| source | string | 分享来源的名称,可以留空|
| icon | string | 分享来源的icon图标url可以留空|
示例cardimage 的cq码
```test
[CQ:cardimage,file=https://i.pixiv.cat/img-master/img/2020/03/25/00/00/08/80334602_p0_master1200.jpg]
```
## API ## API
@ -177,7 +236,7 @@ Type: `xml`
| 字段 | 类型 | 说明 | | 字段 | 类型 | 说明 |
| -------- | ------ | ---- | | -------- | ------ | ---- |
| group_id | int64 | 群号 | | group_id | int64 | 群号 |
| name | string | 新名 | | group_name | string | 新名 |
### 获取图片信息 ### 获取图片信息

View File

@ -2,20 +2,25 @@ package global
import ( import (
"encoding/json" "encoding/json"
"os"
"strconv"
"time" "time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
type JsonConfig struct { type JsonConfig struct {
Uin int64 `json:"uin"` Uin int64 `json:"uin"`
Password string `json:"password"` Password string `json:"password"`
EncryptPassword bool `json:"encrypt_password"` EncryptPassword bool `json:"encrypt_password"`
PasswordEncrypted string `json:"password_encrypted"` PasswordEncrypted string `json:"password_encrypted"`
EnableDB bool `json:"enable_db"` EnableDB bool `json:"enable_db"`
AccessToken string `json:"access_token"` AccessToken string `json:"access_token"`
ReLogin bool `json:"relogin"` ReLogin struct {
ReLoginDelay int `json:"relogin_delay"` Enabled bool `json:"enabled"`
ReLoginDelay int `json:"relogin_delay"`
MaxReloginTimes uint `json:"max_relogin_times"`
} `json:"relogin"`
IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"` IgnoreInvalidCQCode bool `json:"ignore_invalid_cqcode"`
ForceFragmented bool `json:"force_fragmented"` ForceFragmented bool `json:"force_fragmented"`
HeartbeatInterval time.Duration `json:"heartbeat_interval"` HeartbeatInterval time.Duration `json:"heartbeat_interval"`
@ -70,9 +75,16 @@ type GoCQReverseWebsocketConfig struct {
func DefaultConfig() *JsonConfig { func DefaultConfig() *JsonConfig {
return &JsonConfig{ return &JsonConfig{
EnableDB: true, EnableDB: true,
ReLogin: true, ReLogin: struct {
ReLoginDelay: 3, Enabled bool `json:"enabled"`
ReLoginDelay int `json:"relogin_delay"`
MaxReloginTimes uint `json:"max_relogin_times"`
}{
Enabled: true,
ReLoginDelay: 3,
MaxReloginTimes: 0,
},
PostMessageFormat: "string", PostMessageFormat: "string",
ForceFragmented: true, ForceFragmented: true,
HttpConfig: &GoCQHttpConfig{ HttpConfig: &GoCQHttpConfig{
@ -107,6 +119,8 @@ func Load(p string) *JsonConfig {
err := json.Unmarshal([]byte(ReadAllText(p)), &c) err := json.Unmarshal([]byte(ReadAllText(p)), &c)
if err != nil { if err != nil {
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", p, err) log.Warnf("尝试加载配置文件 %v 时出现错误: %v", p, err)
log.Infoln("原文件已备份")
os.Rename(p, p+".backup"+strconv.FormatInt(time.Now().Unix(), 10))
return nil return nil
} }
return &c return &c

View File

@ -4,13 +4,10 @@ import (
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"fmt" "fmt"
"github.com/tidwall/gjson"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strconv"
"strings" "strings"
"github.com/Mrs4s/MiraiGo/message"
"github.com/tidwall/gjson"
) )
func GetBytes(url string) ([]byte, error) { func GetBytes(url string) ([]byte, error) {
@ -54,18 +51,3 @@ func NeteaseMusicSongInfo(id string) (gjson.Result, error) {
return gjson.ParseBytes(d).Get("songs.0"), nil return gjson.ParseBytes(d).Get("songs.0"), nil
} }
func NewXmlMsg(template string, ResId int64) *message.ServiceElement {
var serviceid string
if ResId == 0 {
serviceid = "2" //默认值2
} else {
serviceid = strconv.FormatInt(ResId, 10)
}
//println(serviceid)
return &message.ServiceElement{
Id: int32(ResId),
Content: template,
ResId: serviceid,
SubType: "xml",
}
}

16
go.mod
View File

@ -3,22 +3,28 @@ module github.com/Mrs4s/go-cqhttp
go 1.14 go 1.14
require ( require (
github.com/Mrs4s/MiraiGo v0.0.0-20200827182935-51e155ef20da github.com/Mrs4s/MiraiGo v0.0.0-20200906025848-23750bb59124
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
github.com/gin-gonic/gin v1.6.3 github.com/gin-gonic/gin v1.6.3
github.com/go-playground/validator/v10 v10.3.0 // indirect
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/guonaihong/gout v0.1.1 github.com/guonaihong/gout v0.1.2
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/jonboulle/clockwork v0.2.0 // indirect github.com/jonboulle/clockwork v0.2.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible
github.com/lestrrat-go/strftime v1.0.1 // indirect github.com/lestrrat-go/strftime v1.0.3 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus v1.6.0
github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816
github.com/tebeka/strftime v0.1.5 // indirect github.com/tebeka/strftime v0.1.5 // indirect
github.com/tidwall/gjson v1.6.0 github.com/tidwall/gjson v1.6.1
github.com/xujiajun/nutsdb v0.5.0 github.com/xujiajun/nutsdb v0.5.0
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189 github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect golang.org/x/net v0.0.0-20200904194848-62affa334b73 // indirect
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
) )

54
go.sum
View File

@ -1,21 +1,24 @@
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-20200827182935-51e155ef20da h1:T2Qz4w6sMrBxw+oiwbUa/c996jWYulCAtM+x1L0l3R8= github.com/Mrs4s/MiraiGo v0.0.0-20200906025848-23750bb59124 h1:qqwuCK/U9wzVf4ZmlvXI2BC1+gBESNSUD5yNjTfoExQ=
github.com/Mrs4s/MiraiGo v0.0.0-20200827182935-51e155ef20da/go.mod h1:0je03wji/tSw4bUH4QCF2Z4/EjyNWjSJTyy5tliX6EM= github.com/Mrs4s/MiraiGo v0.0.0-20200906025848-23750bb59124/go.mod h1:TVEPCV9iayaBPTDLNGO9kc734jXNT/sxbhqo4IYkvko=
github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0=
github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU=
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@ -25,10 +28,13 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/go-playground/validator/v10 v10.3.0 h1:nZU+7q+yJoFmwvNgv/LnPUkwPal62+b2xXj0AU1Es7o=
github.com/go-playground/validator/v10 v10.3.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -42,38 +48,50 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
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.1 h1:2i3eqQ1KUhTlj7AFeIHqVUFku5QwUhwE2wNgYTVpbxQ= github.com/guonaihong/gout v0.1.2 h1:TR2XCRopGgJdj231IayEoeavgbznFXzzzcZVdT/hG10=
github.com/guonaihong/gout v0.1.1/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA= github.com/guonaihong/gout v0.1.2/go.mod h1:vXvv5Kxr70eM5wrp4F0+t9lnLWmq+YPW2GByll2f/EA=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
github.com/jonboulle/clockwork v0.2.0 h1:J2SLSdy7HgElq8ekSl2Mxh6vrRNFxqbXGenYH2I02Vs=
github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
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/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=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible h1:4mNlp+/SvALIPFpbXV3kxNJJno9iKFWGxSDE13Kl66Q= github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible h1:4mNlp+/SvALIPFpbXV3kxNJJno9iKFWGxSDE13Kl66Q=
github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= github.com/lestrrat-go/file-rotatelogs v2.3.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU= github.com/lestrrat-go/strftime v1.0.3 h1:qqOPU7y+TM8Y803I8fG9c/DyKG3xH/xkng6keC1015Q=
github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= github.com/lestrrat-go/strftime v1.0.3/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g=
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/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
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/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/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=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo= github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
@ -85,16 +103,18 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
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/tebeka/strftime v0.1.5 h1:1NQKN1NiQgkqd/2moD6ySP/5CoZQsKa1d3ZhJ44Jpmg=
github.com/tebeka/strftime v0.1.5/go.mod h1:29/OidkoWHdEKZqzyDLUyC+LmgDgdHo4WAFCDT7D/Ig= github.com/tebeka/strftime v0.1.5/go.mod h1:29/OidkoWHdEKZqzyDLUyC+LmgDgdHo4WAFCDT7D/Ig=
github.com/tidwall/gjson v1.6.0 h1:9VEQWz6LLMUsUl6PueE49ir4Ka6CzLymOAZDxpFsTDc= github.com/tidwall/gjson v1.6.1 h1:LRbvNuNuvAiISWg6gxLEFuCe72UKy5hDqhxW/8183ws=
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc= github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
@ -109,6 +129,7 @@ github.com/xujiajun/utils v0.0.0-20190123093513-8bf096c4f53b/go.mod h1:AZd87GYJl
github.com/yinghau76/go-ascii-art v0.0.0-20190517192627-e7f465a30189 h1:4UJw9if55Fu3HOwbfcaQlJ27p3oeJU2JZqoeT3ITJQk= 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= 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= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@ -117,8 +138,11 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -126,11 +150,13 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f h1:Fqb3ao1hUmOR3GkUOg/Y+BadLwykBIzs5q8Ez2SbHyc=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -138,6 +164,7 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -157,11 +184,14 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

73
main.go
View File

@ -7,16 +7,6 @@ import (
"encoding/base64" "encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client"
"github.com/Mrs4s/go-cqhttp/coolq"
"github.com/Mrs4s/go-cqhttp/global"
"github.com/Mrs4s/go-cqhttp/server"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
log "github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
asciiart "github.com/yinghau76/go-ascii-art"
"image" "image"
"io" "io"
"io/ioutil" "io/ioutil"
@ -26,6 +16,18 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/Mrs4s/MiraiGo/binary"
"github.com/Mrs4s/MiraiGo/client"
"github.com/Mrs4s/go-cqhttp/coolq"
"github.com/Mrs4s/go-cqhttp/global"
"github.com/Mrs4s/go-cqhttp/server"
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
"github.com/rifflock/lfshook"
log "github.com/sirupsen/logrus"
easy "github.com/t-tomalak/logrus-easy-formatter"
asciiart "github.com/yinghau76/go-ascii-art"
) )
func init() { func init() {
@ -144,7 +146,7 @@ func main() {
switch conf.LogLevel { switch conf.LogLevel {
case "warn": case "warn":
logPathMap = lfshook.PathMap{ logPathMap = lfshook.PathMap{
log.WarnLevel: path.Join("logs", date+"-warn.log"), log.WarnLevel: path.Join("logs", date+"-warn.log"),
log.ErrorLevel: path.Join("logs", date+"-warn.log"), log.ErrorLevel: path.Join("logs", date+"-warn.log"),
log.FatalLevel: path.Join("logs", date+"-warn.log"), log.FatalLevel: path.Join("logs", date+"-warn.log"),
log.PanicLevel: path.Join("logs", date+"-warn.log"), log.PanicLevel: path.Join("logs", date+"-warn.log"),
@ -157,7 +159,7 @@ func main() {
} }
default: default:
logPathMap = lfshook.PathMap{ logPathMap = lfshook.PathMap{
log.WarnLevel: path.Join("logs", date+"-warn.log"), log.WarnLevel: path.Join("logs", date+"-warn.log"),
log.ErrorLevel: path.Join("logs", date+"-warn.log"), log.ErrorLevel: path.Join("logs", date+"-warn.log"),
log.FatalLevel: path.Join("logs", date+"-warn.log"), log.FatalLevel: path.Join("logs", date+"-warn.log"),
log.PanicLevel: path.Join("logs", date+"-warn.log"), log.PanicLevel: path.Join("logs", date+"-warn.log"),
@ -278,24 +280,39 @@ func main() {
log.Info("资源初始化完成, 开始处理信息.") log.Info("资源初始化完成, 开始处理信息.")
log.Info("アトリは、高性能ですから!") log.Info("アトリは、高性能ですから!")
cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) { cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) {
if conf.ReLogin { if conf.ReLogin.Enabled {
log.Warnf("Bot已离线 (%v),将在 %v 秒后尝试重连.", e.Message, conf.ReLoginDelay) var times uint = 1
time.Sleep(time.Second * time.Duration(conf.ReLoginDelay)) for {
rsp, err := cli.Login()
if err != nil { if conf.ReLogin.MaxReloginTimes == 0 {
log.Fatalf("重连失败: %v", err) } else if times > conf.ReLogin.MaxReloginTimes {
} break
if !rsp.Success {
switch rsp.Error {
case client.NeedCaptcha:
log.Fatalf("重连失败: 需要验证码. (验证码处理正在开发中)")
case client.UnsafeDeviceError:
log.Fatalf("重连失败: 设备锁")
default:
log.Fatalf("重连失败: %v", rsp.ErrorMessage)
} }
log.Warnf("Bot已离线 (%v),将在 %v 秒后尝试重连. 重连次数:%v",
e.Message, conf.ReLogin.ReLoginDelay, times)
times++
time.Sleep(time.Second * time.Duration(conf.ReLogin.ReLoginDelay))
rsp, err := cli.Login()
if err != nil {
log.Errorf("重连失败: %v", err)
continue
}
if !rsp.Success {
switch rsp.Error {
case client.NeedCaptcha:
log.Fatalf("重连失败: 需要验证码. (验证码处理正在开发中)")
case client.UnsafeDeviceError:
log.Fatalf("重连失败: 设备锁")
default:
log.Errorf("重连失败: %v", rsp.ErrorMessage)
continue
}
}
log.Info("重连成功")
return
} }
return log.Fatal("重连失败: 重连次数达到设置的上限值")
} }
b.Release() b.Release()
log.Fatalf("Bot已离线%v", e.Message) log.Fatalf("Bot已离线%v", e.Message)

View File

@ -131,6 +131,9 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) {
s.engine.Any("/set_group_name", s.SetGroupName) s.engine.Any("/set_group_name", s.SetGroupName)
s.engine.Any("/set_group_name_async", s.SetGroupName) s.engine.Any("/set_group_name_async", s.SetGroupName)
s.engine.Any("/_send_group_notice", s.SendGroupNotice)
s.engine.Any("/_send_group_notice_async", s.SendGroupNotice)
s.engine.Any("/set_group_leave", s.SetGroupLeave) s.engine.Any("/set_group_leave", s.SetGroupLeave)
s.engine.Any("/set_group_leave_async", s.SetGroupLeave) s.engine.Any("/set_group_leave_async", s.SetGroupLeave)
@ -154,6 +157,9 @@ func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) {
s.engine.Any("/get_version_info", s.GetVersionInfo) s.engine.Any("/get_version_info", s.GetVersionInfo)
s.engine.Any("/get_version_info_async", s.GetVersionInfo) s.engine.Any("/get_version_info_async", s.GetVersionInfo)
s.engine.Any("/_get_vip_info", s.GetVipInfo)
s.engine.Any("/_get_vip_info_async", s.GetVipInfo)
s.engine.Any("/.handle_quick_operation", s.HandleQuickOperation) s.engine.Any("/.handle_quick_operation", s.HandleQuickOperation)
go func() { go func() {
@ -199,7 +205,7 @@ func (c *httpClient) onBotPushEvent(m coolq.MSG) {
return h return h
}()).SetTimeout(time.Second * time.Duration(c.timeout)).Do() }()).SetTimeout(time.Second * time.Duration(c.timeout)).Do()
if err != nil { if err != nil {
log.Warnf("上报Event数据到 %v 失败: %v", c.addr, err) log.Warnf("上报Event数据 %v 到 %v 失败: %v", m.ToJson(), c.addr, err)
return return
} }
if gjson.Valid(res) { if gjson.Valid(res) {
@ -347,7 +353,12 @@ func (s *httpServer) SetWholeBan(c *gin.Context) {
func (s *httpServer) SetGroupName(c *gin.Context) { func (s *httpServer) SetGroupName(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64) gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
c.JSON(200, s.bot.CQSetGroupName(gid, getParam(c, "name"))) c.JSON(200, s.bot.CQSetGroupName(gid, getParam(c, "group_name")))
}
func (s *httpServer) SendGroupNotice(c *gin.Context) {
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
c.JSON(200, s.bot.CQSetGroupMemo(gid, getParam(c, "content")))
} }
func (s *httpServer) SetGroupLeave(c *gin.Context) { func (s *httpServer) SetGroupLeave(c *gin.Context) {
@ -381,6 +392,11 @@ func (s *httpServer) GetVersionInfo(c *gin.Context) {
c.JSON(200, s.bot.CQGetVersionInfo()) c.JSON(200, s.bot.CQGetVersionInfo())
} }
func (s *httpServer) GetVipInfo(c *gin.Context) {
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
c.JSON(200, s.bot.CQGetVipInfo(uid))
}
func (s *httpServer) HandleQuickOperation(c *gin.Context) { func (s *httpServer) HandleQuickOperation(c *gin.Context) {
if c.Request.Method != "POST" { if c.Request.Method != "POST" {
c.AbortWithStatus(404) c.AbortWithStatus(404)
@ -400,7 +416,6 @@ func getParamOrDefault(c *gin.Context, k, def string) string {
return def return def
} }
func getParam(c *gin.Context, k string) string { func getParam(c *gin.Context, k string) string {
p, _ := getParamWithType(c, k) p, _ := getParamWithType(c, k)
return p return p

View File

@ -123,6 +123,14 @@ func (c *websocketClient) connectEvent() {
} }
return return
} }
handshake := fmt.Sprintf(`{"meta_event_type":"lifecycle","post_type":"meta_event","self_id":%d,"sub_type":"connect","time":%d}`,
c.bot.Client.Uin, time.Now().Unix())
err = conn.WriteMessage(websocket.TextMessage, []byte(handshake))
if err != nil {
log.Warnf("反向Websocket 握手时出现错误: %v", err)
}
log.Infof("已连接到反向Websocket Event服务器 %v", c.conf.ReverseEventUrl) log.Infof("已连接到反向Websocket Event服务器 %v", c.conf.ReverseEventUrl)
c.eventConn = &websocketConn{Conn: conn} c.eventConn = &websocketConn{Conn: conn}
} }
@ -146,6 +154,14 @@ func (c *websocketClient) connectUniversal() {
} }
return return
} }
handshake := fmt.Sprintf(`{"meta_event_type":"lifecycle","post_type":"meta_event","self_id":%d,"sub_type":"connect","time":%d}`,
c.bot.Client.Uin, time.Now().Unix())
err = conn.WriteMessage(websocket.TextMessage, []byte(handshake))
if err != nil {
log.Warnf("反向Websocket 握手时出现错误: %v", err)
}
wrappedConn := &websocketConn{Conn: conn} wrappedConn := &websocketConn{Conn: conn}
go c.listenApi(wrappedConn, true) go c.listenApi(wrappedConn, true)
c.universalConn = wrappedConn c.universalConn = wrappedConn
@ -206,10 +222,20 @@ func (c *websocketClient) onBotPushEvent(m coolq.MSG) {
func (s *websocketServer) event(w http.ResponseWriter, r *http.Request) { func (s *websocketServer) event(w http.ResponseWriter, r *http.Request) {
if s.token != "" { if s.token != "" {
if r.URL.Query().Get("access_token") != s.token && strings.SplitN(r.Header.Get("Authorization"), " ", 2)[1] != s.token { if auth := r.URL.Query().Get("access_token"); auth != s.token && auth != "" {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr) log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401) w.WriteHeader(401)
return return
} else if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) == 2 {
if auth[1] != s.token {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401)
return
}
} else {
log.Warnf("已拒绝 %v 的 Websocket 请求: 空Token或传入格式错误", r.RemoteAddr)
w.WriteHeader(401)
return
} }
} }
c, err := upgrader.Upgrade(w, r, nil) c, err := upgrader.Upgrade(w, r, nil)
@ -235,10 +261,20 @@ func (s *websocketServer) event(w http.ResponseWriter, r *http.Request) {
func (s *websocketServer) api(w http.ResponseWriter, r *http.Request) { func (s *websocketServer) api(w http.ResponseWriter, r *http.Request) {
if s.token != "" { if s.token != "" {
if r.URL.Query().Get("access_token") != s.token && strings.SplitN(r.Header.Get("Authorization"), " ", 2)[1] != s.token { if auth := r.URL.Query().Get("access_token"); auth != s.token && auth != "" {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr) log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401) w.WriteHeader(401)
return return
} else if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) == 2 {
if auth[1] != s.token {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401)
return
}
} else {
log.Warnf("已拒绝 %v 的 Websocket 请求: 空Token或传入格式错误", r.RemoteAddr)
w.WriteHeader(401)
return
} }
} }
c, err := upgrader.Upgrade(w, r, nil) c, err := upgrader.Upgrade(w, r, nil)
@ -253,10 +289,20 @@ func (s *websocketServer) api(w http.ResponseWriter, r *http.Request) {
func (s *websocketServer) any(w http.ResponseWriter, r *http.Request) { func (s *websocketServer) any(w http.ResponseWriter, r *http.Request) {
if s.token != "" { if s.token != "" {
if r.URL.Query().Get("access_token") != s.token && strings.SplitN(r.Header.Get("Authorization"), " ", 2)[1] != s.token { if auth := r.URL.Query().Get("access_token"); auth != s.token && auth != "" {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr) log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401) w.WriteHeader(401)
return return
} else if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) == 2 {
if auth[1] != s.token {
log.Warnf("已拒绝 %v 的 Websocket 请求: Token错误", r.RemoteAddr)
w.WriteHeader(401)
return
}
} else {
log.Warnf("已拒绝 %v 的 Websocket 请求: 空Token或传入格式错误", r.RemoteAddr)
w.WriteHeader(401)
return
} }
} }
c, err := upgrader.Upgrade(w, r, nil) c, err := upgrader.Upgrade(w, r, nil)
@ -431,7 +477,10 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
}()) }())
}, },
"set_group_name": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "set_group_name": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupName(p.Get("group_id").Int(), p.Get("name").Str) return bot.CQSetGroupName(p.Get("group_id").Int(), p.Get("group_name").Str)
},
"_send_group_notice": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupMemo(p.Get("group_id").Int(), p.Get("content").Str)
}, },
"set_group_leave": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "set_group_leave": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQSetGroupLeave(p.Get("group_id").Int()) return bot.CQSetGroupLeave(p.Get("group_id").Int())
@ -460,6 +509,9 @@ var wsApi = map[string]func(*coolq.CQBot, gjson.Result) coolq.MSG{
"get_version_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { "get_version_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVersionInfo() return bot.CQGetVersionInfo()
}, },
"_get_vip_info": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQGetVipInfo(p.Get("user_id").Int())
},
".handle_quick_operation": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG { ".handle_quick_operation": func(bot *coolq.CQBot, p gjson.Result) coolq.MSG {
return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation")) return bot.CQHandleQuickOperation(p.Get("context"), p.Get("operation"))
}, },