ErisPulse-MatrixAdapter 4.1.0__tar.gz → 4.2.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,15 +1,34 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-MatrixAdapter
3
- Version: 4.1.0
3
+ Version: 4.2.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
7
7
  Requires-Python: >=3.9
8
8
  Description-Content-Type: text/markdown
9
9
 
10
- # ErisPulse Matrix Adapter
10
+ <div align="center">
11
11
 
12
- [English](#english) | [中文](#中文)
12
+ <img src=".github/assets/ErisPulseLogo.png" width="180" alt="ErisPulse MatrixAdapter" />
13
+
14
+ # ErisPulse MatrixAdapter
15
+
16
+ **Matrix protocol adapter — decentralized chat via Long Polling sync.**
17
+
18
+ A Matrix protocol adapter built on the ErisPulse framework. It receives events via the Long Polling Sync API and unifies private chats, groups and rooms into OneBot12 standard events, with full support for mentions, replies, HTML rich text, reactions and MXC media.
19
+
20
+ <p>
21
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/pypi/v/ErisPulse-MatrixAdapter?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"></a>
22
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/badge/Python-3.10+-FFD43B?style=for-the-badge&logo=python&logoColor=blue" alt="Python"></a>
23
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge" alt="License"></a>
24
+ <a href="https://github.com/ErisPulse/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/github/stars/ErisPulse/ErisPulse-MatrixAdapter?style=for-the-badge&logo=github&color=brightgreen" alt="Stars"></a>
25
+ <a href="https://pepy.tech/project/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/pepy/dt/ErisPulse-MatrixAdapter?style=for-the-badge&color=blue" alt="Downloads"></a>
26
+ <a href="https://github.com/ErisPulse/ErisPulse"><img src="https://img.shields.io/badge/Powered_by-ErisPulse-FF6B9D?style=for-the-badge&logo=bookstack&logoColor=white" alt="ErisPulse"></a>
27
+ </p>
28
+
29
+ [English](#english) | [简体中文](#中文)
30
+
31
+ </div>
13
32
 
14
33
  ---
15
34
 
@@ -2,9 +2,12 @@ import time
2
2
  import uuid
3
3
  from typing import Dict, Optional, List
4
4
 
5
+ from ErisPulse.Core.Bases import BaseConverter
5
6
 
6
- class MatrixConverter:
7
+
8
+ class MatrixConverter(BaseConverter):
7
9
  def __init__(self, bot_user_id: str = ""):
10
+ super().__init__(platform="matrix")
8
11
  self.bot_user_id = bot_user_id
9
12
  self._dm_rooms: Dict[str, str] = {}
10
13
 
@@ -31,19 +34,13 @@ class MatrixConverter:
31
34
  if sender == self.bot_user_id:
32
35
  return None
33
36
 
34
- base_event = {
35
- "id": event_id,
36
- "time": event_time,
37
- "type": "",
38
- "detail_type": "",
39
- "platform": "matrix",
40
- "self": {
41
- "platform": "matrix",
42
- "user_id": self.bot_user_id,
43
- },
44
- "matrix_raw": raw_event,
45
- "matrix_raw_type": event_type,
46
- }
37
+ # 基础事件结构(BaseConverter 骨架 + Matrix 语义覆盖)
38
+ base_event = self.build_base_event(raw_event, event_type)
39
+ base_event["id"] = str(event_id)
40
+ base_event["time"] = event_time
41
+ base_event["type"] = ""
42
+ base_event["detail_type"] = ""
43
+ base_event["self"]["user_id"] = self.bot_user_id
47
44
 
48
45
  if is_dm:
49
46
  base_event["detail_type"] = "private"
@@ -61,6 +58,7 @@ class MatrixConverter:
61
58
 
62
59
  def _handle_m_room_message(self, raw_event: Dict, base_event: Dict, room_id: str, is_dm: bool) -> Dict:
63
60
  base_event["type"] = "message"
61
+ base_event["message_id"] = str(raw_event.get("event_id", ""))
64
62
  base_event["user_id"] = raw_event.get("sender", "")
65
63
  base_event["user_nickname"] = raw_event.get("sender", "")
66
64
 
@@ -7,12 +7,22 @@ from typing import Dict, List, Optional
7
7
 
8
8
  from ErisPulse.Core import client
9
9
  from ErisPulse.Core.Bases.adapter import BaseAdapter
10
+ from ErisPulse.Core.Bases import BotAccountConfig
10
11
  from ErisPulse.Core.Event import register_event_mixin, unregister_platform_event_methods
11
- from ErisPulse.runtime.config_schema import BotAccountConfig
12
12
  from ErisPulse.Core.i18n import i18n
13
13
 
14
14
  from .Converter import MatrixConverter
15
15
 
16
+ try:
17
+ from ErisPulse.runtime.tasks import spawn_background
18
+ except ImportError: # pragma: no cover
19
+ spawn_background = None
20
+
21
+ __version__ = "4.2.0"
22
+
23
+ # 软依赖的框架最低版本(运行时检测,仅提示不强制)
24
+ MIN_FRAMEWORK_VERSION = (2, 7, 1)
25
+
16
26
 
17
27
  # ============================================================================
18
28
  # 配置声明(多账户)
@@ -331,7 +341,40 @@ class MatrixAdapter(BaseAdapter):
331
341
  self._heartbeat_meta_tasks: Dict[str, asyncio.Task] = {}
332
342
  self._converters: Dict[str, MatrixConverter] = {}
333
343
  self._running = False
344
+ self._message_targets: Dict[str, str] = {}
334
345
  self._register_i18n()
346
+ self._check_framework_version()
347
+ self._get_logger().info(f"MatrixAdapter v{__version__} 已加载")
348
+
349
+ @staticmethod
350
+ def _parse_version(version_str: str) -> tuple:
351
+ """解析版本号为可比较的三元组(忽略 dev/预发布后缀,如 2.8.0-dev.3 → (2, 8, 0))"""
352
+ parts = []
353
+ for piece in str(version_str).split("."):
354
+ digits = "".join(ch for ch in piece if ch.isdigit())
355
+ parts.append(int(digits) if digits else 0)
356
+ while len(parts) < 3:
357
+ parts.append(0)
358
+ return tuple(parts[:3])
359
+
360
+ def _check_framework_version(self):
361
+ """软依赖检测:框架版本过低时打警告(不阻断加载)"""
362
+ try:
363
+ from importlib.metadata import version as _pkg_version
364
+
365
+ raw = _pkg_version("ErisPulse")
366
+ except Exception:
367
+ return
368
+ try:
369
+ if self._parse_version(raw) < MIN_FRAMEWORK_VERSION:
370
+ self._get_logger().warning(
371
+ f"当前 ErisPulse 版本 {raw} 过低:MatrixAdapter v{__version__} 需要 >= "
372
+ f"{'.'.join(map(str, MIN_FRAMEWORK_VERSION))}"
373
+ "(BaseConverter / Api DSL / spawn_background 等特性),"
374
+ "部分功能可能不可用,建议升级框架"
375
+ )
376
+ except Exception:
377
+ pass
335
378
 
336
379
  def _register_i18n(self):
337
380
  """注册配置字段与日志消息的 i18n 翻译"""
@@ -449,6 +492,39 @@ class MatrixAdapter(BaseAdapter):
449
492
  def _get_config_key(self) -> str:
450
493
  return "Matrix_Adapter"
451
494
 
495
+ async def _delete_message_by_id(self, message_id: str, account_id: Optional[str] = None) -> dict:
496
+ """按消息登记表撤回消息(Matrix redact 需要 room_id + event_id)"""
497
+ room_id = self._message_targets.get(message_id)
498
+ if not room_id:
499
+ return self.make_error(retcode=34001, message=f"未找到消息 {message_id} 的目标上下文,无法撤回")
500
+ import uuid as _uuid
501
+
502
+ txn_id = _uuid.uuid4().hex
503
+ return await self.call_api(
504
+ f"/_matrix/client/v3/rooms/{room_id}/redact/{message_id}/{txn_id}",
505
+ method="PUT", _account_id=account_id,
506
+ )
507
+
508
+ def _migrate_legacy_config(self):
509
+ """将旧版单账户扁平配置(access_token 直接在 [Matrix_Adapter] 下)迁移到 accounts 结构"""
510
+ try:
511
+ from ErisPulse.Core import config as config_mgr
512
+
513
+ key = self._get_config_key()
514
+ data = config_mgr.getConfig(key)
515
+ if not isinstance(data, dict):
516
+ return
517
+ accounts = data.get("accounts")
518
+ if isinstance(accounts, dict) and accounts:
519
+ return
520
+ if not data.get("access_token"):
521
+ return
522
+ data["accounts"] = {"default": {**data, "enabled": True}}
523
+ config_mgr.setConfig(key, data)
524
+ self.logger.info("已将旧版单账户配置迁移到 accounts.default")
525
+ except Exception as e:
526
+ self.logger.debug(f"旧配置迁移检查跳过: {e}")
527
+
452
528
  def _get_runtime(self, name: str) -> dict:
453
529
  if name not in self._account_runtime:
454
530
  self._account_runtime[name] = {
@@ -459,51 +535,8 @@ class MatrixAdapter(BaseAdapter):
459
535
  }
460
536
  return self._account_runtime[name]
461
537
 
462
- def _load_accounts(self) -> dict:
463
- from ErisPulse.Core.config import config as config_mgr
464
- from ErisPulse.runtime.config_schema import dict_to_dataclass
465
-
466
- key = "Matrix_Adapter.accounts"
467
- data = config_mgr.getConfig(key)
468
- if not data:
469
- # 兼容旧配置:如果存在旧的单账户 Matrix_Adapter 配置且有 access_token,迁移为 default 账户
470
- old = config_mgr.getConfig("Matrix_Adapter")
471
- if old and old.get("access_token"):
472
- self.logger.warning(
473
- i18n.t("matrix.old_config_detected", default="检测到旧格式单账户配置,建议迁移到 Matrix_Adapter.accounts.default")
474
- )
475
- data = {"default": {**old, "enabled": True}}
476
- else:
477
- data = {
478
- "default": {
479
- "homeserver": "https://matrix.org",
480
- "access_token": "",
481
- "user_id": "",
482
- "password": "",
483
- "auto_accept_invites": True,
484
- "enabled": True,
485
- }
486
- }
487
- try:
488
- config_mgr.setConfig(key, data)
489
- except Exception as e:
490
- self.logger.error(i18n.t("matrix.save_default_failed", error=e, default="保存默认配置失败: {error}"))
491
- accounts = {}
492
- for name, account_data in data.items():
493
- if not isinstance(account_data, dict):
494
- continue
495
- if not account_data.get("access_token") and not account_data.get("user_id"):
496
- self.logger.warning(i18n.t("matrix.missing_credentials", name=name, default="账户 '{name}' 缺少 access_token/user_id,已跳过"))
497
- continue
498
- instance = dict_to_dataclass(MatrixAccountConfig, account_data)
499
- instance.name = name
500
- if not instance.enabled:
501
- self.logger.warning(
502
- i18n.t("matrix.account_disabled", name=name, default="账户 '{name}' 已加载但未启用(enabled=false),请在配置中将 [Matrix_Adapter.accounts.{name}] 的 enabled 设为 true")
503
- )
504
- accounts[name] = instance
505
- self.logger.info(i18n.t("matrix.accounts_loaded", count=len(accounts), default="Matrix适配器初始化完成,共加载 {count} 个账户"))
506
- return accounts
538
+ # 账户加载使用框架默认实现(AccountConfigClass 模板 + 校验);
539
+ # 旧版单账户扁平配置迁移见 _migrate_legacy_config;缺少凭据的账户由 _login_if_needed 失败自然跳过。
507
540
 
508
541
  async def _login_if_needed(self, account_name: str, account: MatrixAccountConfig):
509
542
  runtime = self._get_runtime(account_name)
@@ -748,6 +781,10 @@ class MatrixAdapter(BaseAdapter):
748
781
  else:
749
782
  onebot_event = None
750
783
  if onebot_event:
784
+ if onebot_event.get("type") == "message" and onebot_event.get("message_id"):
785
+ self._message_targets[str(onebot_event["message_id"])] = str(room_id)
786
+ while len(self._message_targets) > 800:
787
+ self._message_targets.pop(next(iter(self._message_targets)), None)
751
788
  await self.sdk.adapter.emit(onebot_event)
752
789
  except Exception as e:
753
790
  self.logger.error(i18n.t("matrix.process_event_failed", error=e, default="处理事件失败: {error}"))
@@ -927,6 +964,116 @@ class MatrixAdapter(BaseAdapter):
927
964
  except asyncio.CancelledError:
928
965
  pass
929
966
 
967
+ # ==================== Api DSL ====================
968
+
969
+ class Api(BaseAdapter.Api):
970
+ """Matrix 标准 API 动作实现(ApiDSL,基于 Matrix Client-Server API)
971
+
972
+ {!--< tips >!--}
973
+ 1. get_self_info → GET /account/whoami
974
+ 2. get_user_info → GET /profile/{userId}
975
+ 3. get_group_info → GET /rooms/{roomId}/state/m.room.name
976
+ 4. get_group_list → GET /joined_rooms;get_group_member_list → GET /rooms/{roomId}/members
977
+ 5. delete_message → PUT /rooms/{roomId}/redact/{eventId}/{txn}(登记表补全 roomId)
978
+ 6. leave_group → POST /rooms/{roomId}/leave
979
+ {!--< /tips >!--}
980
+ """
981
+
982
+ async def get_self_info(self) -> dict:
983
+ r = await self._adapter.call_api(
984
+ "/_matrix/client/v3/account/whoami", method="GET",
985
+ _account_id=self._account_id,
986
+ )
987
+ if r.get("status") != "ok":
988
+ return r
989
+ u = r.get("data") or {}
990
+ r["data"] = {"user_id": str(u.get("user_id", "")), "user_name": str(u.get("user_id", "")).split(":")[0].lstrip("@")}
991
+ return r
992
+
993
+ async def get_user_info(self, user_id: str) -> dict:
994
+ r = await self._adapter.call_api(
995
+ f"/_matrix/client/v3/profile/{user_id}", method="GET",
996
+ _account_id=self._account_id,
997
+ )
998
+ if r.get("status") != "ok":
999
+ return r
1000
+ u = r.get("data") or {}
1001
+ r["data"] = {
1002
+ "user_id": str(user_id),
1003
+ "user_name": u.get("displayname", ""),
1004
+ "user_avatar": u.get("avatar_url", ""),
1005
+ }
1006
+ return r
1007
+
1008
+ async def get_group_info(self, room_id: str) -> dict:
1009
+ r = await self._adapter.call_api(
1010
+ f"/_matrix/client/v3/rooms/{room_id}/state/m.room.name", method="GET",
1011
+ _account_id=self._account_id,
1012
+ )
1013
+ if r.get("status") != "ok":
1014
+ return r
1015
+ r["data"] = {"group_id": str(room_id), "group_name": (r.get("data") or {}).get("name", "")}
1016
+ return r
1017
+
1018
+ async def get_group_list(self) -> dict:
1019
+ r = await self._adapter.call_api(
1020
+ "/_matrix/client/v3/joined_rooms", method="GET", _account_id=self._account_id
1021
+ )
1022
+ if r.get("status") != "ok":
1023
+ return r
1024
+ rooms = (r.get("data") or {}).get("joined_rooms", []) or []
1025
+ r["data"] = [{"group_id": str(x)} for x in rooms]
1026
+ return r
1027
+
1028
+ async def get_group_member_list(self, room_id: str) -> dict:
1029
+ r = await self._adapter.call_api(
1030
+ f"/_matrix/client/v3/rooms/{room_id}/members",
1031
+ method="GET", _account_id=self._account_id,
1032
+ )
1033
+ if r.get("status") != "ok":
1034
+ return r
1035
+ chunk = (r.get("data") or {}).get("chunk", []) or []
1036
+ members = []
1037
+ for m in chunk:
1038
+ if isinstance(m, dict) and m.get("sender"):
1039
+ members.append({"user_id": str(m["sender"])})
1040
+ r["data"] = members
1041
+ return r
1042
+
1043
+ async def leave_group(self, room_id: str) -> dict:
1044
+ return await self._adapter.call_api(
1045
+ f"/_matrix/client/v3/rooms/{room_id}/leave", method="POST",
1046
+ _account_id=self._account_id,
1047
+ )
1048
+
1049
+ async def delete_message(self, message_id: str) -> dict:
1050
+ return await self._adapter._delete_message_by_id(str(message_id), account_id=self._account_id)
1051
+
1052
+ async def get_status(self) -> dict:
1053
+ ad = self._adapter
1054
+ bots = []
1055
+ for name, runtime in ad._account_runtime.items():
1056
+ bots.append({
1057
+ "self": {"platform": ad.platform, "user_id": runtime.get("bot_id", ""), "account_id": name},
1058
+ "online": bool(runtime.get("bot_id")),
1059
+ })
1060
+ return ad.make_response(data={"good": any(b["online"] for b in bots), "bots": bots})
1061
+
1062
+ async def get_version(self) -> dict:
1063
+ from . import __version__
1064
+
1065
+ return self._adapter.make_response(
1066
+ data={"impl": "ErisPulse-MatrixAdapter", "version": __version__, "onebot_version": "12"}
1067
+ )
1068
+
1069
+ async def get_supported_actions(self) -> dict:
1070
+ actions = {
1071
+ "get_self_info", "get_user_info", "get_group_info", "get_group_list",
1072
+ "get_group_member_list", "leave_group", "delete_message",
1073
+ "get_status", "get_version", "get_supported_actions",
1074
+ }
1075
+ return self._adapter.make_response(data=sorted(actions))
1076
+
930
1077
  async def start(self):
931
1078
  self._running = True
932
1079
 
@@ -955,11 +1102,14 @@ class MatrixAdapter(BaseAdapter):
955
1102
  continue
956
1103
 
957
1104
  await self.emit_meta("connect", runtime.get("bot_id", ""))
958
- self._heartbeat_meta_tasks[account_name] = asyncio.create_task(
959
- self._heartbeat_meta_loop(account_name)
1105
+ hb_coro = self._heartbeat_meta_loop(account_name)
1106
+ sync_coro = self._sync_loop(account_name)
1107
+ # 生命周期任务使用 spawn_background(owner 归属,shutdown 自动回收)
1108
+ self._heartbeat_meta_tasks[account_name] = (
1109
+ spawn_background(hb_coro) if spawn_background is not None else asyncio.create_task(hb_coro)
960
1110
  )
961
- self._sync_tasks[account_name] = asyncio.create_task(
962
- self._sync_loop(account_name)
1111
+ self._sync_tasks[account_name] = (
1112
+ spawn_background(sync_coro) if spawn_background is not None else asyncio.create_task(sync_coro)
963
1113
  )
964
1114
  self.logger.info(
965
1115
  i18n.t("matrix.account_started", name=account_name, bot_id=runtime.get('bot_id'), default="账户 {name} (bot_id: {bot_id}) Matrix 已启动")
@@ -0,0 +1,3 @@
1
+ from .Core import MatrixAdapter, __version__
2
+
3
+ __all__ = ["MatrixAdapter", "__version__"]
@@ -1,15 +1,34 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse-MatrixAdapter
3
- Version: 4.1.0
3
+ Version: 4.2.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
7
7
  Requires-Python: >=3.9
8
8
  Description-Content-Type: text/markdown
9
9
 
10
- # ErisPulse Matrix Adapter
10
+ <div align="center">
11
11
 
12
- [English](#english) | [中文](#中文)
12
+ <img src=".github/assets/ErisPulseLogo.png" width="180" alt="ErisPulse MatrixAdapter" />
13
+
14
+ # ErisPulse MatrixAdapter
15
+
16
+ **Matrix protocol adapter — decentralized chat via Long Polling sync.**
17
+
18
+ A Matrix protocol adapter built on the ErisPulse framework. It receives events via the Long Polling Sync API and unifies private chats, groups and rooms into OneBot12 standard events, with full support for mentions, replies, HTML rich text, reactions and MXC media.
19
+
20
+ <p>
21
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/pypi/v/ErisPulse-MatrixAdapter?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"></a>
22
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/badge/Python-3.10+-FFD43B?style=for-the-badge&logo=python&logoColor=blue" alt="Python"></a>
23
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge" alt="License"></a>
24
+ <a href="https://github.com/ErisPulse/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/github/stars/ErisPulse/ErisPulse-MatrixAdapter?style=for-the-badge&logo=github&color=brightgreen" alt="Stars"></a>
25
+ <a href="https://pepy.tech/project/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/pepy/dt/ErisPulse-MatrixAdapter?style=for-the-badge&color=blue" alt="Downloads"></a>
26
+ <a href="https://github.com/ErisPulse/ErisPulse"><img src="https://img.shields.io/badge/Powered_by-ErisPulse-FF6B9D?style=for-the-badge&logo=bookstack&logoColor=white" alt="ErisPulse"></a>
27
+ </p>
28
+
29
+ [English](#english) | [简体中文](#中文)
30
+
31
+ </div>
13
32
 
14
33
  ---
15
34
 
@@ -1,6 +1,25 @@
1
- # ErisPulse Matrix Adapter
1
+ <div align="center">
2
2
 
3
- [English](#english) | [中文](#中文)
3
+ <img src=".github/assets/ErisPulseLogo.png" width="180" alt="ErisPulse MatrixAdapter" />
4
+
5
+ # ErisPulse MatrixAdapter
6
+
7
+ **Matrix protocol adapter — decentralized chat via Long Polling sync.**
8
+
9
+ A Matrix protocol adapter built on the ErisPulse framework. It receives events via the Long Polling Sync API and unifies private chats, groups and rooms into OneBot12 standard events, with full support for mentions, replies, HTML rich text, reactions and MXC media.
10
+
11
+ <p>
12
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/pypi/v/ErisPulse-MatrixAdapter?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"></a>
13
+ <a href="https://pypi.org/project/ErisPulse-MatrixAdapter/"><img src="https://img.shields.io/badge/Python-3.10+-FFD43B?style=for-the-badge&logo=python&logoColor=blue" alt="Python"></a>
14
+ <a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge" alt="License"></a>
15
+ <a href="https://github.com/ErisPulse/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/github/stars/ErisPulse/ErisPulse-MatrixAdapter?style=for-the-badge&logo=github&color=brightgreen" alt="Stars"></a>
16
+ <a href="https://pepy.tech/project/ErisPulse-MatrixAdapter"><img src="https://img.shields.io/pepy/dt/ErisPulse-MatrixAdapter?style=for-the-badge&color=blue" alt="Downloads"></a>
17
+ <a href="https://github.com/ErisPulse/ErisPulse"><img src="https://img.shields.io/badge/Powered_by-ErisPulse-FF6B9D?style=for-the-badge&logo=bookstack&logoColor=white" alt="ErisPulse"></a>
18
+ </p>
19
+
20
+ [English](#english) | [简体中文](#中文)
21
+
22
+ </div>
4
23
 
5
24
  ---
6
25
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "ErisPulse-MatrixAdapter"
3
- version = "4.1.0"
3
+ version = "4.2.0"
4
4
  description = "ErisPulse的Matrix协议适配模块"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
@@ -1 +0,0 @@
1
- from .Core import MatrixAdapter