@juzi/wechaty-puppet-service 1.0.52 → 1.0.54
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/src/client/grpc-manager.d.ts +2 -2
- package/dist/cjs/src/client/grpc-manager.d.ts.map +1 -1
- package/dist/cjs/src/client/grpc-manager.js +1 -1
- package/dist/cjs/src/client/grpc-manager.js.map +1 -1
- package/dist/cjs/src/client/puppet-service.d.ts +3 -0
- package/dist/cjs/src/client/puppet-service.d.ts.map +1 -1
- package/dist/cjs/src/client/puppet-service.js +90 -0
- package/dist/cjs/src/client/puppet-service.js.map +1 -1
- package/dist/cjs/src/package-json.js +1 -1
- package/dist/cjs/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/cjs/src/server/event-stream-manager.js +15 -1
- package/dist/cjs/src/server/event-stream-manager.js.map +1 -1
- package/dist/cjs/tests/grpc-stream.spec.js +47 -0
- package/dist/cjs/tests/grpc-stream.spec.js.map +1 -1
- package/dist/esm/src/client/grpc-manager.d.ts +2 -2
- package/dist/esm/src/client/grpc-manager.d.ts.map +1 -1
- package/dist/esm/src/client/grpc-manager.js +1 -1
- package/dist/esm/src/client/grpc-manager.js.map +1 -1
- package/dist/esm/src/client/puppet-service.d.ts +3 -0
- package/dist/esm/src/client/puppet-service.d.ts.map +1 -1
- package/dist/esm/src/client/puppet-service.js +90 -0
- package/dist/esm/src/client/puppet-service.js.map +1 -1
- package/dist/esm/src/package-json.js +1 -1
- package/dist/esm/src/server/event-stream-manager.d.ts.map +1 -1
- package/dist/esm/src/server/event-stream-manager.js +15 -1
- package/dist/esm/src/server/event-stream-manager.js.map +1 -1
- package/dist/esm/tests/grpc-stream.spec.js +47 -0
- package/dist/esm/tests/grpc-stream.spec.js.map +1 -1
- package/package.json +1 -1
- package/src/client/grpc-manager.ts +3 -3
- package/src/client/puppet-service.ts +98 -0
- package/src/package-json.ts +1 -1
- package/src/server/event-stream-manager.ts +15 -1
|
@@ -60,6 +60,7 @@ import { GrpcManager } from './grpc-manager.js'
|
|
|
60
60
|
import { PayloadStore } from './payload-store.js'
|
|
61
61
|
import { channelPayloadToPb, channelPbToPayload, postPayloadToPb, urlLinkPbToPayload } from '../utils/pb-payload-helper.js'
|
|
62
62
|
import type { MessageBroadcastTargets } from '@juzi/wechaty-puppet/dist/esm/src/schemas/message.js'
|
|
63
|
+
import { timeoutPromise } from 'gerror'
|
|
63
64
|
|
|
64
65
|
export type PuppetServiceOptions = PUPPET.PuppetOptions & {
|
|
65
66
|
authority? : string
|
|
@@ -74,6 +75,9 @@ export type PuppetServiceOptions = PUPPET.PuppetOptions & {
|
|
|
74
75
|
}
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
const ResetLoginTimeout = 30 * 1000
|
|
79
|
+
const ResetReadyTimeout = 20 * 1000 // normally ready comes 15 seconds after login
|
|
80
|
+
|
|
77
81
|
class PuppetService extends PUPPET.Puppet {
|
|
78
82
|
|
|
79
83
|
static override readonly VERSION = VERSION
|
|
@@ -306,7 +310,15 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
306
310
|
break
|
|
307
311
|
case grpcPuppet.EventType.EVENT_TYPE_LOGIN:
|
|
308
312
|
{
|
|
313
|
+
if (this.waitingForLogin) {
|
|
314
|
+
log.warn('PuppetService', 'this login event is ignored because the it is expected by event stream reconnect')
|
|
315
|
+
return
|
|
316
|
+
}
|
|
309
317
|
const loginPayload = JSON.parse(payload) as PUPPET.payloads.EventLogin
|
|
318
|
+
const accountId = await this._payloadStore.miscellaneous.get('accountId')
|
|
319
|
+
if (accountId !== loginPayload.contactId) {
|
|
320
|
+
await this._payloadStore.miscellaneous.delete('eventSeq')
|
|
321
|
+
}
|
|
310
322
|
await this._payloadStore.miscellaneous.set('accountId', loginPayload.contactId)
|
|
311
323
|
;(
|
|
312
324
|
async () => this.login(loginPayload.contactId)
|
|
@@ -346,6 +358,10 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
346
358
|
this.emit('post-tap', JSON.parse(payload) as PUPPET.payloads.EventPostTap)
|
|
347
359
|
break
|
|
348
360
|
case grpcPuppet.EventType.EVENT_TYPE_READY:
|
|
361
|
+
if (this.waitingForLogin) {
|
|
362
|
+
log.warn('PuppetService', 'this ready event is ignored because the it is expected by event stream reconnect')
|
|
363
|
+
return
|
|
364
|
+
}
|
|
349
365
|
this.emit('ready', JSON.parse(payload) as PUPPET.payloads.EventReady)
|
|
350
366
|
break
|
|
351
367
|
case grpcPuppet.EventType.EVENT_TYPE_ROOM_INVITE:
|
|
@@ -2522,6 +2538,88 @@ class PuppetService extends PUPPET.Puppet {
|
|
|
2522
2538
|
clearInterval(this.healthCheckInterval!)
|
|
2523
2539
|
}
|
|
2524
2540
|
|
|
2541
|
+
// handle watchdog reset
|
|
2542
|
+
// goal: pain free reset of reconnect within threshold (like 30 seconds?)
|
|
2543
|
+
|
|
2544
|
+
private waitingForLogin = false
|
|
2545
|
+
private waitingForReady = false
|
|
2546
|
+
override async reset (): Promise<void> {
|
|
2547
|
+
if (!this._grpcManager) {
|
|
2548
|
+
log.warn('PuppetService', 'grpc manager not constructed, perform regular reset')
|
|
2549
|
+
return super.reset()
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
if (!this.isLoggedIn) {
|
|
2553
|
+
log.warn('PuppetService', 'puppet not logged in, perform regular reset')
|
|
2554
|
+
return super.reset()
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
this.grpcManager.stopStream()
|
|
2558
|
+
const lastEventTimestamp = await this._payloadStore.miscellaneous.get('eventTimestamp')
|
|
2559
|
+
const lastEventSeq = (Date.now() - Number(lastEventTimestamp || 0)) < this.timeoutMilliseconds ? await this._payloadStore.miscellaneous.get('eventSeq') : undefined
|
|
2560
|
+
const accountId = await this._payloadStore.miscellaneous.get('accountId')
|
|
2561
|
+
|
|
2562
|
+
const onLoginResolve = (resolve: () => void) => {
|
|
2563
|
+
const onLogin = (event: grpcPuppet.EventResponse) => {
|
|
2564
|
+
const type = event.getType()
|
|
2565
|
+
const payload = event.getPayload()
|
|
2566
|
+
if (this.waitingForLogin && type === grpcPuppet.EventType.EVENT_TYPE_LOGIN) {
|
|
2567
|
+
const payloadObj = JSON.parse(payload) as PUPPET.payloads.EventLogin
|
|
2568
|
+
this.waitingForLogin = false
|
|
2569
|
+
if (accountId && payloadObj.contactId !== accountId) {
|
|
2570
|
+
throw new Error('login with a different account, perform regular reset')
|
|
2571
|
+
}
|
|
2572
|
+
resolve()
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
return onLogin
|
|
2576
|
+
}
|
|
2577
|
+
const onReadyResolve = (resolve: () => void) => {
|
|
2578
|
+
const onReady = (event: grpcPuppet.EventResponse) => {
|
|
2579
|
+
const type = event.getType()
|
|
2580
|
+
if (this.waitingForReady && type === grpcPuppet.EventType.EVENT_TYPE_READY) {
|
|
2581
|
+
this.waitingForReady = false
|
|
2582
|
+
resolve()
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
2585
|
+
return onReady
|
|
2586
|
+
}
|
|
2587
|
+
|
|
2588
|
+
let onLogin: ReturnType<typeof onLoginResolve>
|
|
2589
|
+
let onReady: ReturnType<typeof onReadyResolve>
|
|
2590
|
+
const loginFuture = new Promise<void>(resolve => {
|
|
2591
|
+
onLogin = onLoginResolve(resolve)
|
|
2592
|
+
this.grpcManager.on('data', onLogin)
|
|
2593
|
+
})
|
|
2594
|
+
const readyFuture = new Promise<void>(resolve => {
|
|
2595
|
+
onReady = onReadyResolve(resolve)
|
|
2596
|
+
this.grpcManager.on('data', onReady)
|
|
2597
|
+
})
|
|
2598
|
+
|
|
2599
|
+
this.waitingForLogin = true
|
|
2600
|
+
this.waitingForReady = true
|
|
2601
|
+
|
|
2602
|
+
// wait for server to clear stream
|
|
2603
|
+
await new Promise(resolve => {
|
|
2604
|
+
setTimeout(resolve, 5000)
|
|
2605
|
+
})
|
|
2606
|
+
|
|
2607
|
+
await this.grpcManager.startStream(lastEventSeq, accountId)
|
|
2608
|
+
try {
|
|
2609
|
+
await timeoutPromise(loginFuture, ResetLoginTimeout)
|
|
2610
|
+
.finally(() => this.grpcManager.off('data', onLogin))
|
|
2611
|
+
} catch (e) {
|
|
2612
|
+
log.warn('PuppetService', 'waiting for event reset login error, will perform regular reset')
|
|
2613
|
+
return super.reset()
|
|
2614
|
+
}
|
|
2615
|
+
try {
|
|
2616
|
+
await timeoutPromise(readyFuture, ResetReadyTimeout)
|
|
2617
|
+
.finally(() => this.grpcManager.off('data', onReady))
|
|
2618
|
+
} catch (e) {
|
|
2619
|
+
log.warn('PuppetService', 'waiting for event reset ready error, will do nothing')
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2525
2623
|
}
|
|
2526
2624
|
|
|
2527
2625
|
export {
|
package/src/package-json.ts
CHANGED
|
@@ -294,13 +294,27 @@ class EventStreamManager {
|
|
|
294
294
|
this.offCallbackList.push(off)
|
|
295
295
|
break
|
|
296
296
|
}
|
|
297
|
+
case 'post-comment': {
|
|
298
|
+
const listener = (payload: PUPPET.payloads.EventPostComment) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_POST_COMMENT, payload)
|
|
299
|
+
this.puppet.on('post-comment', listener)
|
|
300
|
+
const off = () => this.puppet.off('post-comment', listener)
|
|
301
|
+
this.offCallbackList.push(off)
|
|
302
|
+
break
|
|
303
|
+
}
|
|
304
|
+
case 'post-tap': {
|
|
305
|
+
const listener = (payload: PUPPET.payloads.EventPostTap) => this.grpcEmit(grpcPuppet.EventType.EVENT_TYPE_POST_TAP, payload)
|
|
306
|
+
this.puppet.on('post-tap', listener)
|
|
307
|
+
const off = () => this.puppet.off('post-tap', listener)
|
|
308
|
+
this.offCallbackList.push(off)
|
|
309
|
+
break
|
|
310
|
+
}
|
|
297
311
|
case 'reset':
|
|
298
312
|
// the `reset` event should be dealed internally, should not send out
|
|
299
313
|
break
|
|
300
314
|
|
|
301
315
|
default:
|
|
302
316
|
// Huan(202003): in default, the `eventName` type should be `never`, please check.
|
|
303
|
-
|
|
317
|
+
log.warn('eventName ' + eventName + ' unsupported!')
|
|
304
318
|
}
|
|
305
319
|
}
|
|
306
320
|
|