Skip to content

Commit 396a4f2

Browse files
author
eatmoreapple
committed
提高bot的稳定性
1 parent 2f52315 commit 396a4f2

File tree

1 file changed

+58
-45
lines changed

1 file changed

+58
-45
lines changed

bot.go

Lines changed: 58 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ import (
1212
)
1313

1414
type Bot struct {
15-
ScanCallBack func(body []byte) // 扫码回调,可获取扫码用户的头像
16-
LoginCallBack func(body []byte) // 登陆回调
17-
LogoutCallBack func(bot *Bot) // 退出回调
18-
UUIDCallback func(uuid string) // 获取UUID的回调函数
19-
SyncCheckCallback func(resp SyncCheckResponse) // 心跳回调
20-
MessageHandler MessageHandler // 获取消息成功的handle
21-
GetMessageErrorHandler func(err error) // 获取消息发生错误的handle
22-
isHot bool // 是否为热登录模式
23-
once sync.Once
24-
err error
25-
context context.Context
26-
cancel context.CancelFunc
27-
Caller *Caller
28-
self *Self
29-
Storage *Storage
30-
HotReloadStorage HotReloadStorage
15+
ScanCallBack func(body []byte) // 扫码回调,可获取扫码用户的头像
16+
LoginCallBack func(body []byte) // 登陆回调
17+
LogoutCallBack func(bot *Bot) // 退出回调
18+
UUIDCallback func(uuid string) // 获取UUID的回调函数
19+
SyncCheckCallback func(resp SyncCheckResponse) // 心跳回调
20+
MessageHandler MessageHandler // 获取消息成功的handle
21+
MessageErrorHandler func(err error) bool // 获取消息发生错误的handle, 返回true则尝试继续监听
22+
isHot bool // 是否为热登录模式
23+
once sync.Once
24+
err error
25+
context context.Context
26+
cancel context.CancelFunc
27+
Caller *Caller
28+
self *Self
29+
Storage *Storage
30+
HotReloadStorage HotReloadStorage
3131
}
3232

3333
// Alive 判断当前用户是否正常在线
@@ -154,7 +154,7 @@ func (b *Bot) Logout() error {
154154
if err := b.Caller.Logout(info); err != nil {
155155
return err
156156
}
157-
b.stopAsyncCALL(errors.New("logout"))
157+
b.stopSyncCheck(errors.New("logout"))
158158
return nil
159159
}
160160
return errors.New("user not login")
@@ -214,19 +214,26 @@ func (b *Bot) WebInit() error {
214214

215215
// FIX: 当bot在线的情况下执行热登录,会开启多次事件监听
216216
go b.once.Do(func() {
217-
if b.GetMessageErrorHandler == nil {
218-
b.GetMessageErrorHandler = b.stopAsyncCALL
217+
if b.MessageErrorHandler == nil {
218+
b.MessageErrorHandler = b.stopSyncCheck
219219
}
220-
if err = b.asyncCall(); err != nil {
221-
b.GetMessageErrorHandler(err)
220+
for {
221+
err := b.syncCheck()
222+
if err == nil {
223+
continue
224+
}
225+
// 判断是否继续, 如果不继续则退出
226+
if goon := b.MessageErrorHandler(err); !goon {
227+
break
228+
}
222229
}
223230
})
224231
return nil
225232
}
226233

227234
// 轮询请求
228235
// 根据状态码判断是否有新的请求
229-
func (b *Bot) asyncCall() error {
236+
func (b *Bot) syncCheck() error {
230237
var (
231238
err error
232239
resp *SyncCheckResponse
@@ -247,38 +254,47 @@ func (b *Bot) asyncCall() error {
247254
}
248255
// 如果Selector不为0,则获取消息
249256
if !resp.NorMal() {
250-
if err = b.getNewWechatMessage(); err != nil {
257+
messages, err := b.syncMessage()
258+
if err != nil {
251259
return err
252260
}
261+
if b.MessageHandler == nil {
262+
continue
263+
}
264+
for _, message := range messages {
265+
message.init(b)
266+
// 默认同步调用
267+
// 如果异步调用则需自行处理
268+
// 如配合 openwechat.MessageMatchDispatcher 使用
269+
b.MessageHandler(message)
270+
}
253271
}
254272
}
255273
return err
256274
}
257275

258276
// 当获取消息发生错误时, 默认的错误处理行为
259-
func (b *Bot) stopAsyncCALL(err error) {
277+
func (b *Bot) stopSyncCheck(err error) bool {
260278
if IsNetworkError(err) {
261279
log.Println(err)
262-
return
280+
// 继续监听
281+
return true
263282
}
264283
b.err = err
265284
b.Exit()
266285
log.Printf("exit with : %s", err.Error())
286+
return false
267287
}
268288

269289
// 获取新的消息
270-
func (b *Bot) getNewWechatMessage() error {
290+
func (b *Bot) syncMessage() ([]*Message, error) {
271291
resp, err := b.Caller.WebWxSync(b.Storage.Request, b.Storage.Response, b.Storage.LoginInfo)
272292
if err != nil {
273-
return err
293+
return nil, err
274294
}
275295
// 更新SyncKey并且重新存入storage
276296
b.Storage.Response.SyncKey = resp.SyncKey
277-
// 避免单个消息处理函数阻塞,让其他的消息得不到处理
278-
if b.MessageHandler != nil {
279-
b.handleMessage(resp.AddMsgList)
280-
}
281-
return nil
297+
return resp.AddMsgList, nil
282298
}
283299

284300
// Block 当消息同步发生了错误或者用户主动在手机上退出,该方法会立即返回,否则会一直阻塞
@@ -307,8 +323,8 @@ func (b *Bot) MessageOnSuccess(h func(msg *Message)) {
307323
}
308324

309325
// MessageOnError setter for Bot.GetMessageErrorHandler
310-
func (b *Bot) MessageOnError(h func(err error)) {
311-
b.GetMessageErrorHandler = h
326+
func (b *Bot) MessageOnError(h func(err error) bool) {
327+
b.MessageErrorHandler = h
312328
}
313329

314330
// DumpHotReloadStorage 写入HotReloadStorage
@@ -349,29 +365,35 @@ func (b *Bot) OnLogout(f func(bot *Bot)) {
349365
b.LogoutCallBack = f
350366
}
351367

352-
// NewBot Bot的构造方法,需要自己传入Caller
368+
// NewBot Bot的构造方法
353369
func NewBot() *Bot {
354370
caller := DefaultCaller()
371+
// 默认行为为桌面模式
355372
caller.Client.SetMode(Desktop)
356373
ctx, cancel := context.WithCancel(context.Background())
357374
return &Bot{Caller: caller, Storage: &Storage{}, context: ctx, cancel: cancel}
358375
}
359376

360377
// DefaultBot 默认的Bot的构造方法,
361-
// mode不传入默认为openwechat.Normal,详情见mode
378+
// mode不传入默认为 openwechat.Desktop,详情见mode
362379
// bot := openwechat.DefaultBot(openwechat.Desktop)
363380
func DefaultBot(modes ...Mode) *Bot {
364381
bot := NewBot()
365382
if len(modes) > 0 {
366383
bot.Caller.Client.SetMode(modes[0])
367384
}
385+
// 获取二维码回调
368386
bot.UUIDCallback = PrintlnQrcodeUrl
387+
// 扫码回调
369388
bot.ScanCallBack = func(body []byte) {
370389
log.Println("扫码成功,请在手机上确认登录")
371390
}
391+
// 登录回调
372392
bot.LoginCallBack = func(body []byte) {
373393
log.Println("登录成功")
374394
}
395+
// 心跳回调函数
396+
// 默认的行为打印SyncCheckResponse
375397
bot.SyncCheckCallback = func(resp SyncCheckResponse) {
376398
log.Printf("RetCode:%s Selector:%s", resp.RetCode, resp.Selector)
377399
}
@@ -413,15 +435,6 @@ func open(url string) error {
413435
return exec.Command(cmd, args...).Start()
414436
}
415437

416-
func (b *Bot) handleMessage(messageList []*Message) {
417-
for _, message := range messageList {
418-
// 根据不同的消息类型来进行处理,方便后续统一调用
419-
message.init(b)
420-
// 调用自定义的处理方法
421-
b.MessageHandler(message)
422-
}
423-
}
424-
425438
// IsHot returns true if is hot login otherwise false
426439
func (b *Bot) IsHot() bool {
427440
return b.isHot

0 commit comments

Comments
 (0)