wechaty-puppet-matrix 0.0.24 → 0.0.26

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.
@@ -164,6 +164,12 @@ class PuppetMatrix extends PUPPET.Puppet {
164
164
  }, 5000);
165
165
  }
166
166
  }));
167
+ this._client.on('expired', this.wrapAsync(async (expired) => {
168
+ if (expired) {
169
+ log.info(PRE, 'Token has expired');
170
+ void this.onStop();
171
+ }
172
+ }));
167
173
  }
168
174
  addRunningPuppet(this);
169
175
  void this.checkIsLogin();
@@ -364,6 +370,8 @@ class PuppetMatrix extends PUPPET.Puppet {
364
370
  async _stopClient() {
365
371
  this.__currentUserId = undefined;
366
372
  this.__currentUserId = undefined;
373
+ this._client?.destroy();
374
+ this._client = undefined;
367
375
  if (this._cacheMgr) {
368
376
  log.info(PRE, 'colse cache');
369
377
  await this._cacheMgr.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wechaty-puppet-matrix",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "description": "Puppet matrix for Wechaty",
5
5
  "type": "module",
6
6
  "typings": "./dist/esm/src/mod.d.ts",
@@ -644,10 +644,12 @@ class Client extends EventEmitter {
644
644
  private readonly HEARTBEAT_TIMEOUT = 5000 // 5秒超时
645
645
  private reconnectAttempts = 0
646
646
  private heartbeatTimer?: any
647
+ private checkExpiredInterval?: any
647
648
  private heartbeatTimeoutTimer?: any
648
649
  private getQrcodeTimes = 0
649
650
  private restoreTimes = 0
650
651
  private maxRestoreTimes = 1
652
+ private hasExpired = false
651
653
  socket: any
652
654
  server: any
653
655
  tokenInfo: any
@@ -664,6 +666,7 @@ class Client extends EventEmitter {
664
666
  override emit(event: 'verify-code', verifyInfo: VerifyInfo): boolean;
665
667
  override emit(event: 'update-contacts', contacts: ContactPayload[]): boolean;
666
668
  override emit(event: 'room-join', info: any): boolean;
669
+ override emit(event: 'expired', info: boolean): boolean;
667
670
 
668
671
  override emit (event: ClientEvent, ...args: any[]): boolean {
669
672
  return super.emit(event, ...args)
@@ -684,6 +687,20 @@ class Client extends EventEmitter {
684
687
  this.getQrcodeTimes = 0
685
688
  this.restoreTimes = 0
686
689
  this.maxRestoreTimes = 1
690
+ this.hasExpired = false
691
+ }
692
+
693
+ destroy () {
694
+ log.verbose(PRE, 'destroy()')
695
+ this.hasEmitLogout = false
696
+ this.socket && this.socket.end()
697
+ this.socket = null
698
+ this.checkExpiredInterval && clearInterval(this.checkExpiredInterval)
699
+ this.checkExpiredInterval = undefined
700
+ this.heartbeatTimer && clearTimeout(this.heartbeatTimer)
701
+ this.heartbeatTimer = undefined
702
+ this.heartbeatTimeoutTimer && clearTimeout(this.heartbeatTimeoutTimer)
703
+ this.heartbeatTimeoutTimer = undefined
687
704
  }
688
705
 
689
706
  async getTokenInfo () {
@@ -691,6 +708,16 @@ class Client extends EventEmitter {
691
708
  const res = await axios.get(`https://api-bot.aibotk.com/openapi/v1/token/info?secret=5be06b6f8d42a7&token=${this.options.token}`)
692
709
  if (res.data.code === 0) {
693
710
  this.tokenInfo = res.data.data
711
+ this.hasExpired = res.data?.data?.hasExpired
712
+ if (this.hasExpired) {
713
+ log.error('Token已到期,请及时续费')
714
+ this.checkExpiredInterval && clearInterval(this.checkExpiredInterval)
715
+ this.checkExpiredInterval = undefined
716
+ setTimeout(() => {
717
+ this.emit('expired', true)
718
+ }, 3000)
719
+ return false
720
+ }
694
721
  return true
695
722
  } else {
696
723
  log.error('Token auth failed, reason: %s', res.data.message)
@@ -702,8 +729,16 @@ class Client extends EventEmitter {
702
729
  }
703
730
  }
704
731
 
732
+ checkHasExpired () {
733
+ this.checkExpiredInterval = setInterval(() => {
734
+ log.info('checkHasExpired')
735
+ void this.getTokenInfo()
736
+ }, 1000 * 60 * 60 * 12)
737
+ }
738
+
705
739
  async initServer () {
706
740
  await this.getTokenInfo()
741
+ this.checkHasExpired()
707
742
  if (this.socket) {
708
743
  log.error('socket had already been opened!')
709
744
  return
@@ -713,6 +748,9 @@ class Client extends EventEmitter {
713
748
  }
714
749
 
715
750
  async createMqttConnection (): Promise<void> {
751
+ if (this.hasExpired) {
752
+ return
753
+ }
716
754
  if (!this.tokenInfo) {
717
755
  log.error('Token info not available')
718
756
  return
@@ -739,7 +777,7 @@ class Client extends EventEmitter {
739
777
  this.socket = client
740
778
 
741
779
  // 订阅主题
742
- client.subscribe(`aibotk/msg/${this.tokenInfo.guid}`, (err) => {
780
+ client.subscribe(`aibotk/msg/${this.tokenInfo.guid}`, (err: any) => {
743
781
  if (err) {
744
782
  log.error('Failed to subscribe to topic', err)
745
783
  } else {
@@ -783,85 +821,6 @@ class Client extends EventEmitter {
783
821
  this.startHeartbeat()
784
822
  }
785
823
 
786
- async createWebSocket (): Promise<void> {
787
- if (!this.tokenInfo) {
788
- log.error('Token info not available')
789
- return
790
- }
791
- const ws = new WebSocket(
792
- `${this.tokenInfo.endpoint}?guid=${this.tokenInfo.guid}`,
793
- {
794
- perMessageDeflate: true,
795
- maxPayload: 100 * 1024 * 1024,
796
- },
797
- )
798
-
799
- // 连接建立前的 Promise
800
- await new Promise<void>((resolve, reject) => {
801
- ws.once('open', () => {
802
- this.connectionStatus.status = 'connected'
803
- this.reconnectAttempts = 0
804
- log.info('WebSocket connection opened')
805
- resolve()
806
- })
807
-
808
- ws.once('error', (error: any) => {
809
- log.warn('WebSocket connection error', error)
810
- reject(error)
811
- })
812
-
813
- ws.once('close', (code: any, reason: any) => {
814
- void this.handleWebSocketClose(code, reason)
815
- reject(new Error(`WebSocket closed: ${code} - ${reason}`))
816
- })
817
- })
818
- this.socket = ws
819
-
820
- // 设置事件处理器
821
- this.setupWebSocketListeners(ws)
822
- }
823
-
824
- private setupWebSocketListeners (ws: WebSocket): void {
825
- // 消息处理
826
- ws.on('message', (data: string) => {
827
- this.resetHeartbeatTimeout() // 收到任何消息都重置心跳超时
828
- log.silly(PRE, 'initWebSocket() ws.on(message): %s', data)
829
- if (data.toString() === 'pong') {
830
- log.verbose('Received heartbeat')
831
- return
832
- }
833
- try {
834
- const payload = JSON.parse(data)
835
- log.info('Received payload', JSON.stringify(payload))
836
- void this.eventParse(payload)
837
- } catch (error) {
838
- log.warn(PRE, 'initWebSocket() ws.on(message) exception: %s', error)
839
- // @ts-ignore
840
- this.emit('error', (error as Error).message)
841
- }
842
- })
843
-
844
- // 错误处理
845
- ws.on('error', (error: Error) => {
846
- if ((error as any).code === 'ECONNREFUSED') {
847
- log.verbose('Connection refused, potential reconnect scenario')
848
- return
849
- }
850
-
851
- log.verbose(PRE, 'initWebSocket() ws.on(error) %s', error)
852
- // @ts-ignore
853
- this.emit('error', error)
854
- })
855
-
856
- // 关闭处理
857
- ws.on('close', (code:any, reason: any) => {
858
- this.stopHeartbeat()
859
- void this.handleWebSocketClose(code, reason)
860
- })
861
- // 启动心跳
862
- this.startHeartbeat()
863
- }
864
-
865
824
  private startHeartbeat (): void {
866
825
  this.stopHeartbeat() // 确保清理现有定时器
867
826
  this.heartbeatTimer = setInterval(() => {
@@ -922,6 +881,9 @@ class Client extends EventEmitter {
922
881
  }
923
882
 
924
883
  private async reconnectMqtt (): Promise<void> {
884
+ if (this.hasExpired) {
885
+ return
886
+ }
925
887
  if (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) {
926
888
  log.error('Max reconnect attempts reached. Stopping reconnection.')
927
889
  return
@@ -944,20 +906,10 @@ class Client extends EventEmitter {
944
906
  }, delay)
945
907
  }
946
908
 
947
- private async handleWebSocketClose (code?: number, reason?: Buffer | String) {
948
- this.connectionStatus.status = 'disconnected'
949
- log.warn(`WebSocket closed: Code ${code}, Reason ${reason}`)
950
- if (this.socket) {
951
- this.socket.close()
952
- this.socket = null
953
- }
954
-
955
- // 触发重连
956
- await this.reconnect()
957
-
958
- }
959
-
960
909
  private async reconnect (): Promise<void> {
910
+ if (this.hasExpired) {
911
+ return
912
+ }
961
913
  if (this.reconnectAttempts >= this.MAX_RECONNECT_ATTEMPTS) {
962
914
  log.error('Max reconnect attempts reached. Stopping reconnection.')
963
915
  return
@@ -1179,6 +1131,10 @@ class Client extends EventEmitter {
1179
1131
  }
1180
1132
 
1181
1133
  async postData (data: any) {
1134
+ if (this.hasExpired) {
1135
+ log.error('Token已到期,无法提供服务')
1136
+ return
1137
+ }
1182
1138
  const config: any = {
1183
1139
  data: {
1184
1140
  guid: this.tokenInfo.guid,
@@ -207,7 +207,12 @@ class PuppetMatrix extends PUPPET.Puppet {
207
207
  } as any)
208
208
  }, 5000)
209
209
  }
210
-
210
+ }))
211
+ this._client.on('expired', this.wrapAsync(async (expired: boolean) => {
212
+ if (expired) {
213
+ log.info(PRE, 'Token has expired')
214
+ void this.onStop()
215
+ }
211
216
  }))
212
217
  }
213
218
  addRunningPuppet(this)
@@ -434,6 +439,8 @@ class PuppetMatrix extends PUPPET.Puppet {
434
439
  private async _stopClient (): Promise<void> {
435
440
  this.__currentUserId = undefined
436
441
  this.__currentUserId = undefined
442
+ this._client?.destroy()
443
+ this._client = undefined
437
444
  if (this._cacheMgr) {
438
445
  log.info(PRE, 'colse cache')
439
446
  await this._cacheMgr.close()