ErisPulse 1.2.9__py3-none-any.whl → 2.1.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/__init__.py +19 -0
- ErisPulse/Core/adapter.py +619 -0
- ErisPulse/Core/env.py +614 -0
- ErisPulse/{logger.py → Core/logger.py} +1 -118
- ErisPulse/Core/mods.py +226 -0
- ErisPulse/Core/raiserr.py +152 -0
- ErisPulse/Core/server.py +276 -0
- ErisPulse/Core/shellprint.py +165 -0
- ErisPulse/Core/util.py +126 -0
- ErisPulse/__init__.py +654 -243
- ErisPulse/__main__.py +322 -1187
- {erispulse-1.2.9.dist-info → erispulse-2.1.0.dist-info}/METADATA +16 -41
- erispulse-2.1.0.dist-info/RECORD +16 -0
- {erispulse-1.2.9.dist-info → erispulse-2.1.0.dist-info}/entry_points.txt +1 -0
- {erispulse-1.2.9.dist-info → erispulse-2.1.0.dist-info}/licenses/LICENSE +4 -3
- ErisPulse/adapter.py +0 -465
- ErisPulse/db.py +0 -769
- ErisPulse/mods.py +0 -345
- ErisPulse/raiserr.py +0 -141
- ErisPulse/util.py +0 -144
- erispulse-1.2.9.dist-info/RECORD +0 -13
- {erispulse-1.2.9.dist-info → erispulse-2.1.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from .adapter import AdapterFather, SendDSL, adapter
|
|
2
|
+
from .env import env
|
|
3
|
+
from .logger import logger
|
|
4
|
+
from .mods import mods
|
|
5
|
+
from .raiserr import raiserr
|
|
6
|
+
from .util import util
|
|
7
|
+
from .server import adapter_server
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
'AdapterFather',
|
|
11
|
+
'SendDSL',
|
|
12
|
+
'adapter',
|
|
13
|
+
'env',
|
|
14
|
+
'logger',
|
|
15
|
+
'mods',
|
|
16
|
+
'raiserr',
|
|
17
|
+
'util',
|
|
18
|
+
'adapter_server'
|
|
19
|
+
]
|
|
@@ -0,0 +1,619 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ErisPulse 适配器系统
|
|
3
|
+
|
|
4
|
+
提供平台适配器基类、消息发送DSL和适配器管理功能。支持多平台消息处理、事件驱动和生命周期管理。
|
|
5
|
+
|
|
6
|
+
{!--< tips >!--}
|
|
7
|
+
1. 适配器必须继承BaseAdapter并实现必要方法
|
|
8
|
+
2. 使用SendDSL实现链式调用风格的消息发送接口
|
|
9
|
+
3. 适配器管理器支持多平台适配器的注册和生命周期管理
|
|
10
|
+
4. 支持OneBot12协议的事件处理
|
|
11
|
+
{!--< /tips >!--}
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import functools
|
|
15
|
+
import asyncio
|
|
16
|
+
import uuid
|
|
17
|
+
import time
|
|
18
|
+
from typing import (
|
|
19
|
+
Callable, Any, Dict, List, Type, Optional, Set,
|
|
20
|
+
Union, Awaitable, TypeVar, Generic, Tuple, Coroutine, FrozenSet
|
|
21
|
+
)
|
|
22
|
+
from collections import defaultdict
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class SendDSLBase:
|
|
26
|
+
"""
|
|
27
|
+
消息发送DSL基类
|
|
28
|
+
|
|
29
|
+
用于实现 Send.To(...).Func(...) 风格的链式调用接口
|
|
30
|
+
|
|
31
|
+
{!--< tips >!--}
|
|
32
|
+
1. 子类应实现具体的消息发送方法(如Text, Image等)
|
|
33
|
+
2. 通过__getattr__实现动态方法调用
|
|
34
|
+
{!--< /tips >!--}
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(self, adapter: 'BaseAdapter', target_type: Optional[str] = None, target_id: Optional[str] = None):
|
|
38
|
+
"""
|
|
39
|
+
初始化DSL发送器
|
|
40
|
+
|
|
41
|
+
:param adapter: 所属适配器实例
|
|
42
|
+
:param target_type: 目标类型(可选)
|
|
43
|
+
:param target_id: 目标ID(可选)
|
|
44
|
+
"""
|
|
45
|
+
self._adapter = adapter
|
|
46
|
+
self._target_type = target_type
|
|
47
|
+
self._target_id = target_id
|
|
48
|
+
self._target_to = target_id
|
|
49
|
+
|
|
50
|
+
def To(self, target_type: str = None, target_id: str = 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)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class BaseAdapter:
|
|
70
|
+
"""
|
|
71
|
+
适配器基类
|
|
72
|
+
|
|
73
|
+
提供与外部平台交互的标准接口,子类必须实现必要方法
|
|
74
|
+
|
|
75
|
+
{!--< tips >!--}
|
|
76
|
+
1. 必须实现call_api, start和shutdown方法
|
|
77
|
+
2. 可以自定义Send类实现平台特定的消息发送逻辑
|
|
78
|
+
3. 通过on装饰器注册事件处理器
|
|
79
|
+
4. 支持OneBot12协议的事件处理
|
|
80
|
+
{!--< /tips >!--}
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
class Send(SendDSLBase):
|
|
84
|
+
"""
|
|
85
|
+
消息发送DSL实现
|
|
86
|
+
|
|
87
|
+
{!--< tips >!--}
|
|
88
|
+
1. 子类可以重写Text方法提供平台特定实现
|
|
89
|
+
2. 可以添加新的消息类型(如Image, Voice等)
|
|
90
|
+
{!--< /tips >!--}
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
def Text(self, text: str) -> Awaitable[Any]:
|
|
94
|
+
"""
|
|
95
|
+
基础文本消息发送方法
|
|
96
|
+
|
|
97
|
+
:param text: 文本内容
|
|
98
|
+
:return: 异步任务
|
|
99
|
+
|
|
100
|
+
:example:
|
|
101
|
+
>>> await adapter.Send.To("123").Text("Hello")
|
|
102
|
+
"""
|
|
103
|
+
return asyncio.create_task(
|
|
104
|
+
self._adapter.call_api(
|
|
105
|
+
endpoint="/send",
|
|
106
|
+
content=text,
|
|
107
|
+
recvId=self._target_id,
|
|
108
|
+
recvType=self._target_type
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def __init__(self):
|
|
113
|
+
"""
|
|
114
|
+
初始化适配器
|
|
115
|
+
"""
|
|
116
|
+
self._handlers = defaultdict(list) # 原生事件处理器
|
|
117
|
+
self._onebot_handlers = defaultdict(list) # OneBot12事件处理器
|
|
118
|
+
self._middlewares = []
|
|
119
|
+
self.Send = self.__class__.Send(self)
|
|
120
|
+
|
|
121
|
+
def on(self, event_type: str = "*", *, onebot12: bool = False) -> Callable[[Callable], Callable]:
|
|
122
|
+
"""
|
|
123
|
+
适配器事件监听装饰器
|
|
124
|
+
|
|
125
|
+
:param event_type: 事件类型
|
|
126
|
+
:param onebot12: 是否监听OneBot12协议事件
|
|
127
|
+
:return: 装饰器函数
|
|
128
|
+
|
|
129
|
+
:example:
|
|
130
|
+
>>> @adapter.on("message")
|
|
131
|
+
>>> async def handle_message(data):
|
|
132
|
+
>>> print(f"收到消息: {data}")
|
|
133
|
+
"""
|
|
134
|
+
def decorator(func: Callable) -> Callable:
|
|
135
|
+
@functools.wraps(func)
|
|
136
|
+
async def wrapper(*args, **kwargs):
|
|
137
|
+
return await func(*args, **kwargs)
|
|
138
|
+
|
|
139
|
+
if onebot12:
|
|
140
|
+
self._onebot_handlers[event_type].append(wrapper)
|
|
141
|
+
else:
|
|
142
|
+
self._handlers[event_type].append(wrapper)
|
|
143
|
+
return wrapper
|
|
144
|
+
return decorator
|
|
145
|
+
|
|
146
|
+
def middleware(self, func: Callable) -> Callable:
|
|
147
|
+
"""
|
|
148
|
+
添加中间件处理器
|
|
149
|
+
|
|
150
|
+
:param func: 中间件函数
|
|
151
|
+
:return: 中间件函数
|
|
152
|
+
|
|
153
|
+
:example:
|
|
154
|
+
>>> @adapter.middleware
|
|
155
|
+
>>> async def log_middleware(data):
|
|
156
|
+
>>> print(f"处理数据: {data}")
|
|
157
|
+
>>> return data
|
|
158
|
+
"""
|
|
159
|
+
self._middlewares.append(func)
|
|
160
|
+
return func
|
|
161
|
+
|
|
162
|
+
async def call_api(self, endpoint: str, **params: Any) -> Any:
|
|
163
|
+
"""
|
|
164
|
+
调用平台API的抽象方法
|
|
165
|
+
|
|
166
|
+
:param endpoint: API端点
|
|
167
|
+
:param params: API参数
|
|
168
|
+
:return: API调用结果
|
|
169
|
+
|
|
170
|
+
:raises NotImplementedError: 必须由子类实现
|
|
171
|
+
"""
|
|
172
|
+
raise NotImplementedError("适配器必须实现call_api方法")
|
|
173
|
+
|
|
174
|
+
async def start(self) -> None:
|
|
175
|
+
"""
|
|
176
|
+
启动适配器的抽象方法
|
|
177
|
+
|
|
178
|
+
:raises NotImplementedError: 必须由子类实现
|
|
179
|
+
"""
|
|
180
|
+
raise NotImplementedError("适配器必须实现start方法")
|
|
181
|
+
|
|
182
|
+
async def shutdown(self) -> None:
|
|
183
|
+
"""
|
|
184
|
+
关闭适配器的抽象方法
|
|
185
|
+
|
|
186
|
+
:raises NotImplementedError: 必须由子类实现
|
|
187
|
+
"""
|
|
188
|
+
raise NotImplementedError("适配器必须实现shutdown方法")
|
|
189
|
+
|
|
190
|
+
def add_handler(self, *args: Any) -> None:
|
|
191
|
+
"""
|
|
192
|
+
添加事件处理器
|
|
193
|
+
|
|
194
|
+
:param args: 参数列表
|
|
195
|
+
- 1个参数: 处理器函数(监听所有事件)
|
|
196
|
+
- 2个参数: 事件类型和处理器函数
|
|
197
|
+
|
|
198
|
+
:raises TypeError: 当参数数量无效时抛出
|
|
199
|
+
|
|
200
|
+
:example:
|
|
201
|
+
>>> # 监听所有事件
|
|
202
|
+
>>> adapter.add_handler(handle_all_events)
|
|
203
|
+
>>> # 监听特定事件
|
|
204
|
+
>>> adapter.add_handler("message", handle_message)
|
|
205
|
+
"""
|
|
206
|
+
if len(args) == 1:
|
|
207
|
+
event_type = "*"
|
|
208
|
+
handler = args[0]
|
|
209
|
+
elif len(args) == 2:
|
|
210
|
+
event_type, handler = args
|
|
211
|
+
else:
|
|
212
|
+
raise TypeError("add_handler() 接受 1 个(监听所有事件)或 2 个参数(指定事件类型)")
|
|
213
|
+
|
|
214
|
+
@functools.wraps(handler)
|
|
215
|
+
async def wrapper(*handler_args, **handler_kwargs):
|
|
216
|
+
return await handler(*handler_args, **handler_kwargs)
|
|
217
|
+
|
|
218
|
+
self._handlers[event_type].append(wrapper)
|
|
219
|
+
|
|
220
|
+
async def emit(self, event_type: str, data: Any) -> None:
|
|
221
|
+
"""
|
|
222
|
+
触发原生协议事件
|
|
223
|
+
|
|
224
|
+
:param event_type: 事件类型
|
|
225
|
+
:param data: 事件数据
|
|
226
|
+
|
|
227
|
+
:example:
|
|
228
|
+
>>> await adapter.emit("message", {"text": "Hello"})
|
|
229
|
+
"""
|
|
230
|
+
# 先执行中间件
|
|
231
|
+
for middleware in self._middlewares:
|
|
232
|
+
data = await middleware(data)
|
|
233
|
+
|
|
234
|
+
# 触发具体事件类型的处理器
|
|
235
|
+
if event_type in self._handlers:
|
|
236
|
+
for handler in self._handlers[event_type]:
|
|
237
|
+
await handler(data)
|
|
238
|
+
|
|
239
|
+
# 触发通配符 "*" 的处理器
|
|
240
|
+
for handler in self._handlers.get("*", []):
|
|
241
|
+
await handler(data)
|
|
242
|
+
|
|
243
|
+
async def emit_onebot12(self, event_type: str, onebot_data: Dict) -> None:
|
|
244
|
+
"""
|
|
245
|
+
提交OneBot12协议事件
|
|
246
|
+
|
|
247
|
+
:param event_type: OneBot12事件类型
|
|
248
|
+
:param onebot_data: 符合OneBot12标准的事件数据
|
|
249
|
+
|
|
250
|
+
:example:
|
|
251
|
+
>>> await adapter.emit_onebot12("message", {
|
|
252
|
+
>>> "id": "123",
|
|
253
|
+
>>> "time": 1620000000,
|
|
254
|
+
>>> "type": "message",
|
|
255
|
+
>>> "detail_type": "private",
|
|
256
|
+
>>> "message": [{"type": "text", "data": {"text": "Hello"}}]
|
|
257
|
+
>>> })
|
|
258
|
+
"""
|
|
259
|
+
# 先执行中间件
|
|
260
|
+
for middleware in self._middlewares:
|
|
261
|
+
onebot_data = await middleware(onebot_data)
|
|
262
|
+
|
|
263
|
+
# 触发OneBot12事件处理器
|
|
264
|
+
if event_type in self._onebot_handlers:
|
|
265
|
+
for handler in self._onebot_handlers[event_type]:
|
|
266
|
+
await handler(onebot_data)
|
|
267
|
+
|
|
268
|
+
# 触发通配符 "*" 的处理器
|
|
269
|
+
for handler in self._onebot_handlers.get("*", []):
|
|
270
|
+
await handler(onebot_data)
|
|
271
|
+
|
|
272
|
+
async def send(self, target_type: str, target_id: str, message: Any, **kwargs: Any) -> Any:
|
|
273
|
+
"""
|
|
274
|
+
发送消息的便捷方法
|
|
275
|
+
|
|
276
|
+
:param target_type: 目标类型
|
|
277
|
+
:param target_id: 目标ID
|
|
278
|
+
:param message: 消息内容
|
|
279
|
+
:param kwargs: 其他参数
|
|
280
|
+
- method: 发送方法名(默认为"Text")
|
|
281
|
+
:return: 发送结果
|
|
282
|
+
|
|
283
|
+
:raises AttributeError: 当发送方法不存在时抛出
|
|
284
|
+
|
|
285
|
+
:example:
|
|
286
|
+
>>> await adapter.send("user", "123", "Hello")
|
|
287
|
+
>>> await adapter.send("group", "456", "Hello", method="Markdown")
|
|
288
|
+
"""
|
|
289
|
+
method_name = kwargs.pop("method", "Text")
|
|
290
|
+
method = getattr(self.Send.To(target_type, target_id), method_name, None)
|
|
291
|
+
if not method:
|
|
292
|
+
raise AttributeError(f"未找到 {method_name} 方法,请确保已在 Send 类中定义")
|
|
293
|
+
return await method(text=message, **kwargs)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class AdapterManager:
|
|
297
|
+
"""
|
|
298
|
+
适配器管理器
|
|
299
|
+
|
|
300
|
+
管理多个平台适配器的注册、启动和关闭
|
|
301
|
+
|
|
302
|
+
{!--< tips >!--}
|
|
303
|
+
1. 通过register方法注册适配器
|
|
304
|
+
2. 通过startup方法启动适配器
|
|
305
|
+
3. 通过shutdown方法关闭所有适配器
|
|
306
|
+
4. 通过on装饰器注册OneBot12协议事件处理器
|
|
307
|
+
{!--< /tips >!--}
|
|
308
|
+
"""
|
|
309
|
+
|
|
310
|
+
def __init__(self):
|
|
311
|
+
self._adapters: Dict[str, BaseAdapter] = {}
|
|
312
|
+
self._adapter_instances: Dict[Type[BaseAdapter], BaseAdapter] = {}
|
|
313
|
+
self._platform_to_instance: Dict[str, BaseAdapter] = {}
|
|
314
|
+
self._started_instances: Set[BaseAdapter] = set()
|
|
315
|
+
|
|
316
|
+
# OneBot12事件处理器
|
|
317
|
+
self._onebot_handlers = defaultdict(list)
|
|
318
|
+
self._onebot_middlewares = []
|
|
319
|
+
|
|
320
|
+
@property
|
|
321
|
+
def Adapter(self) -> Type[BaseAdapter]:
|
|
322
|
+
"""
|
|
323
|
+
获取BaseAdapter类,用于访问原始事件监听
|
|
324
|
+
|
|
325
|
+
:return: BaseAdapter类
|
|
326
|
+
|
|
327
|
+
:example:
|
|
328
|
+
>>> @sdk.adapter.Adapter.on("raw_event")
|
|
329
|
+
>>> async def handle_raw(data):
|
|
330
|
+
>>> print("收到原始事件:", data)
|
|
331
|
+
"""
|
|
332
|
+
return BaseAdapter
|
|
333
|
+
|
|
334
|
+
def on(self, event_type: str = "*") -> Callable[[Callable], Callable]:
|
|
335
|
+
"""
|
|
336
|
+
OneBot12协议事件监听装饰器
|
|
337
|
+
|
|
338
|
+
:param event_type: OneBot12事件类型
|
|
339
|
+
:return: 装饰器函数
|
|
340
|
+
|
|
341
|
+
:example:
|
|
342
|
+
>>> @sdk.adapter.on("message")
|
|
343
|
+
>>> async def handle_message(data):
|
|
344
|
+
>>> print(f"收到OneBot12消息: {data}")
|
|
345
|
+
"""
|
|
346
|
+
def decorator(func: Callable) -> Callable:
|
|
347
|
+
@functools.wraps(func)
|
|
348
|
+
async def wrapper(*args, **kwargs):
|
|
349
|
+
return await func(*args, **kwargs)
|
|
350
|
+
|
|
351
|
+
self._onebot_handlers[event_type].append(wrapper)
|
|
352
|
+
return wrapper
|
|
353
|
+
return decorator
|
|
354
|
+
|
|
355
|
+
def middleware(self, func: Callable) -> Callable:
|
|
356
|
+
"""
|
|
357
|
+
添加OneBot12中间件处理器
|
|
358
|
+
|
|
359
|
+
:param func: 中间件函数
|
|
360
|
+
:return: 中间件函数
|
|
361
|
+
|
|
362
|
+
:example:
|
|
363
|
+
>>> @sdk.adapter.middleware
|
|
364
|
+
>>> async def onebot_middleware(data):
|
|
365
|
+
>>> print("处理OneBot12数据:", data)
|
|
366
|
+
>>> return data
|
|
367
|
+
"""
|
|
368
|
+
self._onebot_middlewares.append(func)
|
|
369
|
+
return func
|
|
370
|
+
|
|
371
|
+
async def emit(self, data: Any) -> None:
|
|
372
|
+
"""
|
|
373
|
+
提交OneBot12协议事件到指定平台
|
|
374
|
+
|
|
375
|
+
:param platform: 平台名称
|
|
376
|
+
:param event_type: OneBot12事件类型
|
|
377
|
+
:param data: 符合OneBot12标准的事件数据
|
|
378
|
+
|
|
379
|
+
:raises ValueError: 当平台未注册时抛出
|
|
380
|
+
|
|
381
|
+
:example:
|
|
382
|
+
>>> await sdk.adapter.emit("MyPlatform", "message", {
|
|
383
|
+
>>> "id": "123",
|
|
384
|
+
>>> "time": 1620000000,
|
|
385
|
+
>>> "type": "message",
|
|
386
|
+
>>> "detail_type": "private",
|
|
387
|
+
>>> "message": [{"type": "text", "data": {"text": "Hello"}}]
|
|
388
|
+
>>> })
|
|
389
|
+
"""
|
|
390
|
+
platform = data.get("platform", "unknown")
|
|
391
|
+
event_type = data.get("type", "unknown")
|
|
392
|
+
|
|
393
|
+
if platform not in self._adapters:
|
|
394
|
+
raise ValueError(f"平台 {platform} 未注册")
|
|
395
|
+
|
|
396
|
+
# 先执行OneBot12中间件
|
|
397
|
+
processed_data = data
|
|
398
|
+
for middleware in self._onebot_middlewares:
|
|
399
|
+
processed_data = await middleware(processed_data)
|
|
400
|
+
|
|
401
|
+
# 分发到OneBot12事件处理器
|
|
402
|
+
if event_type in self._onebot_handlers:
|
|
403
|
+
for handler in self._onebot_handlers[event_type]:
|
|
404
|
+
await handler(processed_data)
|
|
405
|
+
for handler in self._onebot_handlers.get("*", []):
|
|
406
|
+
await handler(processed_data)
|
|
407
|
+
|
|
408
|
+
def register(self, platform: str, adapter_class: Type[BaseAdapter]) -> bool:
|
|
409
|
+
"""
|
|
410
|
+
注册新的适配器类
|
|
411
|
+
|
|
412
|
+
:param platform: 平台名称
|
|
413
|
+
:param adapter_class: 适配器类
|
|
414
|
+
:return: 注册是否成功
|
|
415
|
+
|
|
416
|
+
:raises TypeError: 当适配器类无效时抛出
|
|
417
|
+
|
|
418
|
+
:example:
|
|
419
|
+
>>> adapter.register("MyPlatform", MyPlatformAdapter)
|
|
420
|
+
"""
|
|
421
|
+
if not issubclass(adapter_class, BaseAdapter):
|
|
422
|
+
raise TypeError("适配器必须继承自BaseAdapter")
|
|
423
|
+
from .. import sdk
|
|
424
|
+
|
|
425
|
+
# 如果该类已经创建过实例,复用
|
|
426
|
+
if adapter_class in self._adapter_instances:
|
|
427
|
+
instance = self._adapter_instances[adapter_class]
|
|
428
|
+
else:
|
|
429
|
+
instance = adapter_class(sdk)
|
|
430
|
+
self._adapter_instances[adapter_class] = instance
|
|
431
|
+
|
|
432
|
+
# 注册平台名,并统一映射到该实例
|
|
433
|
+
self._adapters[platform] = instance
|
|
434
|
+
self._platform_to_instance[platform] = instance
|
|
435
|
+
|
|
436
|
+
if len(platform) <= 10:
|
|
437
|
+
from itertools import product
|
|
438
|
+
combinations = [''.join(c) for c in product(*[(ch.lower(), ch.upper()) for ch in platform])]
|
|
439
|
+
for name in set(combinations):
|
|
440
|
+
setattr(self, name, instance)
|
|
441
|
+
else:
|
|
442
|
+
self.logger.warning(f"平台名 {platform} 过长,如果您是开发者,请考虑使用更短的名称")
|
|
443
|
+
setattr(self, platform.lower(), instance)
|
|
444
|
+
setattr(self, platform.upper(), instance)
|
|
445
|
+
setattr(self, platform.capitalize(), instance)
|
|
446
|
+
|
|
447
|
+
return True
|
|
448
|
+
|
|
449
|
+
async def startup(self, platforms: List[str] = None) -> None:
|
|
450
|
+
"""
|
|
451
|
+
启动指定的适配器
|
|
452
|
+
|
|
453
|
+
:param platforms: 要启动的平台列表,None表示所有平台
|
|
454
|
+
|
|
455
|
+
:raises ValueError: 当平台未注册时抛出
|
|
456
|
+
|
|
457
|
+
:example:
|
|
458
|
+
>>> # 启动所有适配器
|
|
459
|
+
>>> await adapter.startup()
|
|
460
|
+
>>> # 启动指定适配器
|
|
461
|
+
>>> await adapter.startup(["Platform1", "Platform2"])
|
|
462
|
+
"""
|
|
463
|
+
if platforms is None:
|
|
464
|
+
platforms = list(self._adapters.keys())
|
|
465
|
+
|
|
466
|
+
from .env import env
|
|
467
|
+
from .logger import logger
|
|
468
|
+
from .server import adapter_server
|
|
469
|
+
|
|
470
|
+
server_config = env.getConfig("Server")
|
|
471
|
+
|
|
472
|
+
if server_config is None:
|
|
473
|
+
server_config = {
|
|
474
|
+
"host": "0.0.0.0",
|
|
475
|
+
"port": 8000,
|
|
476
|
+
"ssl_certfile": None,
|
|
477
|
+
"ssl_keyfile": None
|
|
478
|
+
}
|
|
479
|
+
env.setConfig("Server", server_config)
|
|
480
|
+
logger.info("已创建服务器配置")
|
|
481
|
+
|
|
482
|
+
host = server_config["host"]
|
|
483
|
+
port = server_config["port"]
|
|
484
|
+
ssl_cert = server_config.get("ssl_certfile", None)
|
|
485
|
+
ssl_key = server_config.get("ssl_keyfile", None)
|
|
486
|
+
|
|
487
|
+
# 启动服务器
|
|
488
|
+
await adapter_server.start(
|
|
489
|
+
host=host,
|
|
490
|
+
port=port,
|
|
491
|
+
ssl_certfile=ssl_cert,
|
|
492
|
+
ssl_keyfile=ssl_key
|
|
493
|
+
)
|
|
494
|
+
# 已经被调度过的 adapter 实例集合(防止重复调度)
|
|
495
|
+
scheduled_adapters = set()
|
|
496
|
+
|
|
497
|
+
for platform in platforms:
|
|
498
|
+
if platform not in self._adapters:
|
|
499
|
+
raise ValueError(f"平台 {platform} 未注册")
|
|
500
|
+
adapter = self._adapters[platform]
|
|
501
|
+
|
|
502
|
+
# 如果该实例已经被启动或已调度,跳过
|
|
503
|
+
if adapter in self._started_instances or adapter in scheduled_adapters:
|
|
504
|
+
continue
|
|
505
|
+
|
|
506
|
+
# 加入调度队列
|
|
507
|
+
scheduled_adapters.add(adapter)
|
|
508
|
+
asyncio.create_task(self._run_adapter(adapter, platform))
|
|
509
|
+
|
|
510
|
+
async def _run_adapter(self, adapter: BaseAdapter, platform: str) -> None:
|
|
511
|
+
"""
|
|
512
|
+
{!--< internal-use >!--}
|
|
513
|
+
运行适配器实例
|
|
514
|
+
|
|
515
|
+
:param adapter: 适配器实例
|
|
516
|
+
:param platform: 平台名称
|
|
517
|
+
"""
|
|
518
|
+
from .. import sdk
|
|
519
|
+
|
|
520
|
+
# 加锁防止并发启动
|
|
521
|
+
if not getattr(adapter, "_starting_lock", None):
|
|
522
|
+
adapter._starting_lock = asyncio.Lock()
|
|
523
|
+
|
|
524
|
+
async with adapter._starting_lock:
|
|
525
|
+
# 再次确认是否已经被启动
|
|
526
|
+
if adapter in self._started_instances:
|
|
527
|
+
sdk.logger.info(f"适配器 {platform}(实例ID: {id(adapter)})已被其他协程启动,跳过")
|
|
528
|
+
return
|
|
529
|
+
|
|
530
|
+
retry_count = 0
|
|
531
|
+
fixed_delay = 3 * 60 * 60
|
|
532
|
+
backoff_intervals = [60, 10 * 60, 30 * 60, 60 * 60]
|
|
533
|
+
|
|
534
|
+
while True:
|
|
535
|
+
try:
|
|
536
|
+
await adapter.start()
|
|
537
|
+
self._started_instances.add(adapter)
|
|
538
|
+
return
|
|
539
|
+
except Exception as e:
|
|
540
|
+
retry_count += 1
|
|
541
|
+
sdk.logger.error(f"平台 {platform} 启动失败(第{retry_count}次重试): {e}")
|
|
542
|
+
|
|
543
|
+
try:
|
|
544
|
+
await adapter.shutdown()
|
|
545
|
+
except Exception as stop_err:
|
|
546
|
+
sdk.logger.warning(f"停止适配器失败: {stop_err}")
|
|
547
|
+
|
|
548
|
+
# 计算等待时间
|
|
549
|
+
if retry_count <= len(backoff_intervals):
|
|
550
|
+
wait_time = backoff_intervals[retry_count - 1]
|
|
551
|
+
else:
|
|
552
|
+
wait_time = fixed_delay
|
|
553
|
+
|
|
554
|
+
sdk.logger.info(f"将在 {wait_time // 60} 分钟后再次尝试重启 {platform}")
|
|
555
|
+
await asyncio.sleep(wait_time)
|
|
556
|
+
|
|
557
|
+
async def shutdown(self) -> None:
|
|
558
|
+
"""
|
|
559
|
+
关闭所有适配器
|
|
560
|
+
|
|
561
|
+
:example:
|
|
562
|
+
>>> await adapter.shutdown()
|
|
563
|
+
"""
|
|
564
|
+
for adapter in self._adapters.values():
|
|
565
|
+
await adapter.shutdown()
|
|
566
|
+
|
|
567
|
+
from .server import adapter_server
|
|
568
|
+
adapter_server.stop()
|
|
569
|
+
|
|
570
|
+
def get(self, platform: str) -> Optional[BaseAdapter]:
|
|
571
|
+
"""
|
|
572
|
+
获取指定平台的适配器实例
|
|
573
|
+
|
|
574
|
+
:param platform: 平台名称
|
|
575
|
+
:return: 适配器实例或None
|
|
576
|
+
|
|
577
|
+
:example:
|
|
578
|
+
>>> adapter = adapter.get("MyPlatform")
|
|
579
|
+
"""
|
|
580
|
+
platform_lower = platform.lower()
|
|
581
|
+
for registered, instance in self._adapters.items():
|
|
582
|
+
if registered.lower() == platform_lower:
|
|
583
|
+
return instance
|
|
584
|
+
return None
|
|
585
|
+
|
|
586
|
+
def __getattr__(self, platform: str) -> BaseAdapter:
|
|
587
|
+
"""
|
|
588
|
+
通过属性访问获取适配器实例
|
|
589
|
+
|
|
590
|
+
:param platform: 平台名称
|
|
591
|
+
:return: 适配器实例
|
|
592
|
+
|
|
593
|
+
:raises AttributeError: 当平台未注册时抛出
|
|
594
|
+
|
|
595
|
+
:example:
|
|
596
|
+
>>> adapter = adapter.MyPlatform
|
|
597
|
+
"""
|
|
598
|
+
platform_lower = platform.lower()
|
|
599
|
+
for registered, instance in self._adapters.items():
|
|
600
|
+
if registered.lower() == platform_lower:
|
|
601
|
+
return instance
|
|
602
|
+
raise AttributeError(f"平台 {platform} 的适配器未注册")
|
|
603
|
+
|
|
604
|
+
@property
|
|
605
|
+
def platforms(self) -> List[str]:
|
|
606
|
+
"""
|
|
607
|
+
获取所有已注册的平台列表
|
|
608
|
+
|
|
609
|
+
:return: 平台名称列表
|
|
610
|
+
|
|
611
|
+
:example:
|
|
612
|
+
>>> print("已注册平台:", adapter.platforms)
|
|
613
|
+
"""
|
|
614
|
+
return list(self._adapters.keys())
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
AdapterFather = BaseAdapter
|
|
618
|
+
adapter = AdapterManager()
|
|
619
|
+
SendDSL = SendDSLBase
|