@@ -12,22 +12,22 @@ import (
12
12
)
13
13
14
14
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
31
31
}
32
32
33
33
// Alive 判断当前用户是否正常在线
@@ -154,7 +154,7 @@ func (b *Bot) Logout() error {
154
154
if err := b .Caller .Logout (info ); err != nil {
155
155
return err
156
156
}
157
- b .stopAsyncCALL (errors .New ("logout" ))
157
+ b .stopSyncCheck (errors .New ("logout" ))
158
158
return nil
159
159
}
160
160
return errors .New ("user not login" )
@@ -214,19 +214,26 @@ func (b *Bot) WebInit() error {
214
214
215
215
// FIX: 当bot在线的情况下执行热登录,会开启多次事件监听
216
216
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
219
219
}
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
+ }
222
229
}
223
230
})
224
231
return nil
225
232
}
226
233
227
234
// 轮询请求
228
235
// 根据状态码判断是否有新的请求
229
- func (b * Bot ) asyncCall () error {
236
+ func (b * Bot ) syncCheck () error {
230
237
var (
231
238
err error
232
239
resp * SyncCheckResponse
@@ -247,38 +254,47 @@ func (b *Bot) asyncCall() error {
247
254
}
248
255
// 如果Selector不为0,则获取消息
249
256
if ! resp .NorMal () {
250
- if err = b .getNewWechatMessage (); err != nil {
257
+ messages , err := b .syncMessage ()
258
+ if err != nil {
251
259
return err
252
260
}
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
+ }
253
271
}
254
272
}
255
273
return err
256
274
}
257
275
258
276
// 当获取消息发生错误时, 默认的错误处理行为
259
- func (b * Bot ) stopAsyncCALL (err error ) {
277
+ func (b * Bot ) stopSyncCheck (err error ) bool {
260
278
if IsNetworkError (err ) {
261
279
log .Println (err )
262
- return
280
+ // 继续监听
281
+ return true
263
282
}
264
283
b .err = err
265
284
b .Exit ()
266
285
log .Printf ("exit with : %s" , err .Error ())
286
+ return false
267
287
}
268
288
269
289
// 获取新的消息
270
- func (b * Bot ) getNewWechatMessage () error {
290
+ func (b * Bot ) syncMessage () ([] * Message , error ) {
271
291
resp , err := b .Caller .WebWxSync (b .Storage .Request , b .Storage .Response , b .Storage .LoginInfo )
272
292
if err != nil {
273
- return err
293
+ return nil , err
274
294
}
275
295
// 更新SyncKey并且重新存入storage
276
296
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
282
298
}
283
299
284
300
// Block 当消息同步发生了错误或者用户主动在手机上退出,该方法会立即返回,否则会一直阻塞
@@ -307,8 +323,8 @@ func (b *Bot) MessageOnSuccess(h func(msg *Message)) {
307
323
}
308
324
309
325
// 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
312
328
}
313
329
314
330
// DumpHotReloadStorage 写入HotReloadStorage
@@ -349,29 +365,35 @@ func (b *Bot) OnLogout(f func(bot *Bot)) {
349
365
b .LogoutCallBack = f
350
366
}
351
367
352
- // NewBot Bot的构造方法,需要自己传入Caller
368
+ // NewBot Bot的构造方法
353
369
func NewBot () * Bot {
354
370
caller := DefaultCaller ()
371
+ // 默认行为为桌面模式
355
372
caller .Client .SetMode (Desktop )
356
373
ctx , cancel := context .WithCancel (context .Background ())
357
374
return & Bot {Caller : caller , Storage : & Storage {}, context : ctx , cancel : cancel }
358
375
}
359
376
360
377
// DefaultBot 默认的Bot的构造方法,
361
- // mode不传入默认为openwechat.Normal ,详情见mode
378
+ // mode不传入默认为 openwechat.Desktop ,详情见mode
362
379
// bot := openwechat.DefaultBot(openwechat.Desktop)
363
380
func DefaultBot (modes ... Mode ) * Bot {
364
381
bot := NewBot ()
365
382
if len (modes ) > 0 {
366
383
bot .Caller .Client .SetMode (modes [0 ])
367
384
}
385
+ // 获取二维码回调
368
386
bot .UUIDCallback = PrintlnQrcodeUrl
387
+ // 扫码回调
369
388
bot .ScanCallBack = func (body []byte ) {
370
389
log .Println ("扫码成功,请在手机上确认登录" )
371
390
}
391
+ // 登录回调
372
392
bot .LoginCallBack = func (body []byte ) {
373
393
log .Println ("登录成功" )
374
394
}
395
+ // 心跳回调函数
396
+ // 默认的行为打印SyncCheckResponse
375
397
bot .SyncCheckCallback = func (resp SyncCheckResponse ) {
376
398
log .Printf ("RetCode:%s Selector:%s" , resp .RetCode , resp .Selector )
377
399
}
@@ -413,15 +435,6 @@ func open(url string) error {
413
435
return exec .Command (cmd , args ... ).Start ()
414
436
}
415
437
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
-
425
438
// IsHot returns true if is hot login otherwise false
426
439
func (b * Bot ) IsHot () bool {
427
440
return b .isHot
0 commit comments