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.
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/ErisPulse_MatrixAdapter.egg-info/PKG-INFO +1 -1
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/MatrixAdapter/Core.py +110 -6
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/PKG-INFO +1 -1
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/pyproject.toml +1 -1
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/ErisPulse_MatrixAdapter.egg-info/SOURCES.txt +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/ErisPulse_MatrixAdapter.egg-info/dependency_links.txt +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/ErisPulse_MatrixAdapter.egg-info/entry_points.txt +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/ErisPulse_MatrixAdapter.egg-info/top_level.txt +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/MatrixAdapter/Converter.py +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/MatrixAdapter/__init__.py +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/README.md +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/setup.cfg +0 -0
- {erispulse_matrixadapter-4.0.0 → erispulse_matrixadapter-4.0.1}/test/test.py +0 -0
|
@@ -433,9 +433,28 @@ class MatrixAdapter(BaseAdapter):
|
|
|
433
433
|
raise
|
|
434
434
|
|
|
435
435
|
async def _sync_loop(self, account_name: str):
|
|
436
|
-
|
|
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
|
-
|
|
450
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|