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.
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/ErisPulse_MatrixAdapter.egg-info/PKG-INFO +22 -3
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/MatrixAdapter/Converter.py +12 -14
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/MatrixAdapter/Core.py +200 -50
- erispulse_matrixadapter-4.2.0/MatrixAdapter/__init__.py +3 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/PKG-INFO +22 -3
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/README.md +21 -2
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/pyproject.toml +1 -1
- erispulse_matrixadapter-4.1.0/MatrixAdapter/__init__.py +0 -1
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/ErisPulse_MatrixAdapter.egg-info/SOURCES.txt +0 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/ErisPulse_MatrixAdapter.egg-info/dependency_links.txt +0 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/ErisPulse_MatrixAdapter.egg-info/entry_points.txt +0 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/ErisPulse_MatrixAdapter.egg-info/top_level.txt +0 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/setup.cfg +0 -0
- {erispulse_matrixadapter-4.1.0 → erispulse_matrixadapter-4.2.0}/test/test.py +0 -0
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse-MatrixAdapter
|
|
3
|
-
Version: 4.
|
|
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
|
-
|
|
10
|
+
<div align="center">
|
|
11
11
|
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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
|
-
|
|
463
|
-
|
|
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
|
-
|
|
959
|
-
|
|
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] =
|
|
962
|
-
|
|
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 已启动")
|
|
@@ -1,15 +1,34 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse-MatrixAdapter
|
|
3
|
-
Version: 4.
|
|
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
|
-
|
|
10
|
+
<div align="center">
|
|
11
11
|
|
|
12
|
-
|
|
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
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
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 +0,0 @@
|
|
|
1
|
-
from .Core import MatrixAdapter
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|