mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-04 19:17:37 +08:00
Merge pull request #624 from qianjunakasumi/dev
修复登录和重连逻辑,支持重连的验证码等处理,Fix #620
This commit is contained in:
commit
02581ff8a9
@ -117,23 +117,40 @@ func (s *webServer) Run(addr string, cli *client.QQClient) *coolq.CQBot {
|
||||
return b
|
||||
}
|
||||
|
||||
func (s *webServer) Dologin() {
|
||||
// logincore 登录核心实现
|
||||
func (s *webServer) logincore(relogin bool) {
|
||||
|
||||
s.Console = bufio.NewReader(os.Stdin)
|
||||
readLine := func() (str string) {
|
||||
str, _ = s.Console.ReadString('\n')
|
||||
str = strings.TrimSpace(str)
|
||||
return
|
||||
}
|
||||
conf := GetConf()
|
||||
cli := s.Cli
|
||||
cli.AllowSlider = true
|
||||
rsp, err := cli.Login()
|
||||
count := 0
|
||||
for {
|
||||
global.Check(err)
|
||||
|
||||
if s.Cli.Online {
|
||||
log.Warn("Bot已登录")
|
||||
return
|
||||
}
|
||||
|
||||
var times uint = 1 // 重试次数
|
||||
for res, err := s.Cli.Login(); ; res, err = s.Cli.Login() {
|
||||
|
||||
var text string
|
||||
if !rsp.Success {
|
||||
switch rsp.Error {
|
||||
count := 0
|
||||
|
||||
if res == nil {
|
||||
goto Relogin
|
||||
}
|
||||
|
||||
Again: // 不执行 s.Cli.Login() 的循环,适用输入验证码等更新 res 的操作
|
||||
if err == nil && res.Success { // 登录成功
|
||||
break
|
||||
} else if err == client.ErrAlreadyOnline {
|
||||
break
|
||||
}
|
||||
log.Error("登录遇到错误: " + err.Error())
|
||||
|
||||
switch res.Error {
|
||||
case client.SliderNeededError:
|
||||
log.Warnf("登录需要滑条验证码, 请选择解决方案: ")
|
||||
log.Warnf("1. 自行抓包. (推荐)")
|
||||
@ -143,183 +160,164 @@ func (s *webServer) Dologin() {
|
||||
log.Warn("请输入(1 - 3): ")
|
||||
text = readLine()
|
||||
if strings.Contains(text, "1") {
|
||||
log.Warnf("请用浏览器打开 -> %v <- 并获取Ticket.", rsp.VerifyUrl)
|
||||
log.Warnf("请用浏览器打开 -> %v <- 并获取Ticket.", res.VerifyUrl)
|
||||
log.Warn("请输入Ticket: (Enter 提交)")
|
||||
text = readLine()
|
||||
rsp, err = cli.SubmitTicket(strings.TrimSpace(text))
|
||||
continue
|
||||
res, err = s.Cli.SubmitTicket(strings.TrimSpace(text))
|
||||
goto Again
|
||||
}
|
||||
if strings.Contains(text, "3") {
|
||||
cli.AllowSlider = false
|
||||
cli.Disconnect()
|
||||
rsp, err = cli.Login()
|
||||
s.Cli.AllowSlider = false
|
||||
s.Cli.Disconnect()
|
||||
continue
|
||||
}
|
||||
id := utils.RandomStringRange(6, "0123456789")
|
||||
log.Warnf("滑块ID为 %v 请在30S内处理.", id)
|
||||
ticket, err := global.GetSliderTicket(rsp.VerifyUrl, id)
|
||||
ticket, err := global.GetSliderTicket(res.VerifyUrl, id)
|
||||
if err != nil {
|
||||
log.Warnf("错误: " + err.Error())
|
||||
os.Exit(0)
|
||||
}
|
||||
rsp, err = cli.SubmitTicket(ticket)
|
||||
res, err = s.Cli.SubmitTicket(ticket)
|
||||
if err != nil {
|
||||
log.Warnf("错误: " + err.Error())
|
||||
os.Exit(0)
|
||||
continue // 尝试重新登录
|
||||
}
|
||||
continue
|
||||
goto Again
|
||||
case client.NeedCaptcha:
|
||||
_ = ioutil.WriteFile("captcha.jpg", rsp.CaptchaImage, 0644)
|
||||
img, _, _ := image.Decode(bytes.NewReader(rsp.CaptchaImage))
|
||||
_ = ioutil.WriteFile("captcha.jpg", res.CaptchaImage, 0644)
|
||||
img, _, _ := image.Decode(bytes.NewReader(res.CaptchaImage))
|
||||
fmt.Println(asciiart.New("image", img).Art)
|
||||
if conf.WebUI != nil && conf.WebUI.WebInput {
|
||||
log.Warnf("请输入验证码 (captcha.jpg): (http://%s:%d/admin/do_web_write 输入)", conf.WebUI.Host, conf.WebUI.WebUIPort)
|
||||
if s.Conf.WebUI != nil && s.Conf.WebUI.WebInput {
|
||||
log.Warnf("请输入验证码 (captcha.jpg): (http://%s:%d/admin/do_web_write 输入)", s.Conf.WebUI.Host, s.Conf.WebUI.WebUIPort)
|
||||
text = <-WebInput
|
||||
} else {
|
||||
log.Warn("请输入验证码 (captcha.jpg): (Enter 提交)")
|
||||
text = readLine()
|
||||
}
|
||||
rsp, err = cli.SubmitCaptcha(strings.ReplaceAll(text, "\n", ""), rsp.CaptchaSign)
|
||||
global.DelFile("captcha.jpg")
|
||||
continue
|
||||
res, err = s.Cli.SubmitCaptcha(strings.ReplaceAll(text, "\n", ""), res.CaptchaSign)
|
||||
goto Again
|
||||
case client.SMSNeededError:
|
||||
log.Warnf("账号已开启设备锁, 按下 Enter 向手机 %v 发送短信验证码.", rsp.SMSPhone)
|
||||
log.Warnf("账号已开启设备锁, 按下 Enter 向手机 %v 发送短信验证码.", res.SMSPhone)
|
||||
readLine()
|
||||
if !cli.RequestSMS() {
|
||||
if !s.Cli.RequestSMS() {
|
||||
log.Warnf("发送验证码失败,可能是请求过于频繁.")
|
||||
time.Sleep(time.Second * 5)
|
||||
os.Exit(0)
|
||||
continue
|
||||
}
|
||||
log.Warn("请输入短信验证码: (Enter 提交)")
|
||||
text = readLine()
|
||||
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||||
continue
|
||||
res, err = s.Cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||||
goto Again
|
||||
case client.SMSOrVerifyNeededError:
|
||||
log.Warnf("账号已开启设备锁,请选择验证方式:")
|
||||
log.Warnf("1. 向手机 %v 发送短信验证码", rsp.SMSPhone)
|
||||
log.Warnf("1. 向手机 %v 发送短信验证码", res.SMSPhone)
|
||||
log.Warnf("2. 使用手机QQ扫码验证.")
|
||||
log.Warn("请输入(1 - 2): ")
|
||||
text = readLine()
|
||||
if strings.Contains(text, "1") {
|
||||
if !cli.RequestSMS() {
|
||||
if !s.Cli.RequestSMS() {
|
||||
log.Warnf("发送验证码失败,可能是请求过于频繁.")
|
||||
time.Sleep(time.Second * 5)
|
||||
os.Exit(0)
|
||||
}
|
||||
log.Warn("请输入短信验证码: (Enter 提交)")
|
||||
text = readLine()
|
||||
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||||
continue
|
||||
res, err = s.Cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||||
goto Again
|
||||
}
|
||||
log.Warnf("请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
||||
log.Warnf("请前往 -> %v <- 验证.", res.VerifyUrl)
|
||||
log.Infof("按 Enter 继续....")
|
||||
readLine()
|
||||
os.Exit(0)
|
||||
return
|
||||
continue
|
||||
case client.UnsafeDeviceError:
|
||||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
||||
if conf.WebUI != nil && conf.WebUI.WebInput {
|
||||
log.Infof(" (http://%s:%d/admin/do_web_write 确认后继续)....", conf.WebUI.Host, conf.WebUI.WebUIPort)
|
||||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证.", res.VerifyUrl)
|
||||
if s.Conf.WebUI != nil && s.Conf.WebUI.WebInput {
|
||||
log.Infof(" (http://%s:%d/admin/do_web_write 确认后继续)....", s.Conf.WebUI.Host, s.Conf.WebUI.WebUIPort)
|
||||
text = <-WebInput
|
||||
} else {
|
||||
log.Infof("按 Enter 继续....")
|
||||
readLine()
|
||||
}
|
||||
log.Info(text)
|
||||
os.Exit(0)
|
||||
return
|
||||
continue
|
||||
case client.OtherLoginError, client.UnknownLoginError:
|
||||
msg := rsp.ErrorMessage
|
||||
msg := res.ErrorMessage
|
||||
if strings.Contains(msg, "版本") {
|
||||
msg = "密码错误或账号被冻结"
|
||||
}
|
||||
if strings.Contains(msg, "上网环境") && count < 5 {
|
||||
cli.Disconnect()
|
||||
rsp, err = cli.Login()
|
||||
count++
|
||||
s.Cli.Disconnect()
|
||||
log.Warnf("错误: 当前上网环境异常. 将更换服务器并重试.")
|
||||
count++
|
||||
time.Sleep(time.Second)
|
||||
continue
|
||||
}
|
||||
if strings.Contains(msg, "冻结") {
|
||||
log.Fatalf("账号被冻结, 放弃重连")
|
||||
}
|
||||
log.Warnf("登录失败: %v", msg)
|
||||
log.Infof("按 Enter 继续....")
|
||||
readLine()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
Relogin:
|
||||
if relogin {
|
||||
if times > s.Conf.ReLogin.MaxReloginTimes && s.Conf.ReLogin.MaxReloginTimes != 0 {
|
||||
log.Fatal("重连失败: 重连次数达到设置的上限值")
|
||||
s.bot.Release()
|
||||
return
|
||||
}
|
||||
log.Warnf("将在 %v 秒后尝试重连. 重连次数:%v", s.Conf.ReLogin.ReLoginDelay, times)
|
||||
times++
|
||||
time.Sleep(time.Second * time.Duration(s.Conf.ReLogin.ReLoginDelay))
|
||||
s.Cli.Disconnect()
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
||||
time.Sleep(time.Second)
|
||||
if relogin {
|
||||
log.Info("重连成功")
|
||||
}
|
||||
}
|
||||
|
||||
// Dologin 主程序登录
|
||||
func (s *webServer) Dologin() {
|
||||
|
||||
s.Cli.AllowSlider = true
|
||||
s.logincore(false)
|
||||
log.Infof("登录成功 欢迎使用: %v", s.Cli.Nickname)
|
||||
log.Info("开始加载好友列表...")
|
||||
global.Check(cli.ReloadFriendList())
|
||||
log.Infof("共加载 %v 个好友.", len(cli.FriendList))
|
||||
global.Check(s.Cli.ReloadFriendList())
|
||||
log.Infof("共加载 %v 个好友.", len(s.Cli.FriendList))
|
||||
log.Infof("开始加载群列表...")
|
||||
global.Check(cli.ReloadGroupList())
|
||||
log.Infof("共加载 %v 个群.", len(cli.GroupList))
|
||||
s.bot = coolq.NewQQBot(cli, conf)
|
||||
if conf.PostMessageFormat != "string" && conf.PostMessageFormat != "array" {
|
||||
global.Check(s.Cli.ReloadGroupList())
|
||||
log.Infof("共加载 %v 个群.", len(s.Cli.GroupList))
|
||||
s.bot = coolq.NewQQBot(s.Cli, s.Conf)
|
||||
if s.Conf.PostMessageFormat != "string" && s.Conf.PostMessageFormat != "array" {
|
||||
log.Warnf("post_message_format 配置错误, 将自动使用 string")
|
||||
coolq.SetMessageFormat("string")
|
||||
} else {
|
||||
coolq.SetMessageFormat(conf.PostMessageFormat)
|
||||
coolq.SetMessageFormat(s.Conf.PostMessageFormat)
|
||||
}
|
||||
if conf.RateLimit.Enabled {
|
||||
global.InitLimiter(conf.RateLimit.Frequency, conf.RateLimit.BucketSize)
|
||||
if s.Conf.RateLimit.Enabled {
|
||||
global.InitLimiter(s.Conf.RateLimit.Frequency, s.Conf.RateLimit.BucketSize)
|
||||
}
|
||||
log.Info("正在加载事件过滤器.")
|
||||
global.BootFilter()
|
||||
coolq.IgnoreInvalidCQCode = conf.IgnoreInvalidCQCode
|
||||
coolq.SplitURL = conf.FixURL
|
||||
coolq.ForceFragmented = conf.ForceFragmented
|
||||
coolq.IgnoreInvalidCQCode = s.Conf.IgnoreInvalidCQCode
|
||||
coolq.SplitURL = s.Conf.FixURL
|
||||
coolq.ForceFragmented = s.Conf.ForceFragmented
|
||||
log.Info("资源初始化完成, 开始处理信息.")
|
||||
log.Info("アトリは、高性能ですから!")
|
||||
cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||||
if conf.ReLogin.Enabled {
|
||||
conf.ReLogin.Enabled = false
|
||||
defer func() { conf.ReLogin.Enabled = true }()
|
||||
var times uint = 1
|
||||
for {
|
||||
if cli.Online {
|
||||
log.Warn("Bot已登录")
|
||||
|
||||
s.Cli.OnDisconnected(func(q *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||||
if !s.Conf.ReLogin.Enabled {
|
||||
return
|
||||
}
|
||||
if times > conf.ReLogin.MaxReloginTimes && conf.ReLogin.MaxReloginTimes != 0 {
|
||||
break
|
||||
}
|
||||
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)
|
||||
cli.Disconnect()
|
||||
continue
|
||||
}
|
||||
if !rsp.Success {
|
||||
switch rsp.Error {
|
||||
case client.NeedCaptcha:
|
||||
log.Fatalf("重连失败: 需要验证码. (验证码处理正在开发中)")
|
||||
case client.UnsafeDeviceError:
|
||||
log.Fatalf("重连失败: 设备锁")
|
||||
default:
|
||||
log.Errorf("重连失败: %v", rsp.ErrorMessage)
|
||||
if strings.Contains(rsp.ErrorMessage, "冻结") {
|
||||
log.Fatalf("账号被冻结, 放弃重连")
|
||||
}
|
||||
cli.Disconnect()
|
||||
continue
|
||||
}
|
||||
}
|
||||
log.Info("重连成功")
|
||||
return
|
||||
}
|
||||
log.Fatal("重连失败: 重连次数达到设置的上限值")
|
||||
}
|
||||
s.bot.Release()
|
||||
log.Fatalf("Bot已离线:%v", e.Message)
|
||||
log.Warnf("Bot已离线 (%v),尝试重连", e.Message)
|
||||
s.logincore(true)
|
||||
})
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user