ErisPulse-MatrixAdapter 4.0.2__tar.gz → 4.1.0__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.2
3
+ Version: 4.1.0
4
4
  Summary: ErisPulse的Matrix协议适配模块
5
5
  Author-email: wsu2059 <wsu2059@qq.com>
6
6
  Project-URL: homepage, https://github.com/ErisPulse/ErisPulse-MatrixAdapter
@@ -9,6 +9,7 @@ from ErisPulse.Core import client
9
9
  from ErisPulse.Core.Bases.adapter import BaseAdapter
10
10
  from ErisPulse.Core.Event import register_event_mixin, unregister_platform_event_methods
11
11
  from ErisPulse.runtime.config_schema import BotAccountConfig
12
+ from ErisPulse.Core.i18n import i18n
12
13
 
13
14
  from .Converter import MatrixConverter
14
15
 
@@ -21,43 +22,57 @@ class MatrixAccountConfig(BotAccountConfig):
21
22
  homeserver: str = field(
22
23
  default="https://matrix.org",
23
24
  metadata={
24
- "description": "Matrix server address",
25
+ "description": {"i18n": "matrix.homeserver", "default": "Matrix 服务器地址"},
25
26
  "required": True,
26
- "webui": {"widget": "text", "group": "connection", "order": 1},
27
+ "ui": {
28
+ "widget": "text",
29
+ "group": "connection",
30
+ "order": 1,
31
+ "placeholder": {"i18n": "matrix.homeserver.ph", "default": "https://matrix.org"},
32
+ },
27
33
  },
28
34
  )
29
35
  access_token: str = field(
30
36
  default="",
31
37
  metadata={
32
- "description": "Access token (alternative to user_id/password)",
38
+ "description": {"i18n": "matrix.access_token", "default": "Access Token(替代 user_id/password)"},
33
39
  "secret": True,
34
- "webui": {"widget": "password", "group": "basic", "order": 2},
40
+ "ui": {"widget": "password", "group": "basic", "order": 2},
35
41
  },
36
42
  )
37
43
  user_id: str = field(
38
44
  default="",
39
45
  metadata={
40
- "description": "Username (used for password login)",
41
- "webui": {"widget": "text", "group": "basic", "order": 3},
46
+ "description": {"i18n": "matrix.user_id", "default": "用户名(用于密码登录)"},
47
+ "ui": {"widget": "text", "group": "basic", "order": 3},
42
48
  },
43
49
  )
44
50
  password: str = field(
45
51
  default="",
46
52
  metadata={
47
- "description": "Password (used for password login)",
53
+ "description": {"i18n": "matrix.password", "default": "密码(用于密码登录)"},
48
54
  "secret": True,
49
- "webui": {"widget": "password", "group": "basic", "order": 4},
55
+ "ui": {"widget": "password", "group": "basic", "order": 4},
50
56
  },
51
57
  )
52
58
  auto_accept_invites: bool = field(
53
59
  default=True,
54
60
  metadata={
55
- "description": "Automatically accept room invitations",
56
- "webui": {"widget": "switch", "group": "behavior", "order": 5},
61
+ "description": {"i18n": "matrix.auto_accept_invites", "default": "自动接受房间邀请"},
62
+ "ui": {"widget": "switch", "group": "behavior", "order": 5},
57
63
  },
58
64
  )
59
65
 
60
66
 
67
+ MatrixAccountConfig._schema_meta = {
68
+ "group_labels": {
69
+ "basic": {"i18n": "matrix.group.basic", "default": "基本设置"},
70
+ "connection": {"i18n": "matrix.group.connection", "default": "连接设置"},
71
+ "behavior": {"i18n": "matrix.group.behavior", "default": "行为设置"},
72
+ }
73
+ } # type: ignore[attr-defined]
74
+
75
+
61
76
  # ============================================================================
62
77
  # 事件 Mixin(平台扩展方法)
63
78
  # ============================================================================
@@ -316,6 +331,120 @@ class MatrixAdapter(BaseAdapter):
316
331
  self._heartbeat_meta_tasks: Dict[str, asyncio.Task] = {}
317
332
  self._converters: Dict[str, MatrixConverter] = {}
318
333
  self._running = False
334
+ self._register_i18n()
335
+
336
+ def _register_i18n(self):
337
+ """注册配置字段与日志消息的 i18n 翻译"""
338
+ try:
339
+ from ErisPulse.runtime.config_schema import register_config_i18n
340
+ register_config_i18n(MatrixAccountConfig, "zh-CN", domain="matrix")
341
+ register_config_i18n(MatrixAccountConfig, "en", {
342
+ "matrix.homeserver": "Matrix server address",
343
+ "matrix.homeserver.ph": "https://matrix.org",
344
+ "matrix.access_token": "Access Token (alternative to user_id/password)",
345
+ "matrix.user_id": "Username (used for password login)",
346
+ "matrix.password": "Password (used for password login)",
347
+ "matrix.auto_accept_invites": "Automatically accept room invitations",
348
+ "matrix.group.basic": "Basic",
349
+ "matrix.group.connection": "Connection",
350
+ "matrix.group.behavior": "Behavior",
351
+ }, domain="matrix")
352
+ except Exception:
353
+ pass
354
+
355
+ zh_CN = {
356
+ "matrix.old_config_detected": "检测到旧格式单账户配置,建议迁移到 Matrix_Adapter.accounts.default",
357
+ "matrix.save_default_failed": "保存默认配置失败: {error}",
358
+ "matrix.missing_credentials": "账户 '{name}' 缺少 access_token/user_id,已跳过",
359
+ "matrix.account_disabled": "账户 '{name}' 已加载但未启用(enabled=false),请在配置中将 [Matrix_Adapter.accounts.{name}] 的 enabled 设为 true",
360
+ "matrix.accounts_loaded": "Matrix适配器初始化完成,共加载 {count} 个账户",
361
+ "matrix.authenticated": "账户 {name} Matrix 已认证: {bot_id}",
362
+ "matrix.login_success": "账户 {name} Matrix 登录成功: {bot_id}",
363
+ "matrix.login_failed": "登录失败: {message}",
364
+ "matrix.login_error": "账户 {name} Matrix 登录失败: {error}",
365
+ "matrix.initial_sync_failed_nologin": "账户 {name} 初始同步失败且无法重新登录,停止同步",
366
+ "matrix.initial_sync_still_failed": "账户 {name} 重新登录后初始同步仍失败,停止同步",
367
+ "matrix.auth_failed": "账户 {name} 认证失败 ({count}/{max}): {message}",
368
+ "matrix.relogin_success": "账户 {name} 重新登录成功,继续同步",
369
+ "matrix.sync_failed": "账户 {name} 同步失败 ({count}/{max}): {message}",
370
+ "matrix.max_failures_stop": "账户 {name} 连续 {max} 次失败,停止同步循环",
371
+ "matrix.sync_loop_error": "账户 {name} 同步循环异常: {error}",
372
+ "matrix.max_exceptions_stop": "账户 {name} 连续 {max} 次异常,停止同步循环",
373
+ "matrix.relogin_attempt": "账户 {name} 尝试重新登录...",
374
+ "matrix.relogin_done": "账户 {name} 重新登录成功",
375
+ "matrix.relogin_failed": "账户 {name} 重新登录失败: {error}",
376
+ "matrix.initial_sync_done": "账户 {name} 初始同步完成, next_batch: {batch}",
377
+ "matrix.initial_sync_failed": "账户 {name} 初始同步失败: {message}",
378
+ "matrix.dm_discovered": "账户 {name} 发现 {count} 个 DM 房间",
379
+ "matrix.process_event": "账户 {name} 处理 Matrix 事件: {event}",
380
+ "matrix.process_event_failed": "处理事件失败: {error}",
381
+ "matrix.room_invite": "账户 {name} 收到房间邀请: {room}",
382
+ "matrix.room_joined": "账户 {name} 已自动加入房间: {room}",
383
+ "matrix.join_room_failed": "加入房间失败: {error}",
384
+ "matrix.download_failed": "账户 {name} 下载文件失败: HTTP {status}",
385
+ "matrix.download_error": "账户 {name} 下载文件异常: {error}",
386
+ "matrix.account_not_found": "账户 {name} 不存在,无法上传媒体",
387
+ "matrix.upload_failed": "账户 {name} 上传媒体失败: {data}",
388
+ "matrix.upload_error": "账户 {name} 上传媒体异常: {error}",
389
+ "matrix.api_timeout": "账户 {name} Matrix API 请求超时: {endpoint}",
390
+ "matrix.timeout_msg": "请求超时",
391
+ "matrix.api_call_failed": "账户 {name} 调用 Matrix API 失败: {error}",
392
+ "matrix.api_error": "API调用失败: {error}",
393
+ "matrix.no_enabled_accounts": "没有已启用的账户,Matrix 适配器将以空闲状态启动",
394
+ "matrix.no_bot_id": "账户 {name} 无法获取 bot user_id,请检查配置",
395
+ "matrix.account_started": "账户 {name} (bot_id: {bot_id}) Matrix 已启动",
396
+ "matrix.adapter_started": "Matrix 适配器启动完成,共 {count} 个账户",
397
+ "matrix.adapter_shutdown": "Matrix 适配器已关闭",
398
+ }
399
+ en = {
400
+ "matrix.old_config_detected": "Old single-account config detected, please migrate to Matrix_Adapter.accounts.default",
401
+ "matrix.save_default_failed": "Failed to save default config: {error}",
402
+ "matrix.missing_credentials": "Account '{name}' missing access_token/user_id, skipped",
403
+ "matrix.account_disabled": "Account '{name}' loaded but disabled (enabled=false), please set enabled=true in [Matrix_Adapter.accounts.{name}]",
404
+ "matrix.accounts_loaded": "Matrix adapter initialized, loaded {count} account(s)",
405
+ "matrix.authenticated": "Account {name} Matrix authenticated: {bot_id}",
406
+ "matrix.login_success": "Account {name} Matrix login success: {bot_id}",
407
+ "matrix.login_failed": "Login failed: {message}",
408
+ "matrix.login_error": "Account {name} Matrix login failed: {error}",
409
+ "matrix.initial_sync_failed_nologin": "Account {name} initial sync failed and re-login not possible, stopping sync",
410
+ "matrix.initial_sync_still_failed": "Account {name} initial sync still failing after re-login, stopping sync",
411
+ "matrix.auth_failed": "Account {name} auth failed ({count}/{max}): {message}",
412
+ "matrix.relogin_success": "Account {name} re-login success, resuming sync",
413
+ "matrix.sync_failed": "Account {name} sync failed ({count}/{max}): {message}",
414
+ "matrix.max_failures_stop": "Account {name} failed {max} consecutive times, stopping sync loop",
415
+ "matrix.sync_loop_error": "Account {name} sync loop error: {error}",
416
+ "matrix.max_exceptions_stop": "Account {name} {max} consecutive exceptions, stopping sync loop",
417
+ "matrix.relogin_attempt": "Account {name} attempting re-login...",
418
+ "matrix.relogin_done": "Account {name} re-login success",
419
+ "matrix.relogin_failed": "Account {name} re-login failed: {error}",
420
+ "matrix.initial_sync_done": "Account {name} initial sync done, next_batch: {batch}",
421
+ "matrix.initial_sync_failed": "Account {name} initial sync failed: {message}",
422
+ "matrix.dm_discovered": "Account {name} discovered {count} DM room(s)",
423
+ "matrix.process_event": "Account {name} processing Matrix event: {event}",
424
+ "matrix.process_event_failed": "Failed to process event: {error}",
425
+ "matrix.room_invite": "Account {name} received room invite: {room}",
426
+ "matrix.room_joined": "Account {name} auto-joined room: {room}",
427
+ "matrix.join_room_failed": "Failed to join room: {error}",
428
+ "matrix.download_failed": "Account {name} download failed: HTTP {status}",
429
+ "matrix.download_error": "Account {name} download error: {error}",
430
+ "matrix.account_not_found": "Account {name} not found, cannot upload media",
431
+ "matrix.upload_failed": "Account {name} upload media failed: {data}",
432
+ "matrix.upload_error": "Account {name} upload media error: {error}",
433
+ "matrix.api_timeout": "Account {name} Matrix API request timeout: {endpoint}",
434
+ "matrix.timeout_msg": "Request timeout",
435
+ "matrix.api_call_failed": "Account {name} Matrix API call failed: {error}",
436
+ "matrix.api_error": "API call failed: {error}",
437
+ "matrix.no_enabled_accounts": "No enabled accounts, Matrix adapter will start idle",
438
+ "matrix.no_bot_id": "Account {name} could not obtain bot user_id, please check config",
439
+ "matrix.account_started": "Account {name} (bot_id: {bot_id}) Matrix started",
440
+ "matrix.adapter_started": "Matrix adapter started, {count} account(s) total",
441
+ "matrix.adapter_shutdown": "Matrix adapter shut down",
442
+ }
443
+ try:
444
+ i18n.register("zh-CN", zh_CN, domain="matrix")
445
+ i18n.register("en", en, domain="matrix")
446
+ except Exception:
447
+ pass
319
448
 
320
449
  def _get_config_key(self) -> str:
321
450
  return "Matrix_Adapter"
@@ -341,7 +470,7 @@ class MatrixAdapter(BaseAdapter):
341
470
  old = config_mgr.getConfig("Matrix_Adapter")
342
471
  if old and old.get("access_token"):
343
472
  self.logger.warning(
344
- "检测到旧格式单账户配置,建议迁移到 Matrix_Adapter.accounts.default"
473
+ i18n.t("matrix.old_config_detected", default="检测到旧格式单账户配置,建议迁移到 Matrix_Adapter.accounts.default")
345
474
  )
346
475
  data = {"default": {**old, "enabled": True}}
347
476
  else:
@@ -358,23 +487,22 @@ class MatrixAdapter(BaseAdapter):
358
487
  try:
359
488
  config_mgr.setConfig(key, data)
360
489
  except Exception as e:
361
- self.logger.error(f"保存默认配置失败: {e}")
490
+ self.logger.error(i18n.t("matrix.save_default_failed", error=e, default="保存默认配置失败: {error}"))
362
491
  accounts = {}
363
492
  for name, account_data in data.items():
364
493
  if not isinstance(account_data, dict):
365
494
  continue
366
495
  if not account_data.get("access_token") and not account_data.get("user_id"):
367
- self.logger.warning(f"账户 '{name}' 缺少 access_token/user_id,已跳过")
496
+ self.logger.warning(i18n.t("matrix.missing_credentials", name=name, default="账户 '{name}' 缺少 access_token/user_id,已跳过"))
368
497
  continue
369
498
  instance = dict_to_dataclass(MatrixAccountConfig, account_data)
370
499
  instance.name = name
371
500
  if not instance.enabled:
372
501
  self.logger.warning(
373
- f"账户 '{name}' 已加载但未启用(enabled=false),"
374
- f"请在配置中将 [Matrix_Adapter.accounts.{name}] 的 enabled 设为 true"
502
+ i18n.t("matrix.account_disabled", name=name, default="账户 '{name}' 已加载但未启用(enabled=false),请在配置中将 [Matrix_Adapter.accounts.{name}] 的 enabled 设为 true")
375
503
  )
376
504
  accounts[name] = instance
377
- self.logger.info(f"Matrix适配器初始化完成,共加载 {len(accounts)} 个账户")
505
+ self.logger.info(i18n.t("matrix.accounts_loaded", count=len(accounts), default="Matrix适配器初始化完成,共加载 {count} 个账户"))
378
506
  return accounts
379
507
 
380
508
  async def _login_if_needed(self, account_name: str, account: MatrixAccountConfig):
@@ -392,10 +520,9 @@ class MatrixAdapter(BaseAdapter):
392
520
  bot_id = result["data"].get("user_id", "")
393
521
  runtime["bot_id"] = bot_id
394
522
  runtime["access_token"] = account.access_token
395
- account.bot_id = bot_id
396
523
  if converter:
397
524
  converter.bot_user_id = bot_id
398
- self.logger.info(f"账户 {account_name} Matrix 已认证: {bot_id}")
525
+ self.logger.info(i18n.t("matrix.authenticated", name=account_name, bot_id=bot_id, default="账户 {name} Matrix 已认证: {bot_id}"))
399
526
  return
400
527
  except Exception:
401
528
  pass
@@ -416,20 +543,18 @@ class MatrixAdapter(BaseAdapter):
416
543
  if result.get("status") == "ok" and result.get("data"):
417
544
  token = result["data"].get("access_token", "")
418
545
  bot_id = result["data"].get("user_id", account.user_id)
419
- # 密码登录获得的 token 需回填到账户实例,供后续 call_api 使用
420
- account.access_token = token
546
+ # 密码登录获得的 token 写入运行时状态,供后续 call_api 使用
421
547
  runtime["access_token"] = token
422
548
  runtime["bot_id"] = bot_id
423
- account.bot_id = bot_id
424
549
  if converter:
425
550
  converter.bot_user_id = bot_id
426
- self.logger.info(f"账户 {account_name} Matrix 登录成功: {bot_id}")
551
+ self.logger.info(i18n.t("matrix.login_success", name=account_name, bot_id=bot_id, default="账户 {name} Matrix 登录成功: {bot_id}"))
427
552
  else:
428
553
  raise Exception(
429
- f"登录失败: {result.get('message', 'Unknown error')}"
554
+ i18n.t("matrix.login_failed", message=result.get('message', 'Unknown error'), default="登录失败: {message}")
430
555
  )
431
556
  except Exception as e:
432
- self.logger.error(f"账户 {account_name} Matrix 登录失败: {e}")
557
+ self.logger.error(i18n.t("matrix.login_error", name=account_name, error=e, default="账户 {name} Matrix 登录失败: {error}"))
433
558
  raise
434
559
 
435
560
  async def _sync_loop(self, account_name: str):
@@ -440,13 +565,13 @@ class MatrixAdapter(BaseAdapter):
440
565
  if not await self._initial_sync(account_name):
441
566
  if not await self._try_relogin(account_name, account):
442
567
  self.logger.error(
443
- f"账户 {account_name} 初始同步失败且无法重新登录,停止同步"
568
+ i18n.t("matrix.initial_sync_failed_nologin", name=account_name, default="账户 {name} 初始同步失败且无法重新登录,停止同步")
444
569
  )
445
570
  await self._on_sync_loop_exit(account_name)
446
571
  return
447
572
  if not await self._initial_sync(account_name):
448
573
  self.logger.error(
449
- f"账户 {account_name} 重新登录后初始同步仍失败,停止同步"
574
+ i18n.t("matrix.initial_sync_still_failed", name=account_name, default="账户 {name} 重新登录后初始同步仍失败,停止同步")
450
575
  )
451
576
  await self._on_sync_loop_exit(account_name)
452
577
  return
@@ -476,23 +601,23 @@ class MatrixAdapter(BaseAdapter):
476
601
  if is_auth_error:
477
602
  consecutive_failures += 1
478
603
  self.logger.warning(
479
- f"账户 {account_name} 认证失败 ({consecutive_failures}/{max_failures}): {message}"
604
+ i18n.t("matrix.auth_failed", name=account_name, count=consecutive_failures, max=max_failures, message=message, default="账户 {name} 认证失败 ({count}/{max}): {message}")
480
605
  )
481
606
  if await self._try_relogin(account_name, account):
482
607
  self.logger.info(
483
- f"账户 {account_name} 重新登录成功,继续同步"
608
+ i18n.t("matrix.relogin_success", name=account_name, default="账户 {name} 重新登录成功,继续同步")
484
609
  )
485
610
  consecutive_failures = 0
486
611
  continue
487
612
  else:
488
613
  consecutive_failures += 1
489
614
  self.logger.error(
490
- f"账户 {account_name} 同步失败 ({consecutive_failures}/{max_failures}): {message}"
615
+ i18n.t("matrix.sync_failed", name=account_name, count=consecutive_failures, max=max_failures, message=message, default="账户 {name} 同步失败 ({count}/{max}): {message}")
491
616
  )
492
617
 
493
618
  if consecutive_failures >= max_failures:
494
619
  self.logger.error(
495
- f"账户 {account_name} 连续 {max_failures} 次失败,停止同步循环"
620
+ i18n.t("matrix.max_failures_stop", name=account_name, max=max_failures, default="账户 {name} 连续 {max} 次失败,停止同步循环")
496
621
  )
497
622
  break
498
623
 
@@ -513,11 +638,11 @@ class MatrixAdapter(BaseAdapter):
513
638
  except asyncio.CancelledError:
514
639
  break
515
640
  except Exception as e:
516
- self.logger.error(f"账户 {account_name} 同步循环异常: {e}")
641
+ self.logger.error(i18n.t("matrix.sync_loop_error", name=account_name, error=e, default="账户 {name} 同步循环异常: {error}"))
517
642
  consecutive_failures += 1
518
643
  if consecutive_failures >= max_failures:
519
644
  self.logger.error(
520
- f"账户 {account_name} 连续 {max_failures} 次异常,停止同步循环"
645
+ i18n.t("matrix.max_exceptions_stop", name=account_name, max=max_failures, default="账户 {name} 连续 {max} 次异常,停止同步循环")
521
646
  )
522
647
  break
523
648
  await asyncio.sleep(min(5 * consecutive_failures, 30))
@@ -529,7 +654,7 @@ class MatrixAdapter(BaseAdapter):
529
654
  if not account or not account.user_id or not account.password:
530
655
  return False
531
656
  try:
532
- self.logger.info(f"账户 {account_name} 尝试重新登录...")
657
+ self.logger.info(i18n.t("matrix.relogin_attempt", name=account_name, default="账户 {name} 尝试重新登录..."))
533
658
  # 清空旧 token,强制走密码登录路径
534
659
  old_token = account.access_token
535
660
  account.access_token = ""
@@ -539,10 +664,10 @@ class MatrixAdapter(BaseAdapter):
539
664
  # 恢复旧 token,避免状态污染
540
665
  account.access_token = old_token
541
666
  raise
542
- self.logger.info(f"账户 {account_name} 重新登录成功")
667
+ self.logger.info(i18n.t("matrix.relogin_done", name=account_name, default="账户 {name} 重新登录成功"))
543
668
  return True
544
669
  except Exception as e:
545
- self.logger.error(f"账户 {account_name} 重新登录失败: {e}")
670
+ self.logger.error(i18n.t("matrix.relogin_failed", name=account_name, error=e, default="账户 {name} 重新登录失败: {error}"))
546
671
  return False
547
672
 
548
673
  async def _on_sync_loop_exit(self, account_name: str):
@@ -572,12 +697,12 @@ class MatrixAdapter(BaseAdapter):
572
697
  data = result["data"]
573
698
  runtime["_next_batch"] = data.get("next_batch", "")
574
699
  self.logger.info(
575
- f"账户 {account_name} 初始同步完成, next_batch: {runtime.get('_next_batch')}"
700
+ i18n.t("matrix.initial_sync_done", name=account_name, batch=runtime.get('_next_batch'), default="账户 {name} 初始同步完成, next_batch: {batch}")
576
701
  )
577
702
  return True
578
703
  else:
579
704
  self.logger.warning(
580
- f"账户 {account_name} 初始同步失败: {result.get('message', 'Unknown error')}"
705
+ i18n.t("matrix.initial_sync_failed", name=account_name, message=result.get('message', 'Unknown error'), default="账户 {name} 初始同步失败: {message}")
581
706
  )
582
707
  return False
583
708
 
@@ -599,7 +724,7 @@ class MatrixAdapter(BaseAdapter):
599
724
  runtime["_dm_rooms"] = dm_rooms
600
725
  if converter:
601
726
  converter.set_dm_rooms(dm_rooms)
602
- self.logger.info(f"账户 {account_name} 发现 {len(dm_rooms)} 个 DM 房间")
727
+ self.logger.info(i18n.t("matrix.dm_discovered", name=account_name, count=len(dm_rooms), default="账户 {name} 发现 {count} 个 DM 房间"))
603
728
 
604
729
  async def _process_sync_response(self, account_name: str, data: dict):
605
730
  runtime = self._get_runtime(account_name)
@@ -614,7 +739,7 @@ class MatrixAdapter(BaseAdapter):
614
739
  events = timeline.get("events", [])
615
740
 
616
741
  for event in events:
617
- self.logger.debug(f"账户 {account_name} 处理 Matrix 事件: {event}")
742
+ self.logger.debug(i18n.t("matrix.process_event", name=account_name, event=event, default="账户 {name} 处理 Matrix 事件: {event}"))
618
743
  try:
619
744
  if converter:
620
745
  onebot_event = converter.convert(
@@ -625,7 +750,7 @@ class MatrixAdapter(BaseAdapter):
625
750
  if onebot_event:
626
751
  await self.sdk.adapter.emit(onebot_event)
627
752
  except Exception as e:
628
- self.logger.error(f"处理事件失败: {e}")
753
+ self.logger.error(i18n.t("matrix.process_event_failed", error=e, default="处理事件失败: {error}"))
629
754
 
630
755
  invite_rooms = data.get("rooms", {}).get("invite", {})
631
756
  for room_id, room_data in invite_rooms.items():
@@ -637,7 +762,7 @@ class MatrixAdapter(BaseAdapter):
637
762
  content.get("membership") == "invite"
638
763
  and event.get("state_key") == bot_id
639
764
  ):
640
- self.logger.info(f"账户 {account_name} 收到房间邀请: {room_id}")
765
+ self.logger.info(i18n.t("matrix.room_invite", name=account_name, room=room_id, default="账户 {name} 收到房间邀请: {room}"))
641
766
  if getattr(
642
767
  self.accounts.get(account_name), "auto_accept_invites", True
643
768
  ):
@@ -648,17 +773,17 @@ class MatrixAdapter(BaseAdapter):
648
773
  _account_id=account_name,
649
774
  )
650
775
  self.logger.info(
651
- f"账户 {account_name} 已自动加入房间: {room_id}"
776
+ i18n.t("matrix.room_joined", name=account_name, room=room_id, default="账户 {name} 已自动加入房间: {room}")
652
777
  )
653
778
  except Exception as e:
654
- self.logger.error(f"加入房间失败: {e}")
779
+ self.logger.error(i18n.t("matrix.join_room_failed", error=e, default="加入房间失败: {error}"))
655
780
 
656
781
  async def _download_file(self, account_name: str, url: str) -> Optional[tuple]:
657
782
  try:
658
783
  resp = await client.get(url, timeout=300)
659
784
  if resp.status != 200:
660
785
  self.logger.error(
661
- f"账户 {account_name} 下载文件失败: HTTP {resp.status}"
786
+ i18n.t("matrix.download_failed", name=account_name, status=resp.status, default="账户 {name} 下载文件失败: HTTP {status}")
662
787
  )
663
788
  return None
664
789
  content_type = (
@@ -667,7 +792,7 @@ class MatrixAdapter(BaseAdapter):
667
792
  data = await resp.read()
668
793
  return (data, content_type)
669
794
  except Exception as e:
670
- self.logger.error(f"账户 {account_name} 下载文件异常: {e}")
795
+ self.logger.error(i18n.t("matrix.download_error", name=account_name, error=e, default="账户 {name} 下载文件异常: {error}"))
671
796
  return None
672
797
 
673
798
  async def _upload_media(
@@ -679,7 +804,7 @@ class MatrixAdapter(BaseAdapter):
679
804
  ) -> Optional[str]:
680
805
  account = self.accounts.get(account_name)
681
806
  if not account:
682
- self.logger.error(f"账户 {account_name} 不存在,无法上传媒体")
807
+ self.logger.error(i18n.t("matrix.account_not_found", name=account_name, default="账户 {name} 不存在,无法上传媒体"))
683
808
  return None
684
809
  if not content_type:
685
810
  content_type_map = {
@@ -692,8 +817,11 @@ class MatrixAdapter(BaseAdapter):
692
817
 
693
818
  homeserver = (account.homeserver or "https://matrix.org").rstrip("/")
694
819
  url = f"{homeserver}/_matrix/media/v3/upload"
820
+ # 优先使用运行时 token(同 call_api)
821
+ runtime = self._get_runtime(account_name)
822
+ access_token = runtime.get("access_token") or account.access_token
695
823
  headers = {
696
- "Authorization": f"Bearer {account.access_token}",
824
+ "Authorization": f"Bearer {access_token}",
697
825
  "Content-Type": content_type,
698
826
  }
699
827
 
@@ -703,10 +831,10 @@ class MatrixAdapter(BaseAdapter):
703
831
  if resp.status == 200:
704
832
  return data.get("content_uri", "")
705
833
  else:
706
- self.logger.error(f"账户 {account_name} 上传媒体失败: {data}")
834
+ self.logger.error(i18n.t("matrix.upload_failed", name=account_name, data=data, default="账户 {name} 上传媒体失败: {data}"))
707
835
  return None
708
836
  except Exception as e:
709
- self.logger.error(f"账户 {account_name} 上传媒体异常: {e}")
837
+ self.logger.error(i18n.t("matrix.upload_error", name=account_name, error=e, default="账户 {name} 上传媒体异常: {error}"))
710
838
  return None
711
839
 
712
840
  async def call_api(
@@ -715,8 +843,11 @@ class MatrixAdapter(BaseAdapter):
715
843
  account_name, account = self._resolve_account(_account_id)
716
844
  homeserver = (account.homeserver or "https://matrix.org").rstrip("/")
717
845
  url = f"{homeserver}{endpoint}"
846
+ # 优先使用运行时 token(密码登录后获得),避免 self.accounts 每次重新读取配置导致 token 丢失
847
+ runtime = self._get_runtime(account_name)
848
+ access_token = runtime.get("access_token") or account.access_token
718
849
  headers = {
719
- "Authorization": f"Bearer {account.access_token}",
850
+ "Authorization": f"Bearer {access_token}",
720
851
  "Content-Type": "application/json",
721
852
  }
722
853
  echo = params.pop("echo", None)
@@ -773,15 +904,15 @@ class MatrixAdapter(BaseAdapter):
773
904
  return response
774
905
 
775
906
  except asyncio.TimeoutError:
776
- self.logger.error(f"账户 {account_name} Matrix API 请求超时: {endpoint}")
777
- err = self.make_error(retcode=32000, message="请求超时", raw=None)
907
+ self.logger.error(i18n.t("matrix.api_timeout", name=account_name, endpoint=endpoint, default="账户 {name} Matrix API 请求超时: {endpoint}"))
908
+ err = self.make_error(retcode=32000, message=i18n.t("matrix.timeout_msg", default="请求超时"), raw=None)
778
909
  if echo:
779
910
  err["echo"] = echo
780
911
  return err
781
912
  except Exception as e:
782
- self.logger.error(f"账户 {account_name} 调用 Matrix API 失败: {e}")
913
+ self.logger.error(i18n.t("matrix.api_call_failed", name=account_name, error=e, default="账户 {name} 调用 Matrix API 失败: {error}"))
783
914
  err = self.make_error(
784
- retcode=33000, message=f"API调用失败: {str(e)}", raw=None
915
+ retcode=33000, message=i18n.t("matrix.api_error", error=str(e), default="API调用失败: {error}"), raw=None
785
916
  )
786
917
  if echo:
787
918
  err["echo"] = echo
@@ -800,7 +931,7 @@ class MatrixAdapter(BaseAdapter):
800
931
  self._running = True
801
932
 
802
933
  if not self.enabled_accounts:
803
- self.logger.warning("没有已启用的账户,Matrix 适配器将以空闲状态启动")
934
+ self.logger.warning(i18n.t("matrix.no_enabled_accounts", default="没有已启用的账户,Matrix 适配器将以空闲状态启动"))
804
935
  return
805
936
 
806
937
  for account_name, account in self.enabled_accounts.items():
@@ -819,7 +950,7 @@ class MatrixAdapter(BaseAdapter):
819
950
  runtime = self._get_runtime(account_name)
820
951
  if not runtime.get("bot_id"):
821
952
  self.logger.error(
822
- f"账户 {account_name} 无法获取 bot user_id,请检查配置"
953
+ i18n.t("matrix.no_bot_id", name=account_name, default="账户 {name} 无法获取 bot user_id,请检查配置")
823
954
  )
824
955
  continue
825
956
 
@@ -831,11 +962,11 @@ class MatrixAdapter(BaseAdapter):
831
962
  self._sync_loop(account_name)
832
963
  )
833
964
  self.logger.info(
834
- f"账户 {account_name} (bot_id: {runtime.get('bot_id')}) Matrix 已启动"
965
+ i18n.t("matrix.account_started", name=account_name, bot_id=runtime.get('bot_id'), default="账户 {name} (bot_id: {bot_id}) Matrix 已启动")
835
966
  )
836
967
 
837
968
  self.logger.info(
838
- f"Matrix 适配器启动完成,共 {len(self.enabled_accounts)} 个账户"
969
+ i18n.t("matrix.adapter_started", count=len(self.enabled_accounts), default="Matrix 适配器启动完成,共 {count} 个账户")
839
970
  )
840
971
 
841
972
  async def shutdown(self):
@@ -870,4 +1001,4 @@ class MatrixAdapter(BaseAdapter):
870
1001
  unregister_platform_event_methods("matrix")
871
1002
  except Exception:
872
1003
  pass
873
- self.logger.info("Matrix 适配器已关闭")
1004
+ self.logger.info(i18n.t("matrix.adapter_shutdown", default="Matrix 适配器已关闭"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-MatrixAdapter
3
- Version: 4.0.2
3
+ Version: 4.1.0
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.2"
3
+ version = "4.1.0"
4
4
  description = "ErisPulse的Matrix协议适配模块"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"