ErisPulse 1.1.13__py3-none-any.whl → 1.1.14__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/adapter.py CHANGED
@@ -1,3 +1,354 @@
1
+ """
2
+ # 适配器系统
3
+
4
+ 提供平台适配器基类、消息发送DSL和适配器管理功能。支持多平台消息处理、事件驱动和生命周期管理。
5
+
6
+ ## 核心功能
7
+ 1. 适配器基类定义
8
+ 2. 链式消息发送DSL
9
+ 3. 适配器注册和管理
10
+ 4. 事件处理系统
11
+ 5. 中间件支持
12
+
13
+ ## API 文档
14
+
15
+ ### 适配器基类 (BaseAdapter)
16
+ 适配器基类提供了与外部平台交互的标准接口。
17
+
18
+ #### call_api(endpoint: str, **params) -> Any
19
+ 调用平台API的抽象方法。
20
+ - 参数:
21
+ - endpoint: API端点
22
+ - **params: API参数
23
+ - 返回:
24
+ - Any: API调用结果
25
+ - 说明:
26
+ - 必须由子类实现
27
+ - 处理与平台的实际通信
28
+ - 示例:
29
+ ```python
30
+ class MyPlatformAdapter(BaseAdapter):
31
+ async def call_api(self, endpoint: str, **params):
32
+ if endpoint == "/send":
33
+ return await self._send_message(params)
34
+ elif endpoint == "/upload":
35
+ return await self._upload_file(params)
36
+ raise NotImplementedError(f"未实现的端点: {endpoint}")
37
+ ```
38
+
39
+ #### start() -> None
40
+ 启动适配器的抽象方法。
41
+ - 参数: 无
42
+ - 返回:
43
+ - None
44
+ - 说明:
45
+ - 必须由子类实现
46
+ - 处理适配器的初始化和启动逻辑
47
+ - 示例:
48
+ ```python
49
+ class MyPlatformAdapter(BaseAdapter):
50
+ async def start(self):
51
+ self.client = await self._create_client()
52
+ self.ws = await self.client.create_websocket()
53
+ self._start_heartbeat()
54
+ ```
55
+
56
+ #### shutdown() -> None
57
+ 关闭适配器的抽象方法。
58
+ - 参数: 无
59
+ - 返回:
60
+ - None
61
+ - 说明:
62
+ - 必须由子类实现
63
+ - 处理资源清理和关闭逻辑
64
+ - 示例:
65
+ ```python
66
+ class MyPlatformAdapter(BaseAdapter):
67
+ async def shutdown(self):
68
+ if self.ws:
69
+ await self.ws.close()
70
+ if self.client:
71
+ await self.client.close()
72
+ ```
73
+
74
+ #### on(event_type: str = "*") -> Callable
75
+ 事件监听装饰器。
76
+ - 参数:
77
+ - event_type: 事件类型,默认"*"表示所有事件
78
+ - 返回:
79
+ - Callable: 装饰器函数
80
+ - 示例:
81
+ ```python
82
+ adapter = MyPlatformAdapter()
83
+
84
+ @adapter.on("message")
85
+ async def handle_message(data):
86
+ print(f"收到消息: {data}")
87
+
88
+ @adapter.on("error")
89
+ async def handle_error(error):
90
+ print(f"发生错误: {error}")
91
+
92
+ # 处理所有事件
93
+ @adapter.on()
94
+ async def handle_all(event):
95
+ print(f"事件: {event}")
96
+ ```
97
+
98
+ #### emit(event_type: str, data: Any) -> None
99
+ 触发事件。
100
+ - 参数:
101
+ - event_type: 事件类型
102
+ - data: 事件数据
103
+ - 返回:
104
+ - None
105
+ - 示例:
106
+ ```python
107
+ class MyPlatformAdapter(BaseAdapter):
108
+ async def _handle_websocket_message(self, message):
109
+ # 处理消息并触发相应事件
110
+ if message.type == "chat":
111
+ await self.emit("message", {
112
+ "type": "chat",
113
+ "content": message.content,
114
+ "sender": message.sender
115
+ })
116
+ ```
117
+
118
+ #### middleware(func: Callable) -> Callable
119
+ 添加中间件处理器。
120
+ - 参数:
121
+ - func: 中间件函数
122
+ - 返回:
123
+ - Callable: 中间件函数
124
+ - 示例:
125
+ ```python
126
+ adapter = MyPlatformAdapter()
127
+
128
+ @adapter.middleware
129
+ async def log_middleware(data):
130
+ print(f"处理数据: {data}")
131
+ return data
132
+
133
+ @adapter.middleware
134
+ async def filter_middleware(data):
135
+ if "spam" in data.get("content", ""):
136
+ return None
137
+ return data
138
+ ```
139
+
140
+ ### 消息发送DSL (SendDSL)
141
+ 提供链式调用风格的消息发送接口。
142
+
143
+ #### To(target_type: str = None, target_id: str = None) -> 'SendDSL'
144
+ 设置消息目标。
145
+ - 参数:
146
+ - target_type: 目标类型(可选)
147
+ - target_id: 目标ID
148
+ - 返回:
149
+ - SendDSL: 发送器实例
150
+ - 示例:
151
+ ```python
152
+ # 发送到用户
153
+ sdk.adapter.Platform.Send.To("user", "123").Text("Hello")
154
+
155
+ # 发送到群组
156
+ sdk.adapter.Platform.Send.To("group", "456").Text("Hello Group")
157
+
158
+ # 简化形式(只有ID)
159
+ sdk.adapter.Platform.Send.To("123").Text("Hello")
160
+ ```
161
+
162
+ #### Text(text: str) -> Task
163
+ 发送文本消息。
164
+ - 参数:
165
+ - text: 文本内容
166
+ - 返回:
167
+ - Task: 异步任务
168
+ - 示例:
169
+ ```python
170
+ # 发送简单文本
171
+ await sdk.adapter.Platform.Send.To("user", "123").Text("Hello")
172
+
173
+ # 发送格式化文本
174
+ name = "Alice"
175
+ await sdk.adapter.Platform.Send.To("123").Text(f"Hello {name}")
176
+ ```
177
+
178
+ ### 适配器管理 (AdapterManager)
179
+ 管理多个平台适配器的注册、启动和关闭。
180
+
181
+ #### register(platform: str, adapter_class: Type[BaseAdapter]) -> bool
182
+ 注册新的适配器类。
183
+ - 参数:
184
+ - platform: 平台名称
185
+ - adapter_class: 适配器类
186
+ - 返回:
187
+ - bool: 注册是否成功
188
+ - 示例:
189
+ ```python
190
+ # 注册适配器
191
+ sdk.adapter.register("MyPlatform", MyPlatformAdapter)
192
+
193
+ # 注册多个适配器
194
+ adapters = {
195
+ "Platform1": Platform1Adapter,
196
+ "Platform2": Platform2Adapter
197
+ }
198
+ for name, adapter in adapters.items():
199
+ sdk.adapter.register(name, adapter)
200
+ ```
201
+
202
+ #### startup(platforms: List[str] = None) -> None
203
+ 启动指定的适配器。
204
+ - 参数:
205
+ - platforms: 要启动的平台列表,None表示所有平台
206
+ - 返回:
207
+ - None
208
+ - 示例:
209
+ ```python
210
+ # 启动所有适配器
211
+ await sdk.adapter.startup()
212
+
213
+ # 启动指定适配器
214
+ await sdk.adapter.startup(["Platform1", "Platform2"])
215
+ ```
216
+
217
+ #### shutdown() -> None
218
+ 关闭所有适配器。
219
+ - 参数: 无
220
+ - 返回:
221
+ - None
222
+ - 示例:
223
+ ```python
224
+ # 关闭所有适配器
225
+ await sdk.adapter.shutdown()
226
+
227
+ # 在程序退出时关闭
228
+ import atexit
229
+ atexit.register(lambda: asyncio.run(sdk.adapter.shutdown()))
230
+ ```
231
+
232
+ ## 最佳实践
233
+
234
+ 1. 适配器实现
235
+ ```python
236
+ class MyPlatformAdapter(sdk.BaseAdapter):
237
+ class Send(sdk.BaseAdapter.Send):
238
+ # 实现基本消息类型
239
+ def Text(self, text: str):
240
+ return asyncio.create_task(
241
+ self._adapter.call_api(
242
+ endpoint="/send",
243
+ content=text,
244
+ recvId=self._target_id,
245
+ recvType=self._target_type
246
+ )
247
+ )
248
+
249
+ # 添加自定义消息类型
250
+ def Image(self, file: bytes):
251
+ return asyncio.create_task(
252
+ self._adapter.call_api(
253
+ endpoint="/send_image",
254
+ file=file,
255
+ recvId=self._target_id,
256
+ recvType=self._target_type
257
+ )
258
+ )
259
+
260
+ async def call_api(self, endpoint: str, **params):
261
+ # 实现API调用逻辑
262
+ async with aiohttp.ClientSession() as session:
263
+ async with session.post(
264
+ f"{self.api_base}{endpoint}",
265
+ json=params
266
+ ) as response:
267
+ return await response.json()
268
+
269
+ async def start(self):
270
+ # 初始化连接
271
+ self.client = await self._create_client()
272
+ # 启动事件监听
273
+ asyncio.create_task(self._listen_events())
274
+
275
+ async def shutdown(self):
276
+ # 清理资源
277
+ if self.client:
278
+ await self.client.close()
279
+ ```
280
+
281
+ 2. 事件处理
282
+ ```python
283
+ # 注册事件处理器
284
+ adapter = MyPlatformAdapter()
285
+
286
+ @adapter.on("message")
287
+ async def handle_message(data):
288
+ # 消息处理逻辑
289
+ if data["type"] == "text":
290
+ await process_text_message(data)
291
+ elif data["type"] == "image":
292
+ await process_image_message(data)
293
+
294
+ # 使用中间件
295
+ @adapter.middleware
296
+ async def auth_middleware(data):
297
+ if not verify_token(data.get("token")):
298
+ return None
299
+ return data
300
+
301
+ @adapter.middleware
302
+ async def log_middleware(data):
303
+ sdk.logger.info(f"处理事件: {data}")
304
+ return data
305
+ ```
306
+
307
+ 3. 消息发送
308
+ ```python
309
+ # 基本消息发送
310
+ async def send_welcome(user_id: str):
311
+ await sdk.adapter.Platform.Send.To("user", user_id).Text("欢迎!")
312
+
313
+ # 复杂消息处理
314
+ async def process_group_notification(group_id: str, event: dict):
315
+ # 发送格式化消息
316
+ message = format_notification(event)
317
+ await sdk.adapter.Platform.Send.To("group", group_id).Text(message)
318
+
319
+ # 发送附加文件
320
+ if event.get("has_attachment"):
321
+ file_data = await get_attachment(event["attachment_id"])
322
+ await sdk.adapter.Platform.Send.To("group", group_id).File(file_data)
323
+ ```
324
+
325
+ ## 注意事项
326
+
327
+ 1. 适配器实现
328
+ - 确保正确实现所有抽象方法
329
+ - 处理所有可能的异常情况
330
+ - 实现适当的重试机制
331
+ - 注意资源的正确释放
332
+
333
+ 2. 事件处理
334
+ - 避免在事件处理器中执行长时间操作
335
+ - 使用适当的错误处理
336
+ - 考虑事件处理的顺序性
337
+ - 合理使用中间件过滤机制
338
+
339
+ 3. 消息发送
340
+ - 实现消息发送的限流机制
341
+ - 处理发送失败的情况
342
+ - 注意消息格式的平台兼容性
343
+ - 大文件传输时考虑分片
344
+
345
+ 4. 生命周期管理
346
+ - 确保适配器正确启动和关闭
347
+ - 处理意外断开的情况
348
+ - 实现自动重连机制
349
+ - 注意资源泄漏问题
350
+ """
351
+
1
352
  import functools
2
353
  import asyncio
3
354
  from typing import Callable, Any, Dict, List, Type, Optional, Set