支持热登陆

This commit is contained in:
eatMoreApple 2021-04-27 18:36:50 +08:00
parent 2761e43c49
commit a8c646b33d
4 changed files with 491 additions and 351 deletions

41
bot.go
View File

@ -11,11 +11,14 @@ type Bot struct {
LoginCallBack func(body []byte)
UUIDCallback func(uuid string)
MessageHandler func(msg *Message)
isHot bool
err error
exit chan bool
Caller *Caller
self *Self
storage *Storage
hotReloadStorage HotReloadStorage
mode mode
}
// 判断当前用户是否正常在线
@ -39,6 +42,20 @@ func (b *Bot) GetCurrentUser() (*Self, error) {
return b.self, nil
}
func (b *Bot) HotLogin(storage HotReloadStorage) error {
b.isHot = true
b.hotReloadStorage = storage
if err := storage.Load(); err != nil {
return b.Login()
}
cookies := storage.GetCookie()
path := b.Caller.Client.getBaseUrl()
b.Caller.Client.Jar.SetCookies(path, cookies)
b.storage.LoginInfo = storage.GetLoginInfo()
b.storage.Request = storage.GetBaseRequest()
return b.webInit()
}
// 用户登录
// 该方法会一直阻塞,直到用户扫码登录,或者二维码过期
func (b *Bot) Login() error {
@ -105,8 +122,22 @@ func (b *Bot) login(data []byte) error {
// 将BaseRequest存到storage里面方便后续调用
b.storage.Request = request
if b.isHot {
cookies := b.Caller.Client.getCookies()
if err := b.hotReloadStorage.Dump(cookies, request, info); err != nil {
return err
}
}
return b.webInit()
}
func (b *Bot) webInit() error {
req := b.storage.Request
info := b.storage.LoginInfo
// 获取初始化的用户信息和一些必要的参数
resp, err := b.Caller.WebInit(request)
resp, err := b.Caller.WebInit(req)
if err != nil {
return err
}
@ -116,7 +147,7 @@ func (b *Bot) login(data []byte) error {
b.storage.Response = resp
// 通知手机客户端已经登录
if err = b.Caller.WebWxStatusNotify(request, resp, info); err != nil {
if err = b.Caller.WebWxStatusNotify(req, resp, info); err != nil {
return err
}
// 开启协程,轮训获取是否有新的消息返回
@ -208,12 +239,6 @@ func DefaultBot(modes ...mode) *Bot {
return NewBot(DefaultCaller(urlManager))
}
type Storage struct {
LoginInfo *LoginInfo
Request *BaseRequest
Response *WebInitResponse
}
func GetQrcodeUrl(uuid string) string {
return qrcodeUrl + uuid
}

View File

@ -220,3 +220,18 @@ func TestAgreeFriendsAdd(t *testing.T) {
}
bot.Block()
}
func TestHotLogin(t *testing.T) {
bot := defaultBot()
s := NewFileHotReloadStorage("2.json")
if err := bot.HotLogin(s); err != nil {
t.Error(err)
return
}
self, err := bot.GetCurrentUser()
if err != nil {
t.Error(err)
return
}
t.Log(self.NickName)
}

View File

@ -40,6 +40,16 @@ func DefaultClient(urlManager UrlManager) *Client {
return NewClient(client, urlManager)
}
func (c *Client) getBaseUrl() *url.URL {
path, _ := url.Parse(c.UrlManager.baseUrl)
return path
}
func (c *Client) getCookies() []*http.Cookie {
path := c.getBaseUrl()
return c.Jar.Cookies(path)
}
// 获取登录的uuid
func (c *Client) GetLoginUUID() (*http.Response, error) {
path, _ := url.Parse(jsLoginUrl)

View File

@ -1,3 +1,93 @@
package openwechat
import (
"bytes"
"encoding/json"
"net/http"
"os"
)
type Storage struct {
LoginInfo *LoginInfo
Request *BaseRequest
Response *WebInitResponse
}
type HotReloadStorage interface {
GetCookie() []*http.Cookie
GetBaseRequest() *BaseRequest
GetLoginInfo() *LoginInfo
Dump(cookies []*http.Cookie, req *BaseRequest, info *LoginInfo) error
Load() error
}
type FileHotReloadStorage struct {
Cookie []*http.Cookie
Req *BaseRequest
Info *LoginInfo
filename string
}
func (f *FileHotReloadStorage) Dump(cookies []*http.Cookie, req *BaseRequest, info *LoginInfo) error {
f.Cookie = cookies
f.Req = req
f.Info = info
var (
file *os.File
err error
)
_, err = os.Stat(f.filename)
if err != nil {
if os.IsNotExist(err) {
file, err = os.Create(f.filename)
if err != nil {
return err
}
}
}
if file == nil {
file, err = os.Open(f.filename)
}
if err != nil {
return err
}
defer file.Close()
data, err := json.Marshal(f)
if err != nil {
return err
}
_, err = file.Write(data)
return err
}
func (f *FileHotReloadStorage) Load() error {
file, err := os.Open(f.filename)
if err != nil {
return err
}
defer file.Close()
var buffer bytes.Buffer
if _, err := buffer.ReadFrom(file); err != nil {
return err
}
return json.Unmarshal(buffer.Bytes(), f)
}
func (f FileHotReloadStorage) GetCookie() []*http.Cookie {
return f.Cookie
}
func (f FileHotReloadStorage) GetBaseRequest() *BaseRequest {
return f.Req
}
func (f FileHotReloadStorage) GetLoginInfo() *LoginInfo {
return f.Info
}
func NewFileHotReloadStorage(filename string) *FileHotReloadStorage {
return &FileHotReloadStorage{filename: filename}
}