ErisPulse 2.2.1.dev0__py3-none-any.whl → 2.3.0__py3-none-any.whl
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/Core/Bases/__init__.py +14 -0
- ErisPulse/Core/Bases/adapter.py +196 -0
- ErisPulse/Core/Bases/module.py +54 -0
- ErisPulse/Core/Event/__init__.py +14 -0
- ErisPulse/Core/Event/base.py +15 -2
- ErisPulse/Core/Event/command.py +21 -2
- ErisPulse/Core/Event/message.py +15 -0
- ErisPulse/Core/Event/meta.py +15 -0
- ErisPulse/Core/Event/notice.py +15 -0
- ErisPulse/Core/Event/request.py +16 -1
- ErisPulse/Core/__init__.py +38 -19
- ErisPulse/Core/{erispulse_config.py → _self_config.py} +27 -2
- ErisPulse/Core/adapter.py +374 -377
- ErisPulse/Core/config.py +137 -38
- ErisPulse/Core/exceptions.py +6 -1
- ErisPulse/Core/lifecycle.py +167 -0
- ErisPulse/Core/logger.py +97 -49
- ErisPulse/Core/module.py +279 -56
- ErisPulse/Core/router.py +112 -23
- ErisPulse/Core/storage.py +258 -77
- ErisPulse/Core/ux.py +635 -0
- ErisPulse/__init__.py +722 -244
- ErisPulse/__main__.py +1 -1999
- ErisPulse/utils/__init__.py +17 -0
- ErisPulse/utils/cli.py +1092 -0
- ErisPulse/utils/console.py +53 -0
- ErisPulse/utils/package_manager.py +845 -0
- ErisPulse/utils/reload_handler.py +111 -0
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/METADATA +24 -6
- erispulse-2.3.0.dist-info/RECORD +34 -0
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/WHEEL +1 -1
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/licenses/LICENSE +1 -1
- ErisPulse/Core/env.py +0 -15
- ErisPulse/Core/module_registry.py +0 -227
- erispulse-2.2.1.dev0.dist-info/RECORD +0 -26
- {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/entry_points.txt +0 -0
ErisPulse/Core/adapter.py
CHANGED
|
@@ -1,240 +1,26 @@
|
|
|
1
1
|
"""
|
|
2
2
|
ErisPulse 适配器系统
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
{!--< tips >!--}
|
|
7
|
-
1. 适配器必须继承BaseAdapter并实现必要方法
|
|
8
|
-
2. 使用SendDSL实现链式调用风格的消息发送接口
|
|
9
|
-
3. 适配器管理器支持多平台适配器的注册和生命周期管理
|
|
10
|
-
4. 支持OneBot12协议的事件处理
|
|
11
|
-
{!--< /tips >!--}
|
|
4
|
+
提供平台适配器管理功能。支持多平台消息处理、事件驱动和生命周期管理。
|
|
12
5
|
"""
|
|
13
6
|
|
|
14
7
|
import functools
|
|
15
8
|
import asyncio
|
|
16
9
|
from typing import (
|
|
17
|
-
Callable, Any, Dict, List, Type, Optional, Set
|
|
18
|
-
Union, Awaitable
|
|
10
|
+
Callable, Any, Dict, List, Type, Optional, Set
|
|
19
11
|
)
|
|
20
12
|
from collections import defaultdict
|
|
21
13
|
from .logger import logger
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
消息发送DSL基类
|
|
26
|
-
|
|
27
|
-
用于实现 Send.To(...).Func(...) 风格的链式调用接口
|
|
28
|
-
|
|
29
|
-
{!--< tips >!--}
|
|
30
|
-
1. 子类应实现具体的消息发送方法(如Text, Image等)
|
|
31
|
-
2. 通过__getattr__实现动态方法调用
|
|
32
|
-
{!--< /tips >!--}
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
def __init__(self, adapter: 'BaseAdapter', target_type: Optional[str] = None, target_id: Optional[str] = None, account_id: Optional[str] = None):
|
|
36
|
-
"""
|
|
37
|
-
初始化DSL发送器
|
|
38
|
-
|
|
39
|
-
:param adapter: 所属适配器实例
|
|
40
|
-
:param target_type: 目标类型(可选)
|
|
41
|
-
:param target_id: 目标ID(可选)
|
|
42
|
-
:param _account_id: 发送账号(可选)
|
|
43
|
-
"""
|
|
44
|
-
self._adapter = adapter
|
|
45
|
-
self._target_type = target_type
|
|
46
|
-
self._target_id = target_id
|
|
47
|
-
self._target_to = target_id
|
|
48
|
-
self._account_id = account_id
|
|
49
|
-
|
|
50
|
-
def To(self, target_type: str = None, target_id: Union[str, int] = None) -> 'SendDSL':
|
|
51
|
-
"""
|
|
52
|
-
设置消息目标
|
|
53
|
-
|
|
54
|
-
:param target_type: 目标类型(可选)
|
|
55
|
-
:param target_id: 目标ID(可选)
|
|
56
|
-
:return: SendDSL实例
|
|
57
|
-
|
|
58
|
-
:example:
|
|
59
|
-
>>> adapter.Send.To("user", "123").Text("Hello")
|
|
60
|
-
>>> adapter.Send.To("123").Text("Hello") # 简化形式
|
|
61
|
-
"""
|
|
62
|
-
if target_id is None and target_type is not None:
|
|
63
|
-
target_id = target_type
|
|
64
|
-
target_type = None
|
|
65
|
-
|
|
66
|
-
return self.__class__(self._adapter, target_type, target_id, self._account_id)
|
|
67
|
-
|
|
68
|
-
def Using(self, account_id: Union[str, int]) -> 'SendDSL':
|
|
69
|
-
"""
|
|
70
|
-
设置发送账号
|
|
71
|
-
|
|
72
|
-
:param _account_id: 发送账号
|
|
73
|
-
:return: SendDSL实例
|
|
74
|
-
|
|
75
|
-
:example:
|
|
76
|
-
>>> adapter.Send.Using("bot1").To("123").Text("Hello")
|
|
77
|
-
>>> adapter.Send.To("123").Using("bot1").Text("Hello") # 支持乱序
|
|
78
|
-
"""
|
|
79
|
-
return self.__class__(self._adapter, self._target_type, self._target_id, account_id)
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
class BaseAdapter:
|
|
83
|
-
"""
|
|
84
|
-
适配器基类
|
|
85
|
-
|
|
86
|
-
提供与外部平台交互的标准接口,子类必须实现必要方法
|
|
87
|
-
|
|
88
|
-
{!--< tips >!--}
|
|
89
|
-
1. 必须实现call_api, start和shutdown方法
|
|
90
|
-
2. 可以自定义Send类实现平台特定的消息发送逻辑
|
|
91
|
-
3. 通过on装饰器注册事件处理器
|
|
92
|
-
4. 支持OneBot12协议的事件处理
|
|
93
|
-
{!--< /tips >!--}
|
|
94
|
-
"""
|
|
95
|
-
|
|
96
|
-
class Send(SendDSLBase):
|
|
97
|
-
"""
|
|
98
|
-
消息发送DSL实现
|
|
99
|
-
|
|
100
|
-
{!--< tips >!--}
|
|
101
|
-
1. 子类可以重写Text方法提供平台特定实现
|
|
102
|
-
2. 可以添加新的消息类型(如Image, Voice等)
|
|
103
|
-
{!--< /tips >!--}
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
def Example(self, text: str) -> Awaitable[Any]:
|
|
107
|
-
"""
|
|
108
|
-
示例消息发送方法
|
|
109
|
-
|
|
110
|
-
:param text: 文本内容
|
|
111
|
-
:return: 异步任务
|
|
112
|
-
:example:
|
|
113
|
-
>>> await adapter.Send.To("123").Example("Hello")
|
|
114
|
-
"""
|
|
115
|
-
logger.debug(f"适配器 {self._adapter.__class__.__name__} 发送了实例类型的消息: {text}")
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def __init__(self):
|
|
119
|
-
"""
|
|
120
|
-
初始化适配器
|
|
121
|
-
"""
|
|
122
|
-
self._handlers = defaultdict(list)
|
|
123
|
-
self._middlewares = []
|
|
124
|
-
self.Send = self.__class__.Send(self)
|
|
125
|
-
|
|
126
|
-
def on(self, event_type: str = "*") -> Callable[[Callable], Callable]:
|
|
127
|
-
"""
|
|
128
|
-
适配器事件监听装饰器
|
|
129
|
-
|
|
130
|
-
:param event_type: 事件类型
|
|
131
|
-
:return: 装饰器函数
|
|
132
|
-
"""
|
|
133
|
-
def decorator(func: Callable) -> Callable:
|
|
134
|
-
@functools.wraps(func)
|
|
135
|
-
async def wrapper(*args, **kwargs):
|
|
136
|
-
return await func(*args, **kwargs)
|
|
137
|
-
self._handlers[event_type].append(wrapper)
|
|
138
|
-
|
|
139
|
-
return wrapper
|
|
140
|
-
return decorator
|
|
141
|
-
|
|
142
|
-
def middleware(self, func: Callable) -> Callable:
|
|
143
|
-
"""
|
|
144
|
-
添加中间件处理器
|
|
145
|
-
|
|
146
|
-
:param func: 中间件函数
|
|
147
|
-
:return: 中间件函数
|
|
148
|
-
|
|
149
|
-
:example:
|
|
150
|
-
>>> @adapter.middleware
|
|
151
|
-
>>> async def log_middleware(data):
|
|
152
|
-
>>> print(f"处理数据: {data}")
|
|
153
|
-
>>> return data
|
|
154
|
-
"""
|
|
155
|
-
self._middlewares.append(func)
|
|
156
|
-
return func
|
|
157
|
-
|
|
158
|
-
async def call_api(self, endpoint: str, **params: Any) -> Any:
|
|
159
|
-
"""
|
|
160
|
-
调用平台API的抽象方法
|
|
161
|
-
|
|
162
|
-
:param endpoint: API端点
|
|
163
|
-
:param params: API参数
|
|
164
|
-
:return: API调用结果
|
|
165
|
-
:raises NotImplementedError: 必须由子类实现
|
|
166
|
-
"""
|
|
167
|
-
raise NotImplementedError("适配器必须实现call_api方法")
|
|
168
|
-
|
|
169
|
-
async def start(self) -> None:
|
|
170
|
-
"""
|
|
171
|
-
启动适配器的抽象方法
|
|
172
|
-
|
|
173
|
-
:raises NotImplementedError: 必须由子类实现
|
|
174
|
-
"""
|
|
175
|
-
raise NotImplementedError("适配器必须实现start方法")
|
|
176
|
-
|
|
177
|
-
async def shutdown(self) -> None:
|
|
178
|
-
"""
|
|
179
|
-
关闭适配器的抽象方法
|
|
180
|
-
|
|
181
|
-
:raises NotImplementedError: 必须由子类实现
|
|
182
|
-
"""
|
|
183
|
-
raise NotImplementedError("适配器必须实现shutdown方法")
|
|
184
|
-
|
|
185
|
-
async def emit(self, event_type: str, data: Any) -> None:
|
|
186
|
-
"""
|
|
187
|
-
触发原生协议事件
|
|
188
|
-
|
|
189
|
-
:param event_type: 事件类型
|
|
190
|
-
:param data: 事件数据
|
|
191
|
-
|
|
192
|
-
:example:
|
|
193
|
-
>>> await adapter.emit("message", {"text": "Hello"})
|
|
194
|
-
"""
|
|
195
|
-
# 先执行中间件
|
|
196
|
-
for middleware in self._middlewares:
|
|
197
|
-
data = await middleware(data)
|
|
198
|
-
|
|
199
|
-
# 触发具体事件类型的处理器
|
|
200
|
-
if event_type in self._handlers:
|
|
201
|
-
for handler in self._handlers[event_type]:
|
|
202
|
-
await handler(data)
|
|
203
|
-
|
|
204
|
-
# 触发通配符 "*" 的处理器
|
|
205
|
-
for handler in self._handlers.get("*", []):
|
|
206
|
-
await handler(data)
|
|
207
|
-
|
|
208
|
-
async def send(self, target_type: str, target_id: str, message: Any, **kwargs: Any) -> Any:
|
|
209
|
-
"""
|
|
210
|
-
发送消息的便捷方法
|
|
211
|
-
|
|
212
|
-
:param target_type: 目标类型
|
|
213
|
-
:param target_id: 目标ID
|
|
214
|
-
:param message: 消息内容
|
|
215
|
-
:param kwargs: 其他参数
|
|
216
|
-
- method: 发送方法名(默认为"Text")
|
|
217
|
-
:return: 发送结果
|
|
218
|
-
|
|
219
|
-
:raises AttributeError: 当发送方法不存在时抛出
|
|
220
|
-
|
|
221
|
-
:example:
|
|
222
|
-
>>> await adapter.send("user", "123", "Hello")
|
|
223
|
-
>>> await adapter.send("group", "456", "Hello", method="Markdown")
|
|
224
|
-
"""
|
|
225
|
-
method_name = kwargs.pop("method", "Text")
|
|
226
|
-
method = getattr(self.Send.To(target_type, target_id), method_name, None)
|
|
227
|
-
if not method:
|
|
228
|
-
raise AttributeError(f"未找到 {method_name} 方法,请确保已在 Send 类中定义")
|
|
229
|
-
return await method(text=message, **kwargs)
|
|
230
|
-
|
|
14
|
+
from .Bases.adapter import BaseAdapter
|
|
15
|
+
from .config import config
|
|
16
|
+
from .lifecycle import lifecycle
|
|
231
17
|
|
|
232
18
|
class AdapterManager:
|
|
233
19
|
"""
|
|
234
20
|
适配器管理器
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
21
|
+
|
|
22
|
+
管理多个平台适配器的注册、启动和关闭,提供与模块管理器一致的接口
|
|
23
|
+
|
|
238
24
|
{!--< tips >!--}
|
|
239
25
|
1. 通过register方法注册适配器
|
|
240
26
|
2. 通过startup方法启动适配器
|
|
@@ -242,133 +28,76 @@ class AdapterManager:
|
|
|
242
28
|
4. 通过on装饰器注册OneBot12协议事件处理器
|
|
243
29
|
{!--< /tips >!--}
|
|
244
30
|
"""
|
|
245
|
-
|
|
31
|
+
|
|
246
32
|
def __init__(self):
|
|
247
|
-
|
|
248
|
-
self.
|
|
249
|
-
self.
|
|
250
|
-
self.
|
|
251
|
-
|
|
33
|
+
# 适配器存储 - 简化数据结构
|
|
34
|
+
self._adapters: Dict[str, BaseAdapter] = {} # 平台名到实例的映射
|
|
35
|
+
self._started_instances: Set[BaseAdapter] = set() # 已启动的实例
|
|
36
|
+
self._adapter_info: Dict[str, Dict] = {} # 适配器信息
|
|
37
|
+
|
|
252
38
|
# OneBot12事件处理器
|
|
253
39
|
self._onebot_handlers = defaultdict(list)
|
|
254
40
|
self._onebot_middlewares = []
|
|
41
|
+
# 原生事件处理器
|
|
42
|
+
self._raw_handlers = defaultdict(list)
|
|
255
43
|
|
|
256
|
-
|
|
257
|
-
def Adapter(self) -> Type[BaseAdapter]:
|
|
258
|
-
"""
|
|
259
|
-
获取BaseAdapter类,用于访问原始事件监听
|
|
260
|
-
|
|
261
|
-
:return: BaseAdapter类
|
|
262
|
-
|
|
263
|
-
:example:
|
|
264
|
-
>>> @sdk.adapter.Adapter.on("raw_event")
|
|
265
|
-
>>> async def handle_raw(data):
|
|
266
|
-
>>> print("收到原始事件:", data)
|
|
267
|
-
"""
|
|
268
|
-
return BaseAdapter
|
|
44
|
+
# ==================== 适配器注册与管理 ====================
|
|
269
45
|
|
|
270
|
-
def
|
|
271
|
-
"""
|
|
272
|
-
OneBot12协议事件监听装饰器
|
|
273
|
-
|
|
274
|
-
:param event_type: OneBot12事件类型
|
|
275
|
-
:return: 装饰器函数
|
|
276
|
-
|
|
277
|
-
:example:
|
|
278
|
-
>>> @sdk.adapter.on("message")
|
|
279
|
-
>>> async def handle_message(data):
|
|
280
|
-
>>> print(f"收到OneBot12消息: {data}")
|
|
46
|
+
def register(self, platform: str, adapter_class: Type[BaseAdapter], adapter_info: Optional[Dict] = None) -> bool:
|
|
281
47
|
"""
|
|
282
|
-
|
|
283
|
-
@functools.wraps(func)
|
|
284
|
-
async def wrapper(*args, **kwargs):
|
|
285
|
-
return await func(*args, **kwargs)
|
|
286
|
-
|
|
287
|
-
self._onebot_handlers[event_type].append(wrapper)
|
|
288
|
-
return wrapper
|
|
289
|
-
return decorator
|
|
48
|
+
注册新的适配器类(标准化注册方法)
|
|
290
49
|
|
|
291
|
-
def middleware(self, func: Callable) -> Callable:
|
|
292
|
-
"""
|
|
293
|
-
添加OneBot12中间件处理器
|
|
294
|
-
|
|
295
|
-
:param func: 中间件函数
|
|
296
|
-
:return: 中间件函数
|
|
297
|
-
|
|
298
|
-
:example:
|
|
299
|
-
>>> @sdk.adapter.middleware
|
|
300
|
-
>>> async def onebot_middleware(data):
|
|
301
|
-
>>> print("处理OneBot12数据:", data)
|
|
302
|
-
>>> return data
|
|
303
|
-
"""
|
|
304
|
-
self._onebot_middlewares.append(func)
|
|
305
|
-
return func
|
|
306
|
-
|
|
307
|
-
async def emit(self, data: Any) -> None:
|
|
308
|
-
"""
|
|
309
|
-
提交OneBot12协议事件到指定平台
|
|
310
|
-
|
|
311
|
-
:param platform: 平台名称
|
|
312
|
-
:param event_type: OneBot12事件类型
|
|
313
|
-
:param data: 符合OneBot12标准的事件数据
|
|
314
|
-
|
|
315
|
-
:raises ValueError: 当平台未注册时抛出
|
|
316
|
-
|
|
317
|
-
:example:
|
|
318
|
-
>>> await sdk.adapter.emit("MyPlatform", "message", {
|
|
319
|
-
>>> "id": "123",
|
|
320
|
-
>>> "time": 1620000000,
|
|
321
|
-
>>> "type": "message",
|
|
322
|
-
>>> "detail_type": "private",
|
|
323
|
-
>>> "message": [{"type": "text", "data": {"text": "Hello"}}]
|
|
324
|
-
>>> })
|
|
325
|
-
"""
|
|
326
|
-
platform = data.get("platform", "unknown")
|
|
327
|
-
event_type = data.get("type", "unknown")
|
|
328
|
-
|
|
329
|
-
if platform not in self._adapters:
|
|
330
|
-
raise ValueError(f"平台 {platform} 未注册")
|
|
331
|
-
|
|
332
|
-
# 先执行OneBot12中间件
|
|
333
|
-
processed_data = data
|
|
334
|
-
for middleware in self._onebot_middlewares:
|
|
335
|
-
processed_data = await middleware(processed_data)
|
|
336
|
-
|
|
337
|
-
# 分发到OneBot12事件处理器
|
|
338
|
-
if event_type in self._onebot_handlers:
|
|
339
|
-
for handler in self._onebot_handlers[event_type]:
|
|
340
|
-
await handler(processed_data)
|
|
341
|
-
for handler in self._onebot_handlers.get("*", []):
|
|
342
|
-
await handler(processed_data)
|
|
343
|
-
|
|
344
|
-
def register(self, platform: str, adapter_class: Type[BaseAdapter]) -> bool:
|
|
345
|
-
"""
|
|
346
|
-
注册新的适配器类
|
|
347
|
-
|
|
348
50
|
:param platform: 平台名称
|
|
349
51
|
:param adapter_class: 适配器类
|
|
52
|
+
:param adapter_info: 适配器信息
|
|
350
53
|
:return: 注册是否成功
|
|
351
|
-
|
|
54
|
+
|
|
352
55
|
:raises TypeError: 当适配器类无效时抛出
|
|
353
|
-
|
|
56
|
+
|
|
354
57
|
:example:
|
|
355
58
|
>>> adapter.register("MyPlatform", MyPlatformAdapter)
|
|
356
59
|
"""
|
|
60
|
+
logger.info(f"注册适配器 {platform}({adapter_class.__name__})")
|
|
357
61
|
if not issubclass(adapter_class, BaseAdapter):
|
|
358
|
-
raise TypeError("适配器必须继承自BaseAdapter")
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
62
|
+
raise TypeError("适配器必须继承自BaseAdapter,否则我们无法加载这个适配器,它会导致未知的错误")
|
|
63
|
+
|
|
64
|
+
# 检查是否已存在该平台的适配器
|
|
65
|
+
if platform in self._adapters:
|
|
66
|
+
logger.warning(f"平台 {platform} 已存在,将覆盖原适配器")
|
|
67
|
+
|
|
68
|
+
if adapter_info:
|
|
69
|
+
self._adapter_info[platform] = adapter_info
|
|
70
|
+
|
|
71
|
+
# 检查是否已存在相同类的适配器实例
|
|
72
|
+
existing_instance = None
|
|
73
|
+
for existing_platform, existing_adapter in self._adapters.items():
|
|
74
|
+
if existing_adapter.__class__ == adapter_class:
|
|
75
|
+
existing_instance = existing_adapter
|
|
76
|
+
break
|
|
77
|
+
|
|
78
|
+
# 如果存在相同类的适配器实例,直接绑定到已注册的实例
|
|
79
|
+
if existing_instance is not None:
|
|
80
|
+
self._adapters[platform] = existing_instance
|
|
81
|
+
logger.debug(f"适配器 {platform} 已绑定到已注册的实例 {existing_platform}")
|
|
364
82
|
else:
|
|
83
|
+
# 创建适配器实例
|
|
84
|
+
from .. import sdk
|
|
365
85
|
instance = adapter_class(sdk)
|
|
366
|
-
self.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
self.
|
|
371
|
-
|
|
86
|
+
self._adapters[platform] = instance
|
|
87
|
+
logger.debug(f"适配器 {platform} 注册成功")
|
|
88
|
+
|
|
89
|
+
# 注册平台名称的多种大小写形式作为属性
|
|
90
|
+
self._register_platform_attributes(platform, self._adapters[platform])
|
|
91
|
+
|
|
92
|
+
return True
|
|
93
|
+
|
|
94
|
+
def _register_platform_attributes(self, platform: str, instance: BaseAdapter) -> None:
|
|
95
|
+
"""
|
|
96
|
+
注册平台名称的多种大小写形式作为属性
|
|
97
|
+
|
|
98
|
+
:param platform: 平台名称
|
|
99
|
+
:param instance: 适配器实例
|
|
100
|
+
"""
|
|
372
101
|
if len(platform) <= 10:
|
|
373
102
|
from itertools import product
|
|
374
103
|
combinations = [''.join(c) for c in product(*[(ch.lower(), ch.upper()) for ch in platform])]
|
|
@@ -380,16 +109,14 @@ class AdapterManager:
|
|
|
380
109
|
setattr(self, platform.upper(), instance)
|
|
381
110
|
setattr(self, platform.capitalize(), instance)
|
|
382
111
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
async def startup(self, platforms: List[str] = None) -> None:
|
|
112
|
+
async def startup(self, platforms = None) -> None:
|
|
386
113
|
"""
|
|
387
114
|
启动指定的适配器
|
|
388
|
-
|
|
115
|
+
|
|
389
116
|
:param platforms: 要启动的平台列表,None表示所有平台
|
|
390
|
-
|
|
117
|
+
|
|
391
118
|
:raises ValueError: 当平台未注册时抛出
|
|
392
|
-
|
|
119
|
+
|
|
393
120
|
:example:
|
|
394
121
|
>>> # 启动所有适配器
|
|
395
122
|
>>> await adapter.startup()
|
|
@@ -403,20 +130,29 @@ class AdapterManager:
|
|
|
403
130
|
for platform in platforms:
|
|
404
131
|
if platform not in self._adapters:
|
|
405
132
|
raise ValueError(f"平台 {platform} 未注册")
|
|
406
|
-
|
|
133
|
+
|
|
407
134
|
logger.info(f"启动适配器 {platforms}")
|
|
408
135
|
|
|
409
|
-
|
|
410
|
-
|
|
136
|
+
# 提交适配器启动开始事件
|
|
137
|
+
await lifecycle.submit_event(
|
|
138
|
+
"adapter.start",
|
|
139
|
+
msg="开始启动适配器",
|
|
140
|
+
data={
|
|
141
|
+
"platforms": platforms
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
from .router import router
|
|
146
|
+
from ._self_config import get_server_config
|
|
411
147
|
server_config = get_server_config()
|
|
412
148
|
|
|
413
149
|
host = server_config["host"]
|
|
414
150
|
port = server_config["port"]
|
|
415
151
|
ssl_cert = server_config.get("ssl_certfile", None)
|
|
416
152
|
ssl_key = server_config.get("ssl_keyfile", None)
|
|
417
|
-
|
|
153
|
+
|
|
418
154
|
# 启动服务器
|
|
419
|
-
await
|
|
155
|
+
await router.start(
|
|
420
156
|
host=host,
|
|
421
157
|
port=port,
|
|
422
158
|
ssl_certfile=ssl_cert,
|
|
@@ -442,7 +178,7 @@ class AdapterManager:
|
|
|
442
178
|
"""
|
|
443
179
|
{!--< internal-use >!--}
|
|
444
180
|
运行适配器实例
|
|
445
|
-
|
|
181
|
+
|
|
446
182
|
:param adapter: 适配器实例
|
|
447
183
|
:param platform: 平台名称
|
|
448
184
|
"""
|
|
@@ -460,15 +196,49 @@ class AdapterManager:
|
|
|
460
196
|
fixed_delay = 3 * 60 * 60
|
|
461
197
|
backoff_intervals = [60, 10 * 60, 30 * 60, 60 * 60]
|
|
462
198
|
|
|
199
|
+
# 提交适配器状态变化事件(starting)
|
|
200
|
+
await lifecycle.submit_event(
|
|
201
|
+
"adapter.status.change",
|
|
202
|
+
msg=f"适配器 {platform} 状态变化: starting",
|
|
203
|
+
data={
|
|
204
|
+
"platform": platform,
|
|
205
|
+
"status": "starting",
|
|
206
|
+
"retry_count": retry_count
|
|
207
|
+
}
|
|
208
|
+
)
|
|
209
|
+
|
|
463
210
|
while True:
|
|
464
211
|
try:
|
|
465
212
|
await adapter.start()
|
|
466
213
|
self._started_instances.add(adapter)
|
|
214
|
+
|
|
215
|
+
# 提交适配器状态变化事件(started)
|
|
216
|
+
await lifecycle.submit_event(
|
|
217
|
+
"adapter.status.change",
|
|
218
|
+
msg=f"适配器 {platform} 状态变化: started",
|
|
219
|
+
data={
|
|
220
|
+
"platform": platform,
|
|
221
|
+
"status": "started"
|
|
222
|
+
}
|
|
223
|
+
)
|
|
224
|
+
|
|
467
225
|
return
|
|
468
226
|
except Exception as e:
|
|
469
227
|
retry_count += 1
|
|
470
228
|
logger.error(f"平台 {platform} 启动失败(第{retry_count}次重试): {e}")
|
|
471
229
|
|
|
230
|
+
# 提交适配器状态变化事件(start_failed)
|
|
231
|
+
await lifecycle.submit_event(
|
|
232
|
+
"adapter.status.change",
|
|
233
|
+
msg=f"适配器 {platform} 状态变化: start_failed",
|
|
234
|
+
data={
|
|
235
|
+
"platform": platform,
|
|
236
|
+
"status": "start_failed",
|
|
237
|
+
"retry_count": retry_count,
|
|
238
|
+
"error": str(e)
|
|
239
|
+
}
|
|
240
|
+
)
|
|
241
|
+
|
|
472
242
|
try:
|
|
473
243
|
await adapter.shutdown()
|
|
474
244
|
except Exception as stop_err:
|
|
@@ -482,73 +252,300 @@ class AdapterManager:
|
|
|
482
252
|
|
|
483
253
|
logger.info(f"将在 {wait_time // 60} 分钟后再次尝试重启 {platform}")
|
|
484
254
|
await asyncio.sleep(wait_time)
|
|
485
|
-
|
|
486
255
|
async def shutdown(self) -> None:
|
|
487
256
|
"""
|
|
488
257
|
关闭所有适配器
|
|
489
|
-
|
|
490
|
-
:example:
|
|
491
|
-
>>> await adapter.shutdown()
|
|
492
258
|
"""
|
|
259
|
+
# 提交适配器关闭开始事件
|
|
260
|
+
await lifecycle.submit_event(
|
|
261
|
+
"adapter.stop",
|
|
262
|
+
msg="开始关闭适配器",
|
|
263
|
+
data={}
|
|
264
|
+
)
|
|
265
|
+
|
|
493
266
|
for adapter in self._adapters.values():
|
|
494
267
|
await adapter.shutdown()
|
|
495
|
-
|
|
496
|
-
from .router import adapter_server
|
|
497
|
-
await adapter_server.stop()
|
|
498
268
|
|
|
499
|
-
|
|
269
|
+
from .router import router
|
|
270
|
+
await router.stop()
|
|
271
|
+
|
|
272
|
+
# 提交适配器关闭完成事件
|
|
273
|
+
await lifecycle.submit_event(
|
|
274
|
+
"adapter.stopped",
|
|
275
|
+
msg="适配器关闭完成"
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
# ==================== 适配器配置管理 ====================
|
|
279
|
+
|
|
280
|
+
def _config_register(self, platform: str, enabled: bool = False) -> bool:
|
|
500
281
|
"""
|
|
501
|
-
|
|
502
|
-
|
|
282
|
+
注册新平台适配器(仅当平台不存在时注册)
|
|
283
|
+
|
|
503
284
|
:param platform: 平台名称
|
|
504
|
-
:
|
|
505
|
-
|
|
285
|
+
:param enabled: [bool] 是否启用适配器
|
|
286
|
+
:return: [bool] 操作是否成功
|
|
287
|
+
"""
|
|
288
|
+
if self.exists(platform):
|
|
289
|
+
return True
|
|
290
|
+
|
|
291
|
+
# 平台不存在,进行注册
|
|
292
|
+
config.setConfig(f"ErisPulse.adapters.status.{platform}", enabled)
|
|
293
|
+
status = "启用" if enabled else "禁用"
|
|
294
|
+
logger.info(f"平台适配器 {platform} 已注册并{status}")
|
|
295
|
+
return True
|
|
296
|
+
|
|
297
|
+
def exists(self, platform: str) -> bool:
|
|
298
|
+
"""
|
|
299
|
+
检查平台是否存在
|
|
300
|
+
|
|
301
|
+
:param platform: 平台名称
|
|
302
|
+
:return: [bool] 平台是否存在
|
|
303
|
+
"""
|
|
304
|
+
# 检查平台是否在配置中注册
|
|
305
|
+
adapter_statuses = config.getConfig("ErisPulse.adapters.status", {})
|
|
306
|
+
return platform in adapter_statuses
|
|
307
|
+
|
|
308
|
+
def is_enabled(self, platform: str) -> bool:
|
|
309
|
+
"""
|
|
310
|
+
检查平台适配器是否启用
|
|
311
|
+
|
|
312
|
+
:param platform: 平台名称
|
|
313
|
+
:return: [bool] 平台适配器是否启用
|
|
314
|
+
"""
|
|
315
|
+
# 不使用默认值,如果配置不存在则返回 None
|
|
316
|
+
status = config.getConfig(f"ErisPulse.adapters.status.{platform}")
|
|
317
|
+
|
|
318
|
+
# 如果状态不存在,说明是新适配器
|
|
319
|
+
if status is None:
|
|
320
|
+
return False # 新适配器默认不启用,需要在初始化时处理
|
|
321
|
+
|
|
322
|
+
# 处理字符串形式的布尔值
|
|
323
|
+
if isinstance(status, str):
|
|
324
|
+
return status.lower() not in ('false', '0', 'no', 'off')
|
|
325
|
+
|
|
326
|
+
return bool(status)
|
|
327
|
+
|
|
328
|
+
def enable(self, platform: str) -> bool:
|
|
329
|
+
"""
|
|
330
|
+
启用平台适配器
|
|
331
|
+
|
|
332
|
+
:param platform: 平台名称
|
|
333
|
+
:return: [bool] 操作是否成功
|
|
334
|
+
"""
|
|
335
|
+
if not self.exists(platform):
|
|
336
|
+
logger.error(f"平台 {platform} 不存在")
|
|
337
|
+
return False
|
|
338
|
+
|
|
339
|
+
config.setConfig(f"ErisPulse.adapters.status.{platform}", True)
|
|
340
|
+
logger.info(f"平台 {platform} 已启用")
|
|
341
|
+
return True
|
|
342
|
+
|
|
343
|
+
def disable(self, platform: str) -> bool:
|
|
344
|
+
"""
|
|
345
|
+
禁用平台适配器
|
|
346
|
+
|
|
347
|
+
:param platform: 平台名称
|
|
348
|
+
:return: [bool] 操作是否成功
|
|
349
|
+
"""
|
|
350
|
+
if not self.exists(platform):
|
|
351
|
+
logger.error(f"平台 {platform} 不存在")
|
|
352
|
+
return False
|
|
353
|
+
|
|
354
|
+
config.setConfig(f"ErisPulse.adapters.status.{platform}", False)
|
|
355
|
+
logger.info(f"平台 {platform} 已禁用")
|
|
356
|
+
return True
|
|
357
|
+
|
|
358
|
+
def list_adapters(self) -> Dict[str, bool]:
|
|
359
|
+
"""
|
|
360
|
+
列出所有平台适配器状态
|
|
361
|
+
|
|
362
|
+
:return: [Dict[str, bool]] 平台适配器状态字典
|
|
363
|
+
"""
|
|
364
|
+
return config.getConfig("ErisPulse.adapters.status", {})
|
|
365
|
+
|
|
366
|
+
# ==================== 事件处理与消息发送 ====================
|
|
367
|
+
|
|
368
|
+
def on(self, event_type: str = "*", *, raw: bool = False, platform: Optional[str] = None) -> Callable[[Callable], Callable]:
|
|
369
|
+
"""
|
|
370
|
+
OneBot12协议事件监听装饰器
|
|
371
|
+
|
|
372
|
+
:param event_type: OneBot12事件类型
|
|
373
|
+
:param raw: 是否监听原生事件
|
|
374
|
+
:param platform: 指定平台,None表示监听所有平台
|
|
375
|
+
:return: 装饰器函数
|
|
376
|
+
|
|
506
377
|
:example:
|
|
507
|
-
>>>
|
|
378
|
+
>>> # 监听OneBot12标准事件(所有平台)
|
|
379
|
+
>>> @sdk.adapter.on("message")
|
|
380
|
+
>>> async def handle_message(data):
|
|
381
|
+
>>> print(f"收到OneBot12消息: {data}")
|
|
382
|
+
>>>
|
|
383
|
+
>>> # 监听特定平台的OneBot12标准事件
|
|
384
|
+
>>> @sdk.adapter.on("message", platform="onebot11")
|
|
385
|
+
>>> async def handle_onebot11_message(data):
|
|
386
|
+
>>> print(f"收到OneBot11标准消息: {data}")
|
|
387
|
+
>>>
|
|
388
|
+
>>> # 监听平台原生事件
|
|
389
|
+
>>> @sdk.adapter.on("message", raw=True, platform="onebot11")
|
|
390
|
+
>>> async def handle_raw_message(data):
|
|
391
|
+
>>> print(f"收到OneBot11原生事件: {data}")
|
|
392
|
+
>>>
|
|
393
|
+
>>> # 监听所有平台的原生事件
|
|
394
|
+
>>> @sdk.adapter.on("message", raw=True)
|
|
395
|
+
>>> async def handle_all_raw_message(data):
|
|
396
|
+
>>> print(f"收到原生事件: {data}")
|
|
508
397
|
"""
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
return
|
|
513
|
-
return None
|
|
398
|
+
def decorator(func: Callable) -> Callable:
|
|
399
|
+
@functools.wraps(func)
|
|
400
|
+
async def wrapper(*args, **kwargs):
|
|
401
|
+
return await func(*args, **kwargs)
|
|
514
402
|
|
|
515
|
-
|
|
403
|
+
# 创建带元信息的处理器包装器
|
|
404
|
+
handler_wrapper = {
|
|
405
|
+
'func': wrapper,
|
|
406
|
+
'platform': platform
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if raw:
|
|
410
|
+
self._raw_handlers[event_type].append(handler_wrapper)
|
|
411
|
+
else:
|
|
412
|
+
self._onebot_handlers[event_type].append(handler_wrapper)
|
|
413
|
+
return wrapper
|
|
414
|
+
return decorator
|
|
415
|
+
|
|
416
|
+
def middleware(self, func: Callable) -> Callable:
|
|
516
417
|
"""
|
|
517
|
-
|
|
518
|
-
|
|
418
|
+
添加OneBot12中间件处理器
|
|
419
|
+
|
|
420
|
+
:param func: 中间件函数
|
|
421
|
+
:return: 中间件函数
|
|
422
|
+
|
|
423
|
+
:example:
|
|
424
|
+
>>> @sdk.adapter.middleware
|
|
425
|
+
>>> async def onebot_middleware(data):
|
|
426
|
+
>>> print("处理OneBot12数据:", data)
|
|
427
|
+
>>> return data
|
|
428
|
+
"""
|
|
429
|
+
self._onebot_middlewares.append(func)
|
|
430
|
+
return func
|
|
431
|
+
|
|
432
|
+
async def emit(self, data: Any) -> None:
|
|
433
|
+
"""
|
|
434
|
+
提交OneBot12协议事件到指定平台
|
|
435
|
+
|
|
436
|
+
:param data: 符合OneBot12标准的事件数据
|
|
437
|
+
|
|
438
|
+
:example:
|
|
439
|
+
>>> await sdk.adapter.emit({
|
|
440
|
+
>>> "id": "123",
|
|
441
|
+
>>> "time": 1620000000,
|
|
442
|
+
>>> "type": "message",
|
|
443
|
+
>>> "detail_type": "private",
|
|
444
|
+
>>> "message": [{"type": "text", "data": {"text": "Hello"}}],
|
|
445
|
+
>>> "platform": "myplatform",
|
|
446
|
+
>>> "myplatform_raw": {...平台原生事件数据...},
|
|
447
|
+
>>> "myplatform_raw_type": "text_message"
|
|
448
|
+
>>> })
|
|
449
|
+
"""
|
|
450
|
+
platform = data.get("platform", "unknown")
|
|
451
|
+
event_type = data.get("type", "unknown")
|
|
452
|
+
platform_raw = data.get(f"{platform}_raw", {})
|
|
453
|
+
raw_event_type = data.get(f"{platform}_raw_type")
|
|
454
|
+
|
|
455
|
+
# 先执行OneBot12中间件
|
|
456
|
+
processed_data = data
|
|
457
|
+
for middleware in self._onebot_middlewares:
|
|
458
|
+
processed_data = await middleware(processed_data)
|
|
459
|
+
|
|
460
|
+
# 分发到OneBot12事件处理器
|
|
461
|
+
handlers_to_call = []
|
|
462
|
+
|
|
463
|
+
# 处理特定事件类型的处理器
|
|
464
|
+
if event_type in self._onebot_handlers:
|
|
465
|
+
handlers_to_call.extend(self._onebot_handlers[event_type])
|
|
466
|
+
|
|
467
|
+
# 处理通配符处理器
|
|
468
|
+
handlers_to_call.extend(self._onebot_handlers.get("*", []))
|
|
469
|
+
|
|
470
|
+
# 调用符合条件的标准事件处理器
|
|
471
|
+
for handler_wrapper in handlers_to_call:
|
|
472
|
+
handler_platform = handler_wrapper.get('platform')
|
|
473
|
+
# 如果处理器没有指定平台,或者指定的平台与当前事件平台匹配
|
|
474
|
+
if handler_platform is None or handler_platform == platform:
|
|
475
|
+
await handler_wrapper['func'](processed_data)
|
|
476
|
+
|
|
477
|
+
# 只有当存在原生事件数据时才分发原生事件
|
|
478
|
+
if raw_event_type and platform_raw is not None:
|
|
479
|
+
raw_handlers_to_call = []
|
|
480
|
+
|
|
481
|
+
# 处理特定原生事件类型的处理器
|
|
482
|
+
if raw_event_type in self._raw_handlers:
|
|
483
|
+
raw_handlers_to_call.extend(self._raw_handlers[raw_event_type])
|
|
484
|
+
|
|
485
|
+
# 处理原生事件的通配符处理器
|
|
486
|
+
raw_handlers_to_call.extend(self._raw_handlers.get("*", []))
|
|
487
|
+
|
|
488
|
+
# 调用符合条件的原生事件处理器
|
|
489
|
+
for handler_wrapper in raw_handlers_to_call:
|
|
490
|
+
handler_platform = handler_wrapper.get('platform')
|
|
491
|
+
# 如果处理器没有指定平台,或者指定的平台与当前事件平台匹配
|
|
492
|
+
if handler_platform is None or handler_platform == platform:
|
|
493
|
+
await handler_wrapper['func'](platform_raw)
|
|
494
|
+
|
|
495
|
+
# ==================== 工具方法 ====================
|
|
496
|
+
|
|
497
|
+
def get(self, platform: str) -> Optional[BaseAdapter]:
|
|
498
|
+
"""
|
|
499
|
+
获取指定平台的适配器实例
|
|
500
|
+
|
|
519
501
|
:param platform: 平台名称
|
|
520
|
-
:return:
|
|
521
|
-
|
|
522
|
-
:raises AttributeError: 当平台未注册时抛出
|
|
523
|
-
|
|
502
|
+
:return: 适配器实例或None
|
|
503
|
+
|
|
524
504
|
:example:
|
|
525
|
-
>>> adapter = adapter.MyPlatform
|
|
505
|
+
>>> adapter = adapter.get("MyPlatform")
|
|
526
506
|
"""
|
|
527
507
|
platform_lower = platform.lower()
|
|
528
508
|
for registered, instance in self._adapters.items():
|
|
529
509
|
if registered.lower() == platform_lower:
|
|
530
510
|
return instance
|
|
531
|
-
|
|
511
|
+
return None
|
|
532
512
|
|
|
533
513
|
@property
|
|
534
514
|
def platforms(self) -> List[str]:
|
|
535
515
|
"""
|
|
536
516
|
获取所有已注册的平台列表
|
|
537
|
-
|
|
517
|
+
|
|
538
518
|
:return: 平台名称列表
|
|
539
|
-
|
|
519
|
+
|
|
540
520
|
:example:
|
|
541
521
|
>>> print("已注册平台:", adapter.platforms)
|
|
542
522
|
"""
|
|
543
523
|
return list(self._adapters.keys())
|
|
544
524
|
|
|
525
|
+
def __getattr__(self, platform: str) -> BaseAdapter:
|
|
526
|
+
"""
|
|
527
|
+
通过属性访问获取适配器实例
|
|
528
|
+
|
|
529
|
+
:param platform: 平台名称
|
|
530
|
+
:return: 适配器实例
|
|
531
|
+
:raises AttributeError: 当平台不存在或未启用时
|
|
532
|
+
"""
|
|
533
|
+
adapter_instance = self.get(platform)
|
|
534
|
+
if adapter_instance is None:
|
|
535
|
+
raise AttributeError(f"平台 {platform} 不存在或未启用")
|
|
536
|
+
return adapter_instance
|
|
537
|
+
|
|
538
|
+
def __contains__(self, platform: str) -> bool:
|
|
539
|
+
"""
|
|
540
|
+
检查平台是否存在且处于启用状态
|
|
541
|
+
|
|
542
|
+
:param platform: 平台名称
|
|
543
|
+
:return: [bool] 平台是否存在且启用
|
|
544
|
+
"""
|
|
545
|
+
return self.exists(platform) and self.is_enabled(platform)
|
|
545
546
|
|
|
546
|
-
AdapterFather = BaseAdapter
|
|
547
547
|
adapter = AdapterManager()
|
|
548
|
-
SendDSL = SendDSLBase
|
|
549
548
|
|
|
550
549
|
__all__ = [
|
|
551
|
-
"
|
|
552
|
-
"adapter",
|
|
553
|
-
"SendDSL"
|
|
550
|
+
"adapter"
|
|
554
551
|
]
|