ErisPulse-MatrixAdapter 4.0.0__tar.gz → 4.0.1__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-MatrixAdapter
3
- Version: 4.0.0
3
+ Version: 4.0.1
4
4
  Summary: ErisPulse的Matrix协议适配模块
5
5
  Author-email: wsu2059 <wsu2059@qq.com>
6
6
  Project-URL: homepage, https://github.com/ErisPulse/ErisPulse-MatrixAdapter
@@ -433,9 +433,28 @@ class MatrixAdapter(BaseAdapter):
433
433
  raise
434
434
 
435
435
  async def _sync_loop(self, account_name: str):
436
- await self._initial_sync(account_name)
436
+ account = self.accounts.get(account_name)
437
+ max_failures = 5
438
+
439
+ # 初始同步——如果认证失败,尝试重新登录后重试
440
+ if not await self._initial_sync(account_name):
441
+ if not await self._try_relogin(account_name, account):
442
+ self.logger.error(
443
+ f"账户 {account_name} 初始同步失败且无法重新登录,停止同步"
444
+ )
445
+ await self._on_sync_loop_exit(account_name)
446
+ return
447
+ if not await self._initial_sync(account_name):
448
+ self.logger.error(
449
+ f"账户 {account_name} 重新登录后初始同步仍失败,停止同步"
450
+ )
451
+ await self._on_sync_loop_exit(account_name)
452
+ return
453
+
437
454
  await self._discover_dm_rooms(account_name)
438
455
 
456
+ consecutive_failures = 0
457
+
439
458
  while self._running:
440
459
  try:
441
460
  runtime = self._get_runtime(account_name)
@@ -446,12 +465,44 @@ class MatrixAdapter(BaseAdapter):
446
465
  )
447
466
 
448
467
  if result.get("status") != "ok":
449
- self.logger.error(
450
- f"账户 {account_name} 同步失败: {result.get('message')}"
468
+ message = result.get("message", "")
469
+ http_status = result.get("http_status", 0)
470
+ is_auth_error = (
471
+ http_status in (401, 403)
472
+ or "authorization" in message.lower()
473
+ or "token" in message.lower()
451
474
  )
452
- await asyncio.sleep(5)
475
+
476
+ if is_auth_error:
477
+ consecutive_failures += 1
478
+ self.logger.warning(
479
+ f"账户 {account_name} 认证失败 ({consecutive_failures}/{max_failures}): {message}"
480
+ )
481
+ if await self._try_relogin(account_name, account):
482
+ self.logger.info(
483
+ f"账户 {account_name} 重新登录成功,继续同步"
484
+ )
485
+ consecutive_failures = 0
486
+ continue
487
+ else:
488
+ consecutive_failures += 1
489
+ self.logger.error(
490
+ f"账户 {account_name} 同步失败 ({consecutive_failures}/{max_failures}): {message}"
491
+ )
492
+
493
+ if consecutive_failures >= max_failures:
494
+ self.logger.error(
495
+ f"账户 {account_name} 连续 {max_failures} 次失败,停止同步循环"
496
+ )
497
+ break
498
+
499
+ # 指数退避: 5, 10, 20, 40, 60
500
+ backoff = min(5 * (2 ** (consecutive_failures - 1)), 60)
501
+ await asyncio.sleep(backoff)
453
502
  continue
454
503
 
504
+ # 成功——重置计数器
505
+ consecutive_failures = 0
455
506
  data = result.get("data", {})
456
507
  runtime["_next_batch"] = data.get(
457
508
  "next_batch", runtime.get("_next_batch")
@@ -463,9 +514,54 @@ class MatrixAdapter(BaseAdapter):
463
514
  break
464
515
  except Exception as e:
465
516
  self.logger.error(f"账户 {account_name} 同步循环异常: {e}")
466
- await asyncio.sleep(5)
517
+ consecutive_failures += 1
518
+ if consecutive_failures >= max_failures:
519
+ self.logger.error(
520
+ f"账户 {account_name} 连续 {max_failures} 次异常,停止同步循环"
521
+ )
522
+ break
523
+ await asyncio.sleep(min(5 * consecutive_failures, 30))
524
+
525
+ await self._on_sync_loop_exit(account_name)
526
+
527
+ async def _try_relogin(self, account_name: str, account) -> bool:
528
+ """尝试重新登录。成功返回 True,失败或无凭据返回 False。"""
529
+ if not account or not account.user_id or not account.password:
530
+ return False
531
+ try:
532
+ self.logger.info(f"账户 {account_name} 尝试重新登录...")
533
+ # 清空旧 token,强制走密码登录路径
534
+ old_token = account.access_token
535
+ account.access_token = ""
536
+ try:
537
+ await self._login_if_needed(account_name, account)
538
+ except Exception:
539
+ # 恢复旧 token,避免状态污染
540
+ account.access_token = old_token
541
+ raise
542
+ self.logger.info(f"账户 {account_name} 重新登录成功")
543
+ return True
544
+ except Exception as e:
545
+ self.logger.error(f"账户 {account_name} 重新登录失败: {e}")
546
+ return False
467
547
 
468
- async def _initial_sync(self, account_name: str):
548
+ async def _on_sync_loop_exit(self, account_name: str):
549
+ """同步循环因错误退出时清理状态"""
550
+ if not self._running:
551
+ return
552
+ runtime = self._get_runtime(account_name)
553
+ bot_id = runtime.get("bot_id", "")
554
+ if bot_id:
555
+ try:
556
+ await self.emit_meta("disconnect", bot_id)
557
+ except Exception:
558
+ pass
559
+ # 停止该账户的心跳任务
560
+ task = self._heartbeat_meta_tasks.pop(account_name, None)
561
+ if task and not task.done():
562
+ task.cancel()
563
+
564
+ async def _initial_sync(self, account_name: str) -> bool:
469
565
  runtime = self._get_runtime(account_name)
470
566
  result = await self.call_api(
471
567
  endpoint="/_matrix/client/v3/sync?timeout=0",
@@ -478,6 +574,12 @@ class MatrixAdapter(BaseAdapter):
478
574
  self.logger.info(
479
575
  f"账户 {account_name} 初始同步完成, next_batch: {runtime.get('_next_batch')}"
480
576
  )
577
+ return True
578
+ else:
579
+ self.logger.warning(
580
+ f"账户 {account_name} 初始同步失败: {result.get('message', 'Unknown error')}"
581
+ )
582
+ return False
481
583
 
482
584
  async def _discover_dm_rooms(self, account_name: str):
483
585
  runtime = self._get_runtime(account_name)
@@ -644,6 +746,7 @@ class MatrixAdapter(BaseAdapter):
644
746
  raw=raw_response,
645
747
  )
646
748
  response["matrix_raw"] = raw_response
749
+ response["http_status"] = resp.status
647
750
  if echo:
648
751
  response["echo"] = echo
649
752
  return response
@@ -664,6 +767,7 @@ class MatrixAdapter(BaseAdapter):
664
767
  raw=raw_response,
665
768
  )
666
769
  response["matrix_raw"] = raw_response
770
+ response["http_status"] = resp.status
667
771
  if echo:
668
772
  response["echo"] = echo
669
773
  return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-MatrixAdapter
3
- Version: 4.0.0
3
+ Version: 4.0.1
4
4
  Summary: ErisPulse的Matrix协议适配模块
5
5
  Author-email: wsu2059 <wsu2059@qq.com>
6
6
  Project-URL: homepage, https://github.com/ErisPulse/ErisPulse-MatrixAdapter
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ErisPulse-MatrixAdapter"
3
- version = "4.0.0"
3
+ version = "4.0.1"
4
4
  description = "ErisPulse的Matrix协议适配模块"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"