[perf]: 优化登录检查 (#203)
This commit is contained in:
parent
1eadbf8be6
commit
53478bad19
23
bot.go
23
bot.go
@ -6,19 +6,20 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/url"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
ScanCallBack func(body []byte) // 扫码回调,可获取扫码用户的头像
|
||||
LoginCallBack func(body []byte) // 登陆回调
|
||||
LogoutCallBack func(bot *Bot) // 退出回调
|
||||
UUIDCallback func(uuid string) // 获取UUID的回调函数
|
||||
SyncCheckCallback func(resp SyncCheckResponse) // 心跳回调
|
||||
MessageHandler MessageHandler // 获取消息成功的handle
|
||||
MessageErrorHandler func(err error) bool // 获取消息发生错误的handle, 返回true则尝试继续监听
|
||||
ScanCallBack func(body CheckLoginResponse) // 扫码回调,可获取扫码用户的头像
|
||||
LoginCallBack func(body CheckLoginResponse) // 登陆回调
|
||||
LogoutCallBack func(bot *Bot) // 退出回调
|
||||
UUIDCallback func(uuid string) // 获取UUID的回调函数
|
||||
SyncCheckCallback func(resp SyncCheckResponse) // 心跳回调
|
||||
MessageHandler MessageHandler // 获取消息成功的handle
|
||||
MessageErrorHandler func(err error) bool // 获取消息发生错误的handle, 返回true则尝试继续监听
|
||||
once sync.Once
|
||||
err error
|
||||
context context.Context
|
||||
@ -121,9 +122,9 @@ func (b *Bot) Logout() error {
|
||||
}
|
||||
|
||||
// HandleLogin 登录逻辑
|
||||
func (b *Bot) HandleLogin(data []byte) error {
|
||||
func (b *Bot) HandleLogin(path *url.URL) error {
|
||||
// 获取登录的一些基本的信息
|
||||
info, err := b.Caller.GetLoginInfo(data)
|
||||
info, err := b.Caller.GetLoginInfo(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -346,11 +347,11 @@ func DefaultBot(prepares ...BotPreparer) *Bot {
|
||||
// 获取二维码回调
|
||||
bot.UUIDCallback = PrintlnQrcodeUrl
|
||||
// 扫码回调
|
||||
bot.ScanCallBack = func(body []byte) {
|
||||
bot.ScanCallBack = func(_ CheckLoginResponse) {
|
||||
log.Println("扫码成功,请在手机上确认登录")
|
||||
}
|
||||
// 登录回调
|
||||
bot.LoginCallBack = func(body []byte) {
|
||||
bot.LoginCallBack = func(_ CheckLoginResponse) {
|
||||
log.Println("登录成功")
|
||||
}
|
||||
// 心跳回调函数
|
||||
|
20
bot_login.go
20
bot_login.go
@ -225,8 +225,8 @@ type LoginChecker struct {
|
||||
Bot *Bot
|
||||
Tip string
|
||||
UUIDCallback func(uuid string)
|
||||
LoginCallBack func(body []byte)
|
||||
ScanCallBack func(body []byte)
|
||||
LoginCallBack func(body CheckLoginResponse)
|
||||
ScanCallBack func(body CheckLoginResponse)
|
||||
}
|
||||
|
||||
func (l *LoginChecker) CheckLogin() error {
|
||||
@ -242,23 +242,31 @@ func (l *LoginChecker) CheckLogin() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
code, err := resp.Code()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tip == "1" {
|
||||
tip = "0"
|
||||
}
|
||||
switch resp.Code {
|
||||
switch code {
|
||||
case StatusSuccess:
|
||||
// 判断是否有登录回调,如果有执行它
|
||||
if err = l.Bot.HandleLogin(resp.Raw); err != nil {
|
||||
redirectURL, err := resp.RedirectURL()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = l.Bot.HandleLogin(redirectURL); err != nil {
|
||||
return err
|
||||
}
|
||||
if cb := l.LoginCallBack; cb != nil {
|
||||
cb(resp.Raw)
|
||||
cb(resp)
|
||||
}
|
||||
return nil
|
||||
case StatusScanned:
|
||||
// 执行扫码回调
|
||||
if cb := l.ScanCallBack; cb != nil {
|
||||
cb(resp.Raw)
|
||||
cb(resp)
|
||||
}
|
||||
case StatusTimeout:
|
||||
return ErrLoginTimeout
|
||||
|
24
caller.go
24
caller.go
@ -50,7 +50,7 @@ func (c *Caller) GetLoginUUID() (string, error) {
|
||||
}
|
||||
|
||||
// CheckLogin 检查是否登录成功
|
||||
func (c *Caller) CheckLogin(uuid, tip string) (*CheckLoginResponse, error) {
|
||||
func (c *Caller) CheckLogin(uuid, tip string) (CheckLoginResponse, error) {
|
||||
resp, err := c.Client.CheckLogin(uuid, tip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -61,29 +61,13 @@ func (c *Caller) CheckLogin(uuid, tip string) (*CheckLoginResponse, error) {
|
||||
if _, err := buffer.ReadFrom(resp.Body); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 正则匹配检测的code
|
||||
// 具体code参考global.go
|
||||
results := statusCodeRegexp.FindSubmatch(buffer.Bytes())
|
||||
if len(results) != 2 {
|
||||
return nil, errors.New("error status code match")
|
||||
}
|
||||
code := string(results[1])
|
||||
return &CheckLoginResponse{Code: code, Raw: buffer.Bytes()}, nil
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// GetLoginInfo 获取登录信息
|
||||
func (c *Caller) GetLoginInfo(body []byte) (*LoginInfo, error) {
|
||||
func (c *Caller) GetLoginInfo(path *url.URL) (*LoginInfo, error) {
|
||||
// 从响应体里面获取需要跳转的url
|
||||
results := redirectUriRegexp.FindSubmatch(body)
|
||||
if len(results) != 2 {
|
||||
return nil, errors.New("redirect url does not match")
|
||||
}
|
||||
path, err := url.Parse(string(results[1]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.Client.Domain = WechatDomain(path.Host)
|
||||
resp, err := c.Client.GetLoginInfo(path.String())
|
||||
resp, err := c.Client.GetLoginInfo(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -133,8 +133,9 @@ func (c *Client) CheckLogin(uuid, tip string) (*http.Response, error) {
|
||||
}
|
||||
|
||||
// GetLoginInfo 请求获取LoginInfo
|
||||
func (c *Client) GetLoginInfo(path string) (*http.Response, error) {
|
||||
return c.mode.GetLoginInfo(c, path)
|
||||
func (c *Client) GetLoginInfo(path *url.URL) (*http.Response, error) {
|
||||
c.Domain = WechatDomain(path.Host)
|
||||
return c.mode.GetLoginInfo(c, path.String())
|
||||
}
|
||||
|
||||
// WebInit 请求获取初始化信息
|
||||
|
@ -7,6 +7,7 @@ import (
|
||||
var (
|
||||
uuidRegexp = regexp.MustCompile(`uuid = "(.*?)";`)
|
||||
statusCodeRegexp = regexp.MustCompile(`window.code=(\d+);`)
|
||||
avatarRegexp = regexp.MustCompile(`window.userAvatar = '(.*)';`)
|
||||
syncCheckRegexp = regexp.MustCompile(`window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}`)
|
||||
redirectUriRegexp = regexp.MustCompile(`window.redirect_uri="(.*?)"`)
|
||||
)
|
||||
|
48
items.go
48
items.go
@ -2,6 +2,8 @@ package openwechat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
/*
|
||||
@ -117,9 +119,49 @@ type WebWxBatchContactResponse struct {
|
||||
ContactList []*User
|
||||
}
|
||||
|
||||
type CheckLoginResponse struct {
|
||||
Code string
|
||||
Raw []byte
|
||||
// CheckLoginResponse 检查登录状态的响应body
|
||||
type CheckLoginResponse []byte
|
||||
|
||||
// RedirectURL 重定向的URL
|
||||
func (c CheckLoginResponse) RedirectURL() (*url.URL, error) {
|
||||
code, err := c.Code()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if code != StatusSuccess {
|
||||
return nil, fmt.Errorf("expect status code %s, but got %s", StatusSuccess, code)
|
||||
}
|
||||
results := redirectUriRegexp.FindSubmatch(c)
|
||||
if len(results) != 2 {
|
||||
return nil, errors.New("redirect url does not match")
|
||||
}
|
||||
return url.Parse(string(results[1]))
|
||||
}
|
||||
|
||||
// Code 获取当前的登录检查状态的代码
|
||||
func (c CheckLoginResponse) Code() (string, error) {
|
||||
results := statusCodeRegexp.FindSubmatch(c)
|
||||
if len(results) != 2 {
|
||||
return "", errors.New("error status code match")
|
||||
}
|
||||
code := string(results[1])
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// Avatar 获取扫码后的用户头像, base64编码
|
||||
func (c CheckLoginResponse) Avatar() (string, error) {
|
||||
code, err := c.Code()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if code != StatusScanned {
|
||||
return "", nil
|
||||
}
|
||||
results := avatarRegexp.FindSubmatch(c)
|
||||
if len(results) != 2 {
|
||||
return "", errors.New("avatar does not match")
|
||||
}
|
||||
return string(results[1]), nil
|
||||
}
|
||||
|
||||
type MessageResponse struct {
|
||||
|
Loading…
x
Reference in New Issue
Block a user