diff --git a/bot.go b/bot.go index a74894f..5e78bcf 100644 --- a/bot.go +++ b/bot.go @@ -2,7 +2,6 @@ package openwechat import ( "errors" - "fmt" "log" "net/url" ) @@ -42,13 +41,37 @@ func (b *Bot) GetCurrentUser() (*Self, error) { return b.self, nil } -func (b *Bot) HotLogin(storage HotReloadStorage) error { +func (b *Bot) HotLogin(storage HotReloadStorage, retry ...bool) error { b.isHot = true b.hotReloadStorage = storage - if err := storage.Load(); err != nil { + + var err error + + // 如果load出错了,就执行正常登陆逻辑 + // 第一次没有数据load都会出错的 + if err = storage.Load(); err != nil { return b.Login() } - cookies := storage.GetCookie() + + if err = b.hotLoginInit(); err != nil { + return err + } + + // 如果webInit出错,则说明可能身份信息已经失效 + // 如果retry为True的话,则进行正常登陆 + if err = b.webInit(); err != nil { + if len(retry) > 0 { + if retry[0] { + return b.Login() + } + } + } + return err +} + +// 热登陆初始化 +func (b *Bot) hotLoginInit() error { + cookies := b.hotReloadStorage.GetCookie() for u, ck := range cookies { path, err := url.Parse(u) if err != nil { @@ -56,9 +79,9 @@ func (b *Bot) HotLogin(storage HotReloadStorage) error { } b.Caller.Client.Jar.SetCookies(path, ck) } - b.storage.LoginInfo = storage.GetLoginInfo() - b.storage.Request = storage.GetBaseRequest() - return b.webInit() + b.storage.LoginInfo = b.hotReloadStorage.GetLoginInfo() + b.storage.Request = b.hotReloadStorage.GetBaseRequest() + return nil } // 用户登录 @@ -78,7 +101,7 @@ func (b *Bot) Login() error { } switch resp.Code { case statusSuccess: - return b.login(resp.Raw) + return b.handleLogin(resp.Raw) case statusScanned: if b.ScanCallBack != nil { b.ScanCallBack(resp.Raw) @@ -104,7 +127,7 @@ func (b *Bot) Logout() error { } // 登录逻辑 -func (b *Bot) login(data []byte) error { +func (b *Bot) handleLogin(data []byte) error { // 判断是否有登录回调,如果有执行它 if b.LoginCallBack != nil { b.LoginCallBack(data) @@ -171,19 +194,18 @@ func (b *Bot) asyncCall() error { resp *SyncCheckResponse ) for b.Alive() { - info := b.storage.LoginInfo - response := b.storage.Response - resp, err = b.Caller.SyncCheck(info, response) + // 长轮训检查是否有消息返回 + resp, err = b.Caller.SyncCheck(b.storage.LoginInfo, b.storage.Response) if err != nil { return err } // 如果不是正常的状态码返回,发生了错误,直接退出 if !resp.Success() { - return fmt.Errorf("unknow code got %s", resp.RetCode) + return resp } // 如果Selector不为0,则获取消息 if !resp.NorMal() { - if err = b.getMessage(); err != nil { + if err = b.getNewWechatMessage(); err != nil { return err } } @@ -199,7 +221,7 @@ func (b *Bot) stopAsyncCALL(err error) { } // 获取新的消息 -func (b *Bot) getMessage() error { +func (b *Bot) getNewWechatMessage() error { resp, err := b.Caller.WebWxSync(b.storage.Request, b.storage.Response, b.storage.LoginInfo) if err != nil { return err @@ -230,6 +252,11 @@ func (b *Bot) Block() error { return nil } +// 获取当前Bot崩溃的原因 +func (b *Bot) CrashReason() error { + return b.err +} + func NewBot(caller *Caller) *Bot { return &Bot{Caller: caller, storage: &Storage{}, exit: make(chan bool)} } diff --git a/items.go b/items.go index 85bd7ad..f14400c 100644 --- a/items.go +++ b/items.go @@ -1,6 +1,9 @@ package openwechat -import "fmt" +import ( + "errors" + "fmt" +) /* 一些网络返回信息的封装 @@ -43,25 +46,32 @@ func (b BaseResponse) Ok() bool { } func (b BaseResponse) Error() string { - switch b.Ret { + if err := getResponseErrorWithRetCode(b.Ret); err != nil { + return err.Error() + } + return "" +} + +func getResponseErrorWithRetCode(code int) error { + switch code { case 0: - return "" + return nil case 1: - return "param error" + return errors.New("param error") case -14: - return "ticket error" + return errors.New("ticket error") case 1100: - return "not login warn" + return errors.New("not login warn") case 1101: - return "not login check" + return errors.New("not login check") case 1102: - return "cookie invalid error" + return errors.New("cookie invalid error") case 1203: - return "login env error" + return errors.New("login env error") case 1205: - return "opt too often" + return errors.New("opt too often") default: - return fmt.Sprintf("base response ret code %d", b.Ret) + return fmt.Errorf("base response ret code %d", code) } } diff --git a/response.go b/response.go index 5138bc4..6077309 100644 --- a/response.go +++ b/response.go @@ -1,54 +1,54 @@ package openwechat import ( - "bytes" - "encoding/json" - "encoding/xml" - "net/http" + "bytes" + "encoding/json" + "encoding/xml" + "net/http" ) // Http请求的响应结构体封装 type ReturnResponse struct { - *http.Response - err error + *http.Response + err error } // Constructor for ReturnResponse func NewReturnResponse(response *http.Response, err error) *ReturnResponse { - return &ReturnResponse{Response: response, err: err} + return &ReturnResponse{Response: response, err: err} } // 获取当前请求的错误 func (r *ReturnResponse) Err() error { - return r.err + return r.err } // json序列化 func (r *ReturnResponse) ScanJSON(v interface{}) error { - if data, err := r.ReadAll(); err != nil { - return err - } else { - return json.Unmarshal(data, v) - } + if data, err := r.ReadAll(); err != nil { + return err + } else { + return json.Unmarshal(data, v) + } } // xml序列化 func (r *ReturnResponse) ScanXML(v interface{}) error { - if data, err := r.ReadAll(); err != nil { - return err - } else { - return xml.Unmarshal(data, v) - } + if data, err := r.ReadAll(); err != nil { + return err + } else { + return xml.Unmarshal(data, v) + } } // 读取请求体 func (r *ReturnResponse) ReadAll() ([]byte, error) { - if r.Err() != nil { - return nil, r.Err() - } - buffer := bytes.Buffer{} - if _, err := buffer.ReadFrom(r.Body); err != nil { - return nil, err - } - return buffer.Bytes(), nil + if r.Err() != nil { + return nil, r.Err() + } + buffer := bytes.Buffer{} + if _, err := buffer.ReadFrom(r.Body); err != nil { + return nil, err + } + return buffer.Bytes(), nil }