mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-06-30 03:43:25 +00:00
Compare commits
44 Commits
v1.0.0-bet
...
v1.0.0-bet
Author | SHA1 | Date | |
---|---|---|---|
d8a373cfa4 | |||
fb7ba0557c | |||
6011a46f1b | |||
de4f4c8676 | |||
cbd91d27bd | |||
987c57f7cf | |||
379a589fc8 | |||
6ba8774ff1 | |||
b1652c0f4b | |||
48b095f825 | |||
e1f1f715e2 | |||
e2257ee499 | |||
beb5c77767 | |||
823e6cccdd | |||
92b29dee2e | |||
2df33118be | |||
382d2ffda8 | |||
056f10ff64 | |||
0900cf5310 | |||
971a9575ff | |||
c32920ac40 | |||
7db6070b18 | |||
37e2fdaea7 | |||
2506d9144b | |||
67aa9781f2 | |||
44539a8f63 | |||
e3c06731e7 | |||
8506d7586f | |||
b20ab9dc52 | |||
a157bb3220 | |||
c1a7dda54a | |||
f350d971fd | |||
6dfa5e5959 | |||
a0cb34dc7a | |||
6fecede756 | |||
8a269aab69 | |||
7f6e1f61ea | |||
6f83db0ad0 | |||
f488b17dc7 | |||
4250199693 | |||
75aedd867a | |||
af46324dd9 | |||
08fd86493d | |||
88594184f8 |
@ -285,7 +285,7 @@ func (bot *CQBot) CQSendGroupMessage(groupID int64, i interface{}, autoEscape bo
|
|||||||
}
|
}
|
||||||
fixAt := func(elem []message.IMessageElement) {
|
fixAt := func(elem []message.IMessageElement) {
|
||||||
for _, e := range elem {
|
for _, e := range elem {
|
||||||
if at, ok := e.(*message.AtElement); ok && at.Target != 0 {
|
if at, ok := e.(*message.AtElement); ok && at.Target != 0 && at.Display == "" {
|
||||||
at.Display = "@" + func() string {
|
at.Display = "@" + func() string {
|
||||||
mem := group.FindMember(at.Target)
|
mem := group.FindMember(at.Target)
|
||||||
if mem != nil {
|
if mem != nil {
|
||||||
|
@ -316,7 +316,10 @@ func (bot *CQBot) SendPrivateMessage(target int64, groupID int64, m *message.Sen
|
|||||||
log.Errorf("错误: 群员(%v) 不在 群(%v), 无法发起临时会话", target, groupID)
|
log.Errorf("错误: 群员(%v) 不在 群(%v), 无法发起临时会话", target, groupID)
|
||||||
default:
|
default:
|
||||||
if session == nil && groupID != 0 {
|
if session == nil && groupID != 0 {
|
||||||
bot.Client.SendGroupTempMessage(groupID, target, m)
|
msg := bot.Client.SendGroupTempMessage(groupID, target, m)
|
||||||
|
if msg != nil {
|
||||||
|
id = bot.InsertTempMessage(target, msg)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
msg, err := session.(*client.TempSessionInfo).SendMessage(m)
|
msg, err := session.(*client.TempSessionInfo).SendMessage(m)
|
||||||
|
@ -28,7 +28,6 @@ import (
|
|||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
"github.com/Mrs4s/go-cqhttp/global"
|
||||||
"github.com/Mrs4s/go-cqhttp/global/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -37,7 +36,11 @@ var typeReg = regexp.MustCompile(`\[CQ:(\w+)`)
|
|||||||
var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
|
var paramReg = regexp.MustCompile(`,([\w\-.]+?)=([^,\]]+)`)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var conf *config.Config
|
// RemoveReplyAt 是否删除reply后的at
|
||||||
|
var RemoveReplyAt bool
|
||||||
|
|
||||||
|
// ExtraReplyData 是否上报额外reply信息
|
||||||
|
var ExtraReplyData bool
|
||||||
|
|
||||||
// IgnoreInvalidCQCode 是否忽略无效CQ码
|
// IgnoreInvalidCQCode 是否忽略无效CQ码
|
||||||
var IgnoreInvalidCQCode = false
|
var IgnoreInvalidCQCode = false
|
||||||
@ -49,7 +52,6 @@ var SplitURL = false
|
|||||||
var magicCQ = uint32(0)
|
var magicCQ = uint32(0)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
conf = config.Get()
|
|
||||||
CQHeader := "[CQ:"
|
CQHeader := "[CQ:"
|
||||||
magicCQ = *(*uint32)(unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&CQHeader)).Data))
|
magicCQ = *(*uint32)(unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&CQHeader)).Data))
|
||||||
}
|
}
|
||||||
@ -139,7 +141,7 @@ func ToArrayMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r []M
|
|||||||
})
|
})
|
||||||
if reply != nil {
|
if reply != nil {
|
||||||
replyElem := reply.(*message.ReplyElement)
|
replyElem := reply.(*message.ReplyElement)
|
||||||
if conf.Message.ExtraReplyData {
|
if ExtraReplyData {
|
||||||
r = append(r, MSG{
|
r = append(r, MSG{
|
||||||
"type": "reply",
|
"type": "reply",
|
||||||
"data": map[string]string{
|
"data": map[string]string{
|
||||||
@ -161,7 +163,7 @@ func ToArrayMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r []M
|
|||||||
var m MSG
|
var m MSG
|
||||||
switch o := elem.(type) {
|
switch o := elem.(type) {
|
||||||
case *message.ReplyElement:
|
case *message.ReplyElement:
|
||||||
if conf.Message.RemoveReplyAt && len(e) > i+1 {
|
if RemoveReplyAt && len(e) > i+1 {
|
||||||
elem, ok := e[i+1].(*message.AtElement)
|
elem, ok := e[i+1].(*message.AtElement)
|
||||||
if ok && elem.Target == o.Sender {
|
if ok && elem.Target == o.Sender {
|
||||||
e[i+1] = nil
|
e[i+1] = nil
|
||||||
@ -293,7 +295,9 @@ func ToArrayMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r []M
|
|||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r = append(r, m)
|
if m != nil {
|
||||||
|
r = append(r, m)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -312,7 +316,7 @@ func ToStringMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r st
|
|||||||
})
|
})
|
||||||
if reply != nil {
|
if reply != nil {
|
||||||
replyElem := reply.(*message.ReplyElement)
|
replyElem := reply.(*message.ReplyElement)
|
||||||
if conf.Message.ExtraReplyData {
|
if ExtraReplyData {
|
||||||
r += fmt.Sprintf("[CQ:reply,id=%d,seq=%d,qq=%d,time=%d,text=%s]",
|
r += fmt.Sprintf("[CQ:reply,id=%d,seq=%d,qq=%d,time=%d,text=%s]",
|
||||||
toGlobalID(id, replyElem.ReplySeq),
|
toGlobalID(id, replyElem.ReplySeq),
|
||||||
replyElem.ReplySeq, replyElem.Sender, replyElem.Time,
|
replyElem.ReplySeq, replyElem.Sender, replyElem.Time,
|
||||||
@ -324,7 +328,7 @@ func ToStringMessage(e []message.IMessageElement, id int64, isRaw ...bool) (r st
|
|||||||
for i, elem := range e {
|
for i, elem := range e {
|
||||||
switch o := elem.(type) {
|
switch o := elem.(type) {
|
||||||
case *message.ReplyElement:
|
case *message.ReplyElement:
|
||||||
if conf.Message.RemoveReplyAt && len(e) > i+1 {
|
if RemoveReplyAt && len(e) > i+1 {
|
||||||
elem, ok := e[i+1].(*message.AtElement)
|
elem, ok := e[i+1].(*message.AtElement)
|
||||||
if ok && elem.Target == o.Sender {
|
if ok && elem.Target == o.Sender {
|
||||||
e[i+1] = nil
|
e[i+1] = nil
|
||||||
|
@ -3,12 +3,9 @@ package coolq
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/Mrs4s/MiraiGo/client"
|
|
||||||
"github.com/Mrs4s/go-cqhttp/global"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var bot = NewQQBot(client.NewClient(1, ""), global.DefaultConfig())
|
var bot = CQBot{}
|
||||||
|
|
||||||
func TestCQBot_ConvertStringMessage(t *testing.T) {
|
func TestCQBot_ConvertStringMessage(t *testing.T) {
|
||||||
for _, v := range bot.ConvertStringMessage(`[CQ:face,id=115,text=111][CQ:face,id=217]] [CQ:text,text=123] [`, false) {
|
for _, v := range bot.ConvertStringMessage(`[CQ:face,id=115,text=111][CQ:face,id=217]] [CQ:text,text=123] [`, false) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# 事件过滤器
|
# 事件过滤器
|
||||||
|
|
||||||
在go-cqhttp同级目录下新建`filter.json`文件即可开启事件过滤器,启动时会读取该文件中定义的过滤规则(使用 JSON 编写),若文件不存在,或过滤规则语法错误,则不会启用事件过滤器。
|
在配置文件填写对应通信方式的 `middlewares.filter` 即可开启事件过滤器,启动时会读取该文件中定义的过滤规则(使用 JSON 编写),若文件不存在,或过滤规则语法错误,则不会启用事件过滤器。
|
||||||
事件过滤器会处理所有事件(包括心跳事件在内的元事件),请谨慎使用!!
|
事件过滤器会处理所有事件(包括心跳事件在内的元事件),请谨慎使用!!
|
||||||
|
|
||||||
注意: 与客户端建立连接的握手事件**不会**经过事件过滤器
|
注意: 与客户端建立连接的握手事件**不会**经过事件过滤器
|
||||||
@ -114,6 +114,35 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 进阶指南
|
||||||
|
|
||||||
|
1. 对于嵌套的值,可以使用 `.` 进行简化,如
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sender": {
|
||||||
|
"sex": "male"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
与下面的配置文件作用相同
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"sender.sex": "male"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 对于数组,可以使用数字索引,如
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"message.0.type": "text"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
更多进阶语法请参考[GJSON语法](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)
|
||||||
|
|
||||||
## 语法说明
|
## 语法说明
|
||||||
|
|
||||||
过滤规则最外层是一个 JSON 对象,其中的键,如果以 `.`(点号)开头,则表示运算符,其值为运算符的参数,如果不以 `.` 开头,则表示对事件数据对象中相应键的过滤。过滤规则中任何一个对象,只有在它的所有项都匹配的情况下,才会让事件通过(等价于一个 `and` 运算);其中,不以 `.` 开头的键,若其值不是对象,则只有在这个值和事件数据相应值相等的情况下,才会通过(等价于一个 `eq` 运算符)。
|
过滤规则最外层是一个 JSON 对象,其中的键,如果以 `.`(点号)开头,则表示运算符,其值为运算符的参数,如果不以 `.` 开头,则表示对事件数据对象中相应键的过滤。过滤规则中任何一个对象,只有在它的所有项都匹配的情况下,才会让事件通过(等价于一个 `and` 运算);其中,不以 `.` 开头的键,若其值不是对象,则只有在这个值和事件数据相应值相等的情况下,才会通过(等价于一个 `eq` 运算符)。
|
||||||
|
@ -15,7 +15,8 @@ account: # 账号相关
|
|||||||
uin: 1233456 # QQ账号
|
uin: 1233456 # QQ账号
|
||||||
password: '' # 密码为空时使用扫码登录
|
password: '' # 密码为空时使用扫码登录
|
||||||
encrypt: false # 是否开启密码加密
|
encrypt: false # 是否开启密码加密
|
||||||
relogin: # 重连设置
|
status: 0 # 在线状态,详情请查看下方的在线状态表
|
||||||
|
relogin: # 重连设置
|
||||||
disabled: false
|
disabled: false
|
||||||
delay: 3 # 重连延迟, 单位秒
|
delay: 3 # 重连延迟, 单位秒
|
||||||
interval: 0 # 重连间隔
|
interval: 0 # 重连间隔
|
||||||
@ -49,7 +50,7 @@ message:
|
|||||||
report-self-message: false
|
report-self-message: false
|
||||||
|
|
||||||
output:
|
output:
|
||||||
# 日志等级 trace,debug,info,warn,error日志等级 trace,debug,info,warn,error
|
# 日志等级 trace,debug,info,warn,error
|
||||||
log-level: warn
|
log-level: warn
|
||||||
# 是否启用 DEBUG
|
# 是否启用 DEBUG
|
||||||
debug: false # 开启调试模式
|
debug: false # 开启调试模式
|
||||||
@ -138,6 +139,33 @@ database: # 数据库相关设置
|
|||||||
|
|
||||||
> 注3:关闭心跳服务可能引起断线,请谨慎关闭
|
> 注3:关闭心跳服务可能引起断线,请谨慎关闭
|
||||||
|
|
||||||
|
## 在线状态
|
||||||
|
|
||||||
|
| 状态 | 值 |
|
||||||
|
| -----|----|
|
||||||
|
| 在线 | 0 |
|
||||||
|
| 离开 | 1 |
|
||||||
|
| 隐身 | 2 |
|
||||||
|
| 忙 | 3 |
|
||||||
|
| 听歌中 | 4 |
|
||||||
|
| 星座运势 | 5 |
|
||||||
|
| 今日天气 | 6 |
|
||||||
|
| 遇见春天 | 7 |
|
||||||
|
| Timi中 | 8 |
|
||||||
|
| 吃鸡中 | 9 |
|
||||||
|
| 恋爱中 | 10 |
|
||||||
|
| 汪汪汪 | 11 |
|
||||||
|
| 干饭中 | 12 |
|
||||||
|
| 学习中 | 13 |
|
||||||
|
| 熬夜中 | 14 |
|
||||||
|
| 打球中 | 15 |
|
||||||
|
| 信号弱 | 16 |
|
||||||
|
| 在线学习 | 17 |
|
||||||
|
| 游戏中 | 18 |
|
||||||
|
| 度假中 | 19 |
|
||||||
|
| 追剧中 | 20 |
|
||||||
|
| 健身中 | 21 |
|
||||||
|
|
||||||
## 设备信息
|
## 设备信息
|
||||||
|
|
||||||
默认生成的设备信息如下所示:
|
默认生成的设备信息如下所示:
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
_ "embed" // embed the default config file
|
_ "embed" // embed the default config file
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"sync"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@ -25,6 +26,7 @@ type Config struct {
|
|||||||
Uin int64 `yaml:"uin"`
|
Uin int64 `yaml:"uin"`
|
||||||
Password string `yaml:"password"`
|
Password string `yaml:"password"`
|
||||||
Encrypt bool `yaml:"encrypt"`
|
Encrypt bool `yaml:"encrypt"`
|
||||||
|
Status int32 `yaml:"status"`
|
||||||
ReLogin struct {
|
ReLogin struct {
|
||||||
Disabled bool `yaml:"disabled"`
|
Disabled bool `yaml:"disabled"`
|
||||||
Delay int `yaml:"delay"`
|
Delay int `yaml:"delay"`
|
||||||
@ -84,6 +86,13 @@ type HTTPServer struct {
|
|||||||
MiddleWares `yaml:"middlewares"`
|
MiddleWares `yaml:"middlewares"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PprofServer pprof性能分析服务器相关配置
|
||||||
|
type PprofServer struct {
|
||||||
|
Disabled bool `yaml:"disabled"`
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
// WebsocketServer 正向WS相关配置
|
// WebsocketServer 正向WS相关配置
|
||||||
type WebsocketServer struct {
|
type WebsocketServer struct {
|
||||||
Disabled bool `yaml:"disabled"`
|
Disabled bool `yaml:"disabled"`
|
||||||
@ -109,17 +118,25 @@ type LevelDBConfig struct {
|
|||||||
Enable bool `yaml:"enable"`
|
Enable bool `yaml:"enable"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
config *Config
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
// Get 从默认配置文件路径中获取
|
// Get 从默认配置文件路径中获取
|
||||||
func Get() *Config {
|
func Get() *Config {
|
||||||
file, err := os.Open(DefaultConfigFile)
|
once.Do(func() {
|
||||||
if err != nil {
|
file, err := os.Open(DefaultConfigFile)
|
||||||
log.Error("获取配置文件失败: ", err)
|
if err != nil {
|
||||||
return nil
|
log.Error("获取配置文件失败: ", err)
|
||||||
}
|
return
|
||||||
config := &Config{}
|
}
|
||||||
if yaml.NewDecoder(file).Decode(config) != nil {
|
defer file.Close()
|
||||||
log.Fatal("配置文件不合法!", err)
|
config = &Config{}
|
||||||
}
|
if err = yaml.NewDecoder(file).Decode(config); err != nil {
|
||||||
|
log.Fatal("配置文件不合法!", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,8 @@ account: # 账号相关
|
|||||||
uin: 1233456 # QQ账号
|
uin: 1233456 # QQ账号
|
||||||
password: '' # 密码为空时使用扫码登录
|
password: '' # 密码为空时使用扫码登录
|
||||||
encrypt: false # 是否开启密码加密
|
encrypt: false # 是否开启密码加密
|
||||||
relogin: # 重连设置
|
status: 0 # 在线状态 请参考 https://github.com/Mrs4s/go-cqhttp/blob/dev/docs/config.md#在线状态
|
||||||
|
relogin: # 重连设置
|
||||||
disabled: false
|
disabled: false
|
||||||
delay: 3 # 重连延迟, 单位秒
|
delay: 3 # 重连延迟, 单位秒
|
||||||
interval: 0 # 重连间隔
|
interval: 0 # 重连间隔
|
||||||
@ -42,7 +43,7 @@ message:
|
|||||||
extra-reply-data: false
|
extra-reply-data: false
|
||||||
|
|
||||||
output:
|
output:
|
||||||
# 日志等级 trace,debug,info,warn,error日志等级 trace,debug,info,warn,error
|
# 日志等级 trace,debug,info,warn,error
|
||||||
log-level: warn
|
log-level: warn
|
||||||
# 是否启用 DEBUG
|
# 是否启用 DEBUG
|
||||||
debug: false # 开启调试模式
|
debug: false # 开启调试模式
|
||||||
@ -79,10 +80,10 @@ servers:
|
|||||||
<<: *default # 引用默认中间件
|
<<: *default # 引用默认中间件
|
||||||
# 反向HTTP POST地址列表
|
# 反向HTTP POST地址列表
|
||||||
post:
|
post:
|
||||||
#- url: '' # 地址
|
#- url: '' # 地址
|
||||||
# secret: '' # 密钥
|
# secret: '' # 密钥
|
||||||
#- url: 127.0.0.1:5701 # 地址
|
#- url: 127.0.0.1:5701 # 地址
|
||||||
# secret: '' # 密钥
|
# secret: '' # 密钥
|
||||||
|
|
||||||
# 正向WS设置
|
# 正向WS设置
|
||||||
- ws:
|
- ws:
|
||||||
@ -109,11 +110,22 @@ servers:
|
|||||||
reconnect-interval: 3000
|
reconnect-interval: 3000
|
||||||
middlewares:
|
middlewares:
|
||||||
<<: *default # 引用默认中间件
|
<<: *default # 引用默认中间件
|
||||||
|
# pprof 性能分析服务器, 一般情况下不需要启用.
|
||||||
|
# 如果遇到性能问题请上传报告给开发者处理
|
||||||
|
# 注意: pprof服务不支持中间件、不支持鉴权. 请不要开放到公网
|
||||||
|
- pprof:
|
||||||
|
# 是否禁用pprof性能分析服务器
|
||||||
|
disabled: true
|
||||||
|
# pprof服务器监听地址
|
||||||
|
host: 127.0.0.1
|
||||||
|
# pprof服务器监听端口
|
||||||
|
port: 7700
|
||||||
|
|
||||||
# 可添加更多
|
# 可添加更多
|
||||||
#- ws-reverse:
|
#- ws-reverse:
|
||||||
#- ws:
|
#- ws:
|
||||||
#- http:
|
#- http:
|
||||||
|
#- pprof:
|
||||||
|
|
||||||
database: # 数据库相关设置
|
database: # 数据库相关设置
|
||||||
leveldb:
|
leveldb:
|
||||||
|
4
go.mod
4
go.mod
@ -4,8 +4,9 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20210406093140-5ec6c651b797
|
github.com/Mrs4s/MiraiGo v0.0.0-20210411120128-5a90a592d071
|
||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
|
github.com/gin-contrib/pprof v1.3.0 // 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.6
|
github.com/guonaihong/gout v0.1.6
|
||||||
@ -25,6 +26,7 @@ require (
|
|||||||
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60
|
github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60
|
||||||
github.com/willf/bitset v1.1.11 // indirect
|
github.com/willf/bitset v1.1.11 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
|
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect
|
||||||
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6
|
golang.org/x/term v0.0.0-20210317153231-de623e64d2a6
|
||||||
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
|
||||||
|
9
go.sum
9
go.sum
@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
|
|||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII=
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII=
|
||||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
|
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk=
|
||||||
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-20210406093140-5ec6c651b797 h1:u6jJ6bbYghAEM1DVe0SQKoIVva6od7fsdFRRC15DKMw=
|
github.com/Mrs4s/MiraiGo v0.0.0-20210411120128-5a90a592d071 h1:+1TizhfM/MkdPjnVS0VKBd2ZMML9UGFgewn3p/xCKxg=
|
||||||
github.com/Mrs4s/MiraiGo v0.0.0-20210406093140-5ec6c651b797/go.mod h1:NjiWhlvGxwv1ftOWIoiFa/OzklnAYI4YqNexFOKSZKw=
|
github.com/Mrs4s/MiraiGo v0.0.0-20210411120128-5a90a592d071/go.mod h1:NjiWhlvGxwv1ftOWIoiFa/OzklnAYI4YqNexFOKSZKw=
|
||||||
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=
|
||||||
@ -14,9 +14,12 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
|||||||
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
||||||
|
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
||||||
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.6.0/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.0/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
|
github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
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 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
||||||
@ -134,6 +137,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
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/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk=
|
||||||
|
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
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=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
151
main.go
151
main.go
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
@ -18,6 +17,8 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/MiraiGo/binary"
|
||||||
|
|
||||||
"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/Mrs4s/go-cqhttp/global/config"
|
"github.com/Mrs4s/go-cqhttp/global/config"
|
||||||
@ -41,6 +42,15 @@ var (
|
|||||||
c string
|
c string
|
||||||
d bool
|
d bool
|
||||||
h bool
|
h bool
|
||||||
|
|
||||||
|
// 允许通过配置文件设置的状态列表
|
||||||
|
allowStatus = [...]client.UserOnlineStatus{
|
||||||
|
client.StatusOnline, client.StatusAway, client.StatusInvisible, client.StatusBusy,
|
||||||
|
client.StatusListening, client.StatusConstellation, client.StatusWeather, client.StatusMeetSpring,
|
||||||
|
client.StatusTimi, client.StatusEatChicken, client.StatusLoving, client.StatusWangWang, client.StatusCookedRice,
|
||||||
|
client.StatusStudy, client.StatusStayUp, client.StatusPlayBall, client.StatusSignal, client.StatusStudyOnline,
|
||||||
|
client.StatusGaming, client.StatusVacationing, client.StatusWatchingTV, client.StatusFitness,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -149,11 +159,6 @@ func main() {
|
|||||||
log.SetLevel(log.DebugLevel)
|
log.SetLevel(log.DebugLevel)
|
||||||
log.Warnf("已开启Debug模式.")
|
log.Warnf("已开启Debug模式.")
|
||||||
log.Debugf("开发交流群: 192548878")
|
log.Debugf("开发交流群: 192548878")
|
||||||
/*
|
|
||||||
if conf.WebUI == nil || !conf.WebUI.Enabled {
|
|
||||||
log.Warnf("警告: 在Debug模式下未启用WebUi服务, 将无法进行性能分析.")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
log.Info("用户交流群: 721829413")
|
log.Info("用户交流群: 721829413")
|
||||||
if !global.PathExists("device.json") {
|
if !global.PathExists("device.json") {
|
||||||
@ -269,33 +274,35 @@ func main() {
|
|||||||
log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. ")
|
log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. ")
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
/*
|
|
||||||
if conf.WebUI == nil {
|
|
||||||
conf.WebUI = &global.GoCQWebUI{
|
|
||||||
Enabled: true,
|
|
||||||
WebInput: false,
|
|
||||||
Host: "0.0.0.0",
|
|
||||||
WebUIPort: 9999,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if conf.WebUI.WebUIPort <= 0 {
|
|
||||||
conf.WebUI.WebUIPort = 9999
|
|
||||||
}
|
|
||||||
if conf.WebUI.Host == "" {
|
|
||||||
conf.WebUI.Host = "127.0.0.1"
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
global.Proxy = conf.Message.ProxyRewrite
|
global.Proxy = conf.Message.ProxyRewrite
|
||||||
// b := server.WebServer.Run(fmt.Sprintf("%s:%d", conf.WebUI.Host, conf.WebUI.WebUIPort), cli)
|
|
||||||
// c := server.Console
|
|
||||||
isQRCodeLogin := (conf.Account.Uin == 0 || len(conf.Account.Password) == 0) && !conf.Account.Encrypt
|
isQRCodeLogin := (conf.Account.Uin == 0 || len(conf.Account.Password) == 0) && !conf.Account.Encrypt
|
||||||
isTokenLogin := false
|
isTokenLogin := false
|
||||||
|
saveToken := func() {
|
||||||
|
global.AccountToken = cli.GenToken()
|
||||||
|
_ = ioutil.WriteFile("session.token", global.AccountToken, 0677)
|
||||||
|
}
|
||||||
if global.PathExists("session.token") {
|
if global.PathExists("session.token") {
|
||||||
token, err := ioutil.ReadFile("session.token")
|
token, err := ioutil.ReadFile("session.token")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
if conf.Account.Uin != 0 {
|
||||||
|
r := binary.NewReader(token)
|
||||||
|
cu := r.ReadInt64()
|
||||||
|
if cu != conf.Account.Uin {
|
||||||
|
log.Warnf("警告: 配置文件内的QQ号 (%v) 与缓存内的QQ号 (%v) 不相同", conf.Account.Uin, cu)
|
||||||
|
log.Warnf("1. 使用会话缓存继续.")
|
||||||
|
log.Warnf("2. 删除会话缓存并重启.")
|
||||||
|
log.Warnf("请选择: (5秒后自动选1)")
|
||||||
|
text := readLineTimeout(time.Second*5, "1")
|
||||||
|
if text == "2" {
|
||||||
|
_ = os.Remove("session.token")
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if err = cli.TokenLogin(token); err != nil {
|
if err = cli.TokenLogin(token); err != nil {
|
||||||
_ = os.Remove("session.token")
|
_ = os.Remove("session.token")
|
||||||
log.Warnf("恢复会话失败: %v , 尝试使用正常流程登录.", err)
|
log.Warnf("恢复会话失败: %v , 尝试使用正常流程登录.", err)
|
||||||
|
time.Sleep(time.Second)
|
||||||
} else {
|
} else {
|
||||||
isTokenLogin = true
|
isTokenLogin = true
|
||||||
}
|
}
|
||||||
@ -312,41 +319,52 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveToken := func() {
|
|
||||||
global.AccountToken = cli.GenToken()
|
|
||||||
_ = ioutil.WriteFile("session.token", global.AccountToken, 0677)
|
|
||||||
}
|
|
||||||
saveToken()
|
|
||||||
var times uint = 1 // 重试次数
|
var times uint = 1 // 重试次数
|
||||||
var reLoginLock sync.Mutex
|
var reLoginLock sync.Mutex
|
||||||
cli.OnDisconnected(func(q *client.QQClient, e *client.ClientDisconnectedEvent) {
|
cli.OnDisconnected(func(q *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||||||
reLoginLock.Lock()
|
reLoginLock.Lock()
|
||||||
defer reLoginLock.Unlock()
|
defer reLoginLock.Unlock()
|
||||||
log.Warnf("Bot已离线: %v", e.Message)
|
times = 1
|
||||||
if conf.Account.ReLogin.Disabled {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
if times > conf.Account.ReLogin.MaxTimes && conf.Account.ReLogin.MaxTimes != 0 {
|
|
||||||
log.Fatalf("Bot重连次数超过限制, 停止")
|
|
||||||
}
|
|
||||||
if conf.Account.ReLogin.Interval > 0 {
|
|
||||||
log.Warnf("将在 %v 秒后尝试重连. 重连次数:%v/%v", conf.Account.ReLogin.Interval, times, conf.Account.ReLogin.MaxTimes)
|
|
||||||
}
|
|
||||||
log.Warnf("尝试重连...")
|
|
||||||
if cli.Online {
|
if cli.Online {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := cli.TokenLogin(global.AccountToken); err == nil {
|
log.Warnf("Bot已离线: %v", e.Message)
|
||||||
saveToken()
|
time.Sleep(time.Second * time.Duration(conf.Account.ReLogin.Delay))
|
||||||
return
|
for {
|
||||||
}
|
if conf.Account.ReLogin.Disabled {
|
||||||
if isQRCodeLogin {
|
os.Exit(1)
|
||||||
log.Fatalf("快速重连失败")
|
}
|
||||||
}
|
if times > conf.Account.ReLogin.MaxTimes && conf.Account.ReLogin.MaxTimes != 0 {
|
||||||
if err := commonLogin(); err != nil {
|
log.Fatalf("Bot重连次数超过限制, 停止")
|
||||||
log.Fatalf("登录时发生致命错误: %v", err)
|
}
|
||||||
|
times++
|
||||||
|
if conf.Account.ReLogin.Interval > 0 {
|
||||||
|
log.Warnf("将在 %v 秒后尝试重连. 重连次数:%v/%v", conf.Account.ReLogin.Interval, times, conf.Account.ReLogin.MaxTimes)
|
||||||
|
time.Sleep(time.Second * time.Duration(conf.Account.ReLogin.Interval))
|
||||||
|
} else {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
log.Warnf("尝试重连...")
|
||||||
|
err := cli.TokenLogin(global.AccountToken)
|
||||||
|
if err == nil {
|
||||||
|
saveToken()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Warnf("快速重连失败: %v", err)
|
||||||
|
if isQRCodeLogin {
|
||||||
|
log.Fatalf("快速重连失败, 扫码登录无法恢复会话.")
|
||||||
|
}
|
||||||
|
log.Warnf("快速重连失败, 尝试普通登录. 这可能是因为其他端强行T下线导致的.")
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
if err := commonLogin(); err != nil {
|
||||||
|
log.Errorf("登录时发生致命错误: %v", err)
|
||||||
|
} else {
|
||||||
|
saveToken()
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
saveToken()
|
||||||
cli.AllowSlider = true
|
cli.AllowSlider = true
|
||||||
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
||||||
log.Info("开始加载好友列表...")
|
log.Info("开始加载好友列表...")
|
||||||
@ -355,6 +373,10 @@ func main() {
|
|||||||
log.Infof("开始加载群列表...")
|
log.Infof("开始加载群列表...")
|
||||||
global.Check(cli.ReloadGroupList(), true)
|
global.Check(cli.ReloadGroupList(), true)
|
||||||
log.Infof("共加载 %v 个群.", len(cli.GroupList))
|
log.Infof("共加载 %v 个群.", len(cli.GroupList))
|
||||||
|
if conf.Account.Status >= int32(len(allowStatus)) || conf.Account.Status < 0 {
|
||||||
|
conf.Account.Status = 0
|
||||||
|
}
|
||||||
|
cli.SetOnlineStatus(allowStatus[int(conf.Account.Status)])
|
||||||
bot := coolq.NewQQBot(cli, conf)
|
bot := coolq.NewQQBot(cli, conf)
|
||||||
_ = bot.Client
|
_ = bot.Client
|
||||||
if conf.Message.PostFormat != "string" && conf.Message.PostFormat != "array" {
|
if conf.Message.PostFormat != "string" && conf.Message.PostFormat != "array" {
|
||||||
@ -367,6 +389,8 @@ func main() {
|
|||||||
coolq.IgnoreInvalidCQCode = conf.Message.IgnoreInvalidCQCode
|
coolq.IgnoreInvalidCQCode = conf.Message.IgnoreInvalidCQCode
|
||||||
coolq.SplitURL = conf.Message.FixURL
|
coolq.SplitURL = conf.Message.FixURL
|
||||||
coolq.ForceFragmented = conf.Message.ForceFragment
|
coolq.ForceFragmented = conf.Message.ForceFragment
|
||||||
|
coolq.RemoveReplyAt = conf.Message.RemoveReplyAt
|
||||||
|
coolq.ExtraReplyData = conf.Message.ExtraReplyData
|
||||||
for _, m := range conf.Servers {
|
for _, m := range conf.Servers {
|
||||||
if h, ok := m["http"]; ok {
|
if h, ok := m["http"]; ok {
|
||||||
hc := new(config.HTTPServer)
|
hc := new(config.HTTPServer)
|
||||||
@ -392,6 +416,14 @@ func main() {
|
|||||||
go server.RunWebSocketClient(bot, rc)
|
go server.RunWebSocketClient(bot, rc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if p, ok := m["pprof"]; ok {
|
||||||
|
pc := new(config.PprofServer)
|
||||||
|
if err := p.Decode(pc); err != nil {
|
||||||
|
log.Warn("读取http配置失败 :", err)
|
||||||
|
} else {
|
||||||
|
go server.RunPprofServer(pc)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Info("资源初始化完成, 开始处理信息.")
|
log.Info("资源初始化完成, 开始处理信息.")
|
||||||
log.Info("アトリは、高性能ですから!")
|
log.Info("アトリは、高性能ですから!")
|
||||||
@ -439,15 +471,11 @@ func checkUpdate() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var res string
|
var res string
|
||||||
if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases").BindBody(&res).Do(); err != nil {
|
if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases/latest").BindBody(&res).Do(); err != nil {
|
||||||
log.Warnf("检查更新失败: %v", err)
|
log.Warnf("检查更新失败: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
detail := gjson.Parse(res)
|
info := gjson.Parse(res)
|
||||||
if len(detail.Array()) < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := detail.Array()[0]
|
|
||||||
if global.VersionNameCompare(coolq.Version, info.Get("tag_name").Str) {
|
if global.VersionNameCompare(coolq.Version, info.Get("tag_name").Str) {
|
||||||
log.Infof("当前有更新的 go-cqhttp 可供更新, 请前往 https://github.com/Mrs4s/go-cqhttp/releases 下载.")
|
log.Infof("当前有更新的 go-cqhttp 可供更新, 请前往 https://github.com/Mrs4s/go-cqhttp/releases 下载.")
|
||||||
log.Infof("当前版本: %v 最新版本: %v", coolq.Version, info.Get("tag_name").Str)
|
log.Infof("当前版本: %v 最新版本: %v", coolq.Version, info.Get("tag_name").Str)
|
||||||
@ -457,22 +485,13 @@ func checkUpdate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func selfUpdate(imageURL string) {
|
func selfUpdate(imageURL string) {
|
||||||
console := bufio.NewReader(os.Stdin)
|
|
||||||
readLine := func() (str string) {
|
|
||||||
str, _ = console.ReadString('\n')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Infof("正在检查更新.")
|
log.Infof("正在检查更新.")
|
||||||
var res string
|
var res string
|
||||||
if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases").BindBody(&res).Do(); err != nil {
|
if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases/latest").BindBody(&res).Do(); err != nil {
|
||||||
log.Warnf("检查更新失败: %v", err)
|
log.Warnf("检查更新失败: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
detail := gjson.Parse(res)
|
info := gjson.Parse(res)
|
||||||
if len(detail.Array()) < 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
info := detail.Array()[0]
|
|
||||||
version := info.Get("tag_name").Str
|
version := info.Get("tag_name").Str
|
||||||
if coolq.Version != version {
|
if coolq.Version != version {
|
||||||
log.Info("当前最新版本为 ", version)
|
log.Info("当前最新版本为 ", version)
|
||||||
|
@ -86,16 +86,26 @@ func RunHTTPServerAndClients(bot *coolq.CQBot, conf *config.HTTPServer) {
|
|||||||
if authToken != "" {
|
if authToken != "" {
|
||||||
s.engine.Use(func(c *gin.Context) {
|
s.engine.Use(func(c *gin.Context) {
|
||||||
auth := c.Request.Header.Get("Authorization")
|
auth := c.Request.Header.Get("Authorization")
|
||||||
switch {
|
if auth == "" {
|
||||||
case auth != "":
|
headAuth := c.Query("access_token")
|
||||||
if strings.SplitN(auth, " ", 2)[1] != authToken {
|
switch {
|
||||||
|
case headAuth == "":
|
||||||
c.AbortWithStatus(401)
|
c.AbortWithStatus(401)
|
||||||
|
return
|
||||||
|
case headAuth != authToken:
|
||||||
|
c.AbortWithStatus(403)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auth := strings.SplitN(auth, " ", 2)
|
||||||
|
switch {
|
||||||
|
case len(auth) != 2 || auth[1] == "":
|
||||||
|
c.AbortWithStatus(401)
|
||||||
|
return
|
||||||
|
case auth[1] != authToken:
|
||||||
|
c.AbortWithStatus(403)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case c.Query("access_token") != authToken:
|
|
||||||
c.AbortWithStatus(401)
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
c.Next()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
35
server/pprof.go
Normal file
35
server/pprof.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-contrib/pprof"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/Mrs4s/go-cqhttp/global/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RunPprofServer 启动 pprof 性能分析服务器
|
||||||
|
func RunPprofServer(conf *config.PprofServer) {
|
||||||
|
if conf.Disabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
engine := gin.New()
|
||||||
|
addr := fmt.Sprintf("%s:%d", conf.Host, conf.Port)
|
||||||
|
pprof.Register(engine)
|
||||||
|
go func() {
|
||||||
|
log.Infof("pprof debug 服务器已启动: %v/debug/pprof", addr)
|
||||||
|
log.Warnf("警告: pprof 服务不支持鉴权, 请不要运行在公网.")
|
||||||
|
if err := engine.Run(addr); err != nil && err != http.ErrServerClosed {
|
||||||
|
log.Error(err)
|
||||||
|
log.Infof("pprof 服务启动失败, 请检查端口是否被占用.")
|
||||||
|
log.Warnf("将在五秒后退出.")
|
||||||
|
time.Sleep(time.Second * 5)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
@ -264,15 +264,29 @@ func (c *WebSocketClient) onBotPushEvent(m *bytes.Buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *webSocketServer) event(w http.ResponseWriter, r *http.Request) {
|
func (s *webSocketServer) auth(r *http.Request) (bool, int) {
|
||||||
if s.conf.AccessToken != "" {
|
if s.token != "" { // s.token == s.conf.AccessToken
|
||||||
if auth := r.URL.Query().Get("access_token"); auth != s.token {
|
var auth string
|
||||||
if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token {
|
if auth = r.URL.Query().Get("access_token"); auth == "" {
|
||||||
log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr)
|
headAuth := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
|
||||||
w.WriteHeader(401)
|
if len(headAuth) != 2 || headAuth[1] == "" {
|
||||||
return
|
return false, 401
|
||||||
}
|
}
|
||||||
|
auth = headAuth[1]
|
||||||
}
|
}
|
||||||
|
if auth != s.token {
|
||||||
|
log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr)
|
||||||
|
return false, 403
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *webSocketServer) event(w http.ResponseWriter, r *http.Request) {
|
||||||
|
isAuth, errReason := s.auth(r)
|
||||||
|
if !isAuth {
|
||||||
|
w.WriteHeader(errReason)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
c, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -296,14 +310,10 @@ 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 != "" {
|
isAuth, errReason := s.auth(r)
|
||||||
if auth := r.URL.Query().Get("access_token"); auth != s.token {
|
if !isAuth {
|
||||||
if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token {
|
w.WriteHeader(errReason)
|
||||||
log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr)
|
return
|
||||||
w.WriteHeader(401)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
c, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -319,14 +329,10 @@ 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 != "" {
|
isAuth, errReason := s.auth(r)
|
||||||
if auth := r.URL.Query().Get("access_token"); auth != s.token {
|
if !isAuth {
|
||||||
if auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2); len(auth) != 2 || auth[1] != s.token {
|
w.WriteHeader(errReason)
|
||||||
log.Warnf("已拒绝 %v 的 WebSocket 请求: Token鉴权失败", r.RemoteAddr)
|
return
|
||||||
w.WriteHeader(401)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
c, err := upgrader.Upgrade(w, r, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user