ErisPulse-OneBot11Adapter 3.7.0__tar.gz → 4.0.1__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_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/PKG-INFO +1 -1
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/entry_points.txt +0 -1
- erispulse_onebot11adapter-4.0.1/OneBotAdapter/Converter.py +582 -0
- erispulse_onebot11adapter-4.0.1/OneBotAdapter/Core.py +899 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/PKG-INFO +1 -1
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/pyproject.toml +1 -2
- erispulse_onebot11adapter-3.7.0/OneBotAdapter/Converter.py +0 -419
- erispulse_onebot11adapter-3.7.0/OneBotAdapter/Core.py +0 -742
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/SOURCES.txt +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/dependency_links.txt +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/requires.txt +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/ErisPulse_OneBot11Adapter.egg-info/top_level.txt +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/LICENSE +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/OneBotAdapter/__init__.py +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/README.md +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/setup.cfg +0 -0
- {erispulse_onebot11adapter-3.7.0 → erispulse_onebot11adapter-4.0.1}/test/test.py +0 -0
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OneBot11 事件转换器
|
|
3
|
+
|
|
4
|
+
将 OneBot11 协议事件转换为 ErisPulse 统一的事件格式(兼容 OneBot12 结构),
|
|
5
|
+
支持消息、通知、请求、元事件四种事件类型的转换
|
|
6
|
+
|
|
7
|
+
{!--< tips >!--}
|
|
8
|
+
1. 转换后的事件保留原始数据在 onebot11_raw 字段中
|
|
9
|
+
2. CQ 码和数组格式消息均支持解析
|
|
10
|
+
3. 未识别的 CQ 码类型会以 onebot11_ 前缀透传
|
|
11
|
+
{!--< /tips >!--}
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import time
|
|
15
|
+
import uuid
|
|
16
|
+
from typing import Dict, Optional, List, Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class OneBot11Converter:
|
|
20
|
+
"""
|
|
21
|
+
OneBot11 → ErisPulse 事件转换器
|
|
22
|
+
|
|
23
|
+
{!--< tips >!--}
|
|
24
|
+
1. 消息事件会解析 CQ 码并转换为 OB12 消息段格式
|
|
25
|
+
2. 通知事件会映射到统一的 detail_type 命名
|
|
26
|
+
{!--< /tips >!--}
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
self._setup_event_mapping()
|
|
31
|
+
|
|
32
|
+
def _setup_event_mapping(self):
|
|
33
|
+
"""
|
|
34
|
+
初始化事件类型映射表
|
|
35
|
+
|
|
36
|
+
建立 OB11 post_type/notice_type 到 OB12 detail_type 的映射关系
|
|
37
|
+
|
|
38
|
+
{!--< internal-use >!--}
|
|
39
|
+
"""
|
|
40
|
+
self.event_map = {
|
|
41
|
+
"message": "message",
|
|
42
|
+
"notice": "notice",
|
|
43
|
+
"request": "request",
|
|
44
|
+
"meta_event": "meta_event",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
self.notice_subtypes = {
|
|
48
|
+
"group_upload": "group_file_upload",
|
|
49
|
+
"group_admin": "group_admin_change",
|
|
50
|
+
"group_decrease": "group_member_decrease",
|
|
51
|
+
"group_increase": "group_member_increase",
|
|
52
|
+
"group_ban": "group_ban",
|
|
53
|
+
"friend_add": "friend_increase",
|
|
54
|
+
"friend_delete": "friend_decrease",
|
|
55
|
+
"group_recall": "message_recall",
|
|
56
|
+
"friend_recall": "message_recall",
|
|
57
|
+
"notify": "notify",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
def convert(self, raw_event: Dict) -> Optional[Dict]:
|
|
61
|
+
"""
|
|
62
|
+
将 OneBot11 事件转换为 OneBot12 格式
|
|
63
|
+
|
|
64
|
+
根据事件类型(message/notice/request/meta_event)分发到对应处理器,
|
|
65
|
+
转换后的事件保留原始数据在 onebot11_raw 字段中
|
|
66
|
+
|
|
67
|
+
:param raw_event: [Dict] 原始 OneBot11 事件数据
|
|
68
|
+
:return: [Optional[Dict]] 转换后的事件字典,不支持的事件类型返回 None
|
|
69
|
+
|
|
70
|
+
:raises ValueError: 当 raw_event 不是字典类型时抛出
|
|
71
|
+
"""
|
|
72
|
+
if not isinstance(raw_event, dict):
|
|
73
|
+
raise ValueError("事件数据必须是字典类型")
|
|
74
|
+
|
|
75
|
+
post_type = raw_event.get("post_type")
|
|
76
|
+
if post_type not in self.event_map:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
# 基础事件结构
|
|
80
|
+
onebot_event = {
|
|
81
|
+
"id": str(raw_event.get("echo", str(uuid.uuid4()))),
|
|
82
|
+
"time": self._convert_timestamp(raw_event.get("time", int(time.time()))),
|
|
83
|
+
"platform": "onebot11",
|
|
84
|
+
"self": {
|
|
85
|
+
"platform": "onebot11",
|
|
86
|
+
"user_id": str(raw_event.get("self_id", "")),
|
|
87
|
+
},
|
|
88
|
+
"onebot11_raw": raw_event, # 保留原始数据
|
|
89
|
+
"onebot11_raw_type": post_type, # 原始事件类型字段
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# 根据事件类型分发处理
|
|
93
|
+
handler = getattr(self, f"_handle_{post_type}", None)
|
|
94
|
+
if handler:
|
|
95
|
+
return handler(raw_event, onebot_event)
|
|
96
|
+
|
|
97
|
+
return None
|
|
98
|
+
|
|
99
|
+
def _convert_timestamp(self, ts) -> int:
|
|
100
|
+
"""
|
|
101
|
+
转换时间戳为 10 位秒级格式
|
|
102
|
+
|
|
103
|
+
自动处理毫秒级(13位)和秒级(10位)时间戳
|
|
104
|
+
|
|
105
|
+
:param ts: [Union[str, int, float]] 原始时间戳
|
|
106
|
+
:return: [int] 10 位秒级时间戳
|
|
107
|
+
|
|
108
|
+
{!--< internal-use >!--}
|
|
109
|
+
"""
|
|
110
|
+
if isinstance(ts, str):
|
|
111
|
+
if len(ts) == 13: # 毫秒级
|
|
112
|
+
return int(ts) // 1000
|
|
113
|
+
return int(ts)
|
|
114
|
+
elif isinstance(ts, (int, float)):
|
|
115
|
+
if ts > 9999999999: # 毫秒级
|
|
116
|
+
return int(ts // 1000)
|
|
117
|
+
return int(ts)
|
|
118
|
+
return int(time.time()) # 默认当前时间
|
|
119
|
+
|
|
120
|
+
def _handle_message(self, raw_event: Dict, base_event: Dict) -> Dict:
|
|
121
|
+
"""
|
|
122
|
+
处理消息事件
|
|
123
|
+
|
|
124
|
+
解析消息内容(支持 CQ 码和数组格式),生成 OB12 结构的事件数据,
|
|
125
|
+
包含消息段列表、纯文本替代消息、发送者信息等
|
|
126
|
+
|
|
127
|
+
:param raw_event: [Dict] 原始 OB11 消息事件
|
|
128
|
+
:param base_event: [Dict] 基础事件结构
|
|
129
|
+
:return: [Dict] 转换后的消息事件
|
|
130
|
+
|
|
131
|
+
{!--< internal-use >!--}
|
|
132
|
+
"""
|
|
133
|
+
message_type = raw_event["message_type"]
|
|
134
|
+
detail_type = "private" if message_type == "private" else "group"
|
|
135
|
+
|
|
136
|
+
# 解析CQ码消息
|
|
137
|
+
message_segments = self._parse_cq_code(raw_event["message"])
|
|
138
|
+
alt_message = self._generate_alt_message(message_segments)
|
|
139
|
+
|
|
140
|
+
base_event.update(
|
|
141
|
+
{
|
|
142
|
+
"type": "message",
|
|
143
|
+
"detail_type": detail_type,
|
|
144
|
+
"message_id": str(raw_event.get("message_id", "")),
|
|
145
|
+
"message": message_segments,
|
|
146
|
+
"alt_message": alt_message,
|
|
147
|
+
"user_id": str(
|
|
148
|
+
raw_event.get("sender", {}).get(
|
|
149
|
+
"user_id", raw_event.get("user_id", "")
|
|
150
|
+
)
|
|
151
|
+
),
|
|
152
|
+
}
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# 添加发送者信息
|
|
156
|
+
sender = raw_event.get("sender", {})
|
|
157
|
+
if "nickname" in sender:
|
|
158
|
+
base_event["user_nickname"] = sender["nickname"]
|
|
159
|
+
if "card" in sender and sender["card"]:
|
|
160
|
+
base_event["user_nickname"] = sender["card"]
|
|
161
|
+
|
|
162
|
+
if detail_type == "group":
|
|
163
|
+
base_event["group_id"] = str(raw_event.get("group_id", ""))
|
|
164
|
+
# 添加群组信息
|
|
165
|
+
if "group_name" in raw_event:
|
|
166
|
+
base_event["group_name"] = raw_event["group_name"]
|
|
167
|
+
|
|
168
|
+
# 处理子类型
|
|
169
|
+
if raw_event.get("sub_type"):
|
|
170
|
+
base_event["sub_type"] = raw_event["sub_type"]
|
|
171
|
+
|
|
172
|
+
return base_event
|
|
173
|
+
|
|
174
|
+
def _parse_cq_code(self, message: Any) -> List[Dict]:
|
|
175
|
+
"""
|
|
176
|
+
解析消息内容为 OB12 消息段列表
|
|
177
|
+
|
|
178
|
+
支持三种输入格式: 纯文本字符串、CQ 码字符串、OB11 数组格式
|
|
179
|
+
|
|
180
|
+
:param message: [Any] 消息内容(str、List[Dict] 或其他)
|
|
181
|
+
:return: [List[Dict]] OB12 消息段列表
|
|
182
|
+
|
|
183
|
+
{!--< internal-use >!--}
|
|
184
|
+
"""
|
|
185
|
+
if isinstance(message, str):
|
|
186
|
+
# 简单文本消息
|
|
187
|
+
if "[CQ:" not in message:
|
|
188
|
+
return [{"type": "text", "data": {"text": message}}]
|
|
189
|
+
|
|
190
|
+
# 包含CQ码的复杂消息
|
|
191
|
+
segments = []
|
|
192
|
+
last_pos = 0
|
|
193
|
+
|
|
194
|
+
while True:
|
|
195
|
+
cq_start = message.find("[CQ:", last_pos)
|
|
196
|
+
if cq_start == -1:
|
|
197
|
+
# 添加剩余文本
|
|
198
|
+
if last_pos < len(message):
|
|
199
|
+
text = message[last_pos:]
|
|
200
|
+
if text:
|
|
201
|
+
segments.append({"type": "text", "data": {"text": text}})
|
|
202
|
+
break
|
|
203
|
+
|
|
204
|
+
# 添加CQ码前的文本
|
|
205
|
+
if cq_start > last_pos:
|
|
206
|
+
text = message[last_pos:cq_start]
|
|
207
|
+
if text:
|
|
208
|
+
segments.append({"type": "text", "data": {"text": text}})
|
|
209
|
+
|
|
210
|
+
# 解析CQ码
|
|
211
|
+
cq_end = message.find("]", cq_start)
|
|
212
|
+
if cq_end == -1:
|
|
213
|
+
# 格式错误,当作普通文本处理
|
|
214
|
+
segments.append(
|
|
215
|
+
{"type": "text", "data": {"text": message[cq_start:]}}
|
|
216
|
+
)
|
|
217
|
+
break
|
|
218
|
+
|
|
219
|
+
cq_content = message[cq_start + 4 : cq_end] # 去掉[CQ:和]
|
|
220
|
+
parts = cq_content.split(",", 1)
|
|
221
|
+
cq_type = parts[0]
|
|
222
|
+
cq_data = {}
|
|
223
|
+
|
|
224
|
+
if len(parts) > 1:
|
|
225
|
+
data_str = parts[1]
|
|
226
|
+
# 简单解析参数(注意:实际CQ码参数可能包含转义字符)
|
|
227
|
+
data_parts = data_str.split(",")
|
|
228
|
+
for part in data_parts:
|
|
229
|
+
if "=" in part:
|
|
230
|
+
key, value = part.split("=", 1)
|
|
231
|
+
cq_data[key] = value
|
|
232
|
+
|
|
233
|
+
# 转换CQ码类型
|
|
234
|
+
if cq_type == "text":
|
|
235
|
+
segments.append(
|
|
236
|
+
{"type": "text", "data": {"text": cq_data.get("text", "")}}
|
|
237
|
+
)
|
|
238
|
+
elif cq_type == "image":
|
|
239
|
+
segments.append(
|
|
240
|
+
{
|
|
241
|
+
"type": "image",
|
|
242
|
+
"data": {
|
|
243
|
+
"file": cq_data.get("file"),
|
|
244
|
+
"url": cq_data.get("url"),
|
|
245
|
+
"cache": cq_data.get("cache", "1"),
|
|
246
|
+
},
|
|
247
|
+
}
|
|
248
|
+
)
|
|
249
|
+
elif cq_type == "record":
|
|
250
|
+
segments.append(
|
|
251
|
+
{
|
|
252
|
+
"type": "audio",
|
|
253
|
+
"data": {
|
|
254
|
+
"file": cq_data.get("file"),
|
|
255
|
+
"url": cq_data.get("url"),
|
|
256
|
+
"magic": cq_data.get("magic", "0"),
|
|
257
|
+
},
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
elif cq_type == "at":
|
|
261
|
+
segments.append(
|
|
262
|
+
{
|
|
263
|
+
"type": "mention",
|
|
264
|
+
"data": {
|
|
265
|
+
"user_id": cq_data.get("qq"),
|
|
266
|
+
"user_name": cq_data.get("name", ""),
|
|
267
|
+
},
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
elif cq_type == "face":
|
|
271
|
+
segments.append(
|
|
272
|
+
{
|
|
273
|
+
"type": "face",
|
|
274
|
+
"data": {
|
|
275
|
+
"id": cq_data.get("id"),
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
)
|
|
279
|
+
elif cq_type == "reply":
|
|
280
|
+
segments.append(
|
|
281
|
+
{
|
|
282
|
+
"type": "reply",
|
|
283
|
+
"data": {
|
|
284
|
+
"message_id": cq_data.get("id"),
|
|
285
|
+
"user_id": cq_data.get("qq", ""),
|
|
286
|
+
},
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
else:
|
|
290
|
+
# 保留原始CQ码类型
|
|
291
|
+
segments.append({"type": f"onebot11_{cq_type}", "data": cq_data})
|
|
292
|
+
|
|
293
|
+
last_pos = cq_end + 1
|
|
294
|
+
|
|
295
|
+
return segments
|
|
296
|
+
|
|
297
|
+
# 处理数组格式的消息
|
|
298
|
+
elif isinstance(message, list):
|
|
299
|
+
segments = []
|
|
300
|
+
for segment in message:
|
|
301
|
+
if isinstance(segment, str):
|
|
302
|
+
segments.append({"type": "text", "data": {"text": segment}})
|
|
303
|
+
elif isinstance(segment, dict):
|
|
304
|
+
cq_type = segment.get("type", "")
|
|
305
|
+
cq_data = segment.get("data", {})
|
|
306
|
+
|
|
307
|
+
if cq_type == "text":
|
|
308
|
+
segments.append(
|
|
309
|
+
{"type": "text", "data": {"text": cq_data.get("text", "")}}
|
|
310
|
+
)
|
|
311
|
+
elif cq_type == "image":
|
|
312
|
+
segments.append(
|
|
313
|
+
{
|
|
314
|
+
"type": "image",
|
|
315
|
+
"data": {
|
|
316
|
+
"file": cq_data.get("file"),
|
|
317
|
+
"url": cq_data.get("url"),
|
|
318
|
+
"cache": cq_data.get("cache", "1"),
|
|
319
|
+
},
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
elif cq_type == "record":
|
|
323
|
+
segments.append(
|
|
324
|
+
{
|
|
325
|
+
"type": "audio",
|
|
326
|
+
"data": {
|
|
327
|
+
"file": cq_data.get("file"),
|
|
328
|
+
"url": cq_data.get("url"),
|
|
329
|
+
"magic": cq_data.get("magic", "0"),
|
|
330
|
+
},
|
|
331
|
+
}
|
|
332
|
+
)
|
|
333
|
+
elif cq_type == "at":
|
|
334
|
+
segments.append(
|
|
335
|
+
{
|
|
336
|
+
"type": "mention",
|
|
337
|
+
"data": {
|
|
338
|
+
"user_id": cq_data.get("qq"),
|
|
339
|
+
"user_name": cq_data.get("name", ""),
|
|
340
|
+
},
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
elif cq_type == "face":
|
|
344
|
+
segments.append(
|
|
345
|
+
{
|
|
346
|
+
"type": "face",
|
|
347
|
+
"data": {
|
|
348
|
+
"id": cq_data.get("id"),
|
|
349
|
+
},
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
elif cq_type == "reply":
|
|
353
|
+
segments.append(
|
|
354
|
+
{
|
|
355
|
+
"type": "reply",
|
|
356
|
+
"data": {
|
|
357
|
+
"message_id": cq_data.get("id"),
|
|
358
|
+
"user_id": cq_data.get("qq", ""),
|
|
359
|
+
},
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
else:
|
|
363
|
+
# 保留原始CQ码类型
|
|
364
|
+
segments.append(
|
|
365
|
+
{"type": f"onebot11_{cq_type}", "data": cq_data}
|
|
366
|
+
)
|
|
367
|
+
return segments
|
|
368
|
+
|
|
369
|
+
# 其他情况当作纯文本处理
|
|
370
|
+
return [{"type": "text", "data": {"text": str(message)}}]
|
|
371
|
+
|
|
372
|
+
def _generate_alt_message(self, segments: List[Dict]) -> str:
|
|
373
|
+
"""
|
|
374
|
+
从消息段列表生成纯文本替代消息
|
|
375
|
+
|
|
376
|
+
图片替换为 [图片]、语音替换为 [语音]、@ 用户替换为 @name 等
|
|
377
|
+
|
|
378
|
+
:param segments: [List[Dict]] 消息段列表
|
|
379
|
+
:return: [str] 纯文本替代消息
|
|
380
|
+
|
|
381
|
+
{!--< internal-use >!--}
|
|
382
|
+
"""
|
|
383
|
+
parts = []
|
|
384
|
+
for seg in segments:
|
|
385
|
+
if seg["type"] == "text":
|
|
386
|
+
parts.append(seg["data"]["text"])
|
|
387
|
+
elif seg["type"] == "image":
|
|
388
|
+
parts.append("[图片]")
|
|
389
|
+
elif seg["type"] == "audio":
|
|
390
|
+
parts.append("[语音]")
|
|
391
|
+
elif seg["type"] == "mention":
|
|
392
|
+
parts.append(
|
|
393
|
+
f"@{seg['data'].get('user_name', seg['data'].get('user_id', ''))}"
|
|
394
|
+
)
|
|
395
|
+
elif seg["type"] == "face":
|
|
396
|
+
parts.append(f"[表情:{seg['data'].get('id', '')}]")
|
|
397
|
+
elif seg["type"] == "reply":
|
|
398
|
+
parts.append("[回复]")
|
|
399
|
+
elif seg["type"].startswith("onebot11_"):
|
|
400
|
+
parts.append(f"[{seg['type'][9:]}]")
|
|
401
|
+
return "".join(parts)
|
|
402
|
+
|
|
403
|
+
def _handle_notice(self, raw_event: Dict, base_event: Dict) -> Dict:
|
|
404
|
+
"""
|
|
405
|
+
处理通知事件
|
|
406
|
+
|
|
407
|
+
处理群文件上传、群管理员变动、群成员增减、群禁言、好友增减、
|
|
408
|
+
消息撤回、群荣誉/戳一戳/运气王等通知类型
|
|
409
|
+
|
|
410
|
+
:param raw_event: [Dict] 原始 OB11 通知事件
|
|
411
|
+
:param base_event: [Dict] 基础事件结构
|
|
412
|
+
:return: [Dict] 转换后的通知事件
|
|
413
|
+
|
|
414
|
+
{!--< internal-use >!--}
|
|
415
|
+
"""
|
|
416
|
+
notice_type = raw_event["notice_type"]
|
|
417
|
+
sub_type = raw_event.get("sub_type", "")
|
|
418
|
+
|
|
419
|
+
# 映射通知子类型
|
|
420
|
+
detail_type = self.notice_subtypes.get(notice_type, notice_type)
|
|
421
|
+
|
|
422
|
+
base_event.update(
|
|
423
|
+
{"type": "notice", "detail_type": detail_type, "onebot11_notice": raw_event}
|
|
424
|
+
)
|
|
425
|
+
|
|
426
|
+
# 处理不同类型的通知
|
|
427
|
+
if notice_type == "group_upload":
|
|
428
|
+
base_event.update(
|
|
429
|
+
{
|
|
430
|
+
"group_id": str(raw_event.get("group_id")),
|
|
431
|
+
"user_id": str(raw_event.get("user_id")),
|
|
432
|
+
"onebot11_file": raw_event.get("file"),
|
|
433
|
+
}
|
|
434
|
+
)
|
|
435
|
+
elif notice_type == "group_admin":
|
|
436
|
+
base_event.update(
|
|
437
|
+
{
|
|
438
|
+
"group_id": str(raw_event.get("group_id")),
|
|
439
|
+
"user_id": str(raw_event.get("user_id")),
|
|
440
|
+
"sub_type": "set" if sub_type == "set" else "unset",
|
|
441
|
+
}
|
|
442
|
+
)
|
|
443
|
+
elif notice_type in ["group_increase", "group_decrease"]:
|
|
444
|
+
base_event.update(
|
|
445
|
+
{
|
|
446
|
+
"group_id": str(raw_event.get("group_id")),
|
|
447
|
+
"user_id": str(raw_event.get("user_id")),
|
|
448
|
+
"operator_id": str(raw_event.get("operator_id", "")),
|
|
449
|
+
"sub_type": sub_type,
|
|
450
|
+
}
|
|
451
|
+
)
|
|
452
|
+
elif notice_type == "group_ban":
|
|
453
|
+
base_event.update(
|
|
454
|
+
{
|
|
455
|
+
"group_id": str(raw_event.get("group_id")),
|
|
456
|
+
"operator_id": str(raw_event.get("operator_id")),
|
|
457
|
+
"user_id": str(raw_event.get("user_id")),
|
|
458
|
+
"duration": raw_event.get("duration", 0),
|
|
459
|
+
}
|
|
460
|
+
)
|
|
461
|
+
elif notice_type in ["friend_add", "friend_delete"]:
|
|
462
|
+
base_event.update({"user_id": str(raw_event.get("user_id"))})
|
|
463
|
+
elif notice_type in ["group_recall", "friend_recall"]:
|
|
464
|
+
base_event.update(
|
|
465
|
+
{
|
|
466
|
+
"message_id": str(raw_event.get("message_id")),
|
|
467
|
+
"user_id": str(raw_event.get("user_id")),
|
|
468
|
+
"group_id": str(raw_event.get("group_id", ""))
|
|
469
|
+
if notice_type == "group_recall"
|
|
470
|
+
else None,
|
|
471
|
+
}
|
|
472
|
+
)
|
|
473
|
+
elif notice_type == "notify":
|
|
474
|
+
if sub_type == "honor":
|
|
475
|
+
base_event["detail_type"] = "onebot11_honor"
|
|
476
|
+
base_event.update(
|
|
477
|
+
{
|
|
478
|
+
"group_id": str(raw_event.get("group_id")),
|
|
479
|
+
"user_id": str(raw_event.get("user_id")),
|
|
480
|
+
"honor_type": raw_event.get("honor_type"),
|
|
481
|
+
}
|
|
482
|
+
)
|
|
483
|
+
elif sub_type == "poke":
|
|
484
|
+
base_event["detail_type"] = "onebot11_poke"
|
|
485
|
+
base_event.update(
|
|
486
|
+
{
|
|
487
|
+
"group_id": str(raw_event.get("group_id", "")),
|
|
488
|
+
"user_id": str(raw_event.get("user_id")),
|
|
489
|
+
"target_id": str(raw_event.get("target_id")),
|
|
490
|
+
}
|
|
491
|
+
)
|
|
492
|
+
elif sub_type == "lucky_king":
|
|
493
|
+
base_event["detail_type"] = "onebot11_lucky_king"
|
|
494
|
+
base_event.update(
|
|
495
|
+
{
|
|
496
|
+
"group_id": str(raw_event.get("group_id")),
|
|
497
|
+
"user_id": str(raw_event.get("user_id")),
|
|
498
|
+
"target_id": str(raw_event.get("target_id")),
|
|
499
|
+
}
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
return base_event
|
|
503
|
+
|
|
504
|
+
def _handle_request(self, raw_event: Dict, base_event: Dict) -> Dict:
|
|
505
|
+
"""
|
|
506
|
+
处理请求事件
|
|
507
|
+
|
|
508
|
+
处理好友请求和群请求(加群/邀请),提取 user_id、comment、flag 等关键字段
|
|
509
|
+
|
|
510
|
+
:param raw_event: [Dict] 原始 OB11 请求事件
|
|
511
|
+
:param base_event: [Dict] 基础事件结构
|
|
512
|
+
:return: [Dict] 转换后的请求事件
|
|
513
|
+
|
|
514
|
+
{!--< internal-use >!--}
|
|
515
|
+
"""
|
|
516
|
+
request_type = raw_event["request_type"]
|
|
517
|
+
|
|
518
|
+
base_event.update(
|
|
519
|
+
{
|
|
520
|
+
"type": "request",
|
|
521
|
+
"detail_type": request_type,
|
|
522
|
+
"onebot11_request": raw_event,
|
|
523
|
+
}
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
if request_type == "friend":
|
|
527
|
+
base_event.update(
|
|
528
|
+
{
|
|
529
|
+
"user_id": str(raw_event.get("user_id")),
|
|
530
|
+
"comment": raw_event.get("comment"),
|
|
531
|
+
"flag": raw_event.get("flag"),
|
|
532
|
+
"request_id": raw_event.get("flag"),
|
|
533
|
+
}
|
|
534
|
+
)
|
|
535
|
+
elif request_type == "group":
|
|
536
|
+
base_event.update(
|
|
537
|
+
{
|
|
538
|
+
"group_id": str(raw_event.get("group_id")),
|
|
539
|
+
"user_id": str(raw_event.get("user_id")),
|
|
540
|
+
"comment": raw_event.get("comment"),
|
|
541
|
+
"sub_type": raw_event.get("sub_type"),
|
|
542
|
+
"flag": raw_event.get("flag"),
|
|
543
|
+
"request_id": raw_event.get("flag"),
|
|
544
|
+
}
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
return base_event
|
|
548
|
+
|
|
549
|
+
def _handle_meta_event(self, raw_event: Dict, base_event: Dict) -> Dict:
|
|
550
|
+
"""
|
|
551
|
+
处理元事件
|
|
552
|
+
|
|
553
|
+
处理生命周期事件(connect/disable)和心跳事件
|
|
554
|
+
|
|
555
|
+
:param raw_event: [Dict] 原始 OB11 元事件
|
|
556
|
+
:param base_event: [Dict] 基础事件结构
|
|
557
|
+
:return: [Dict] 转换后的元事件
|
|
558
|
+
|
|
559
|
+
{!--< internal-use >!--}
|
|
560
|
+
"""
|
|
561
|
+
meta_type = raw_event["meta_event_type"]
|
|
562
|
+
|
|
563
|
+
if meta_type == "heartbeat":
|
|
564
|
+
detail_type = "heartbeat"
|
|
565
|
+
else:
|
|
566
|
+
detail_type = f"onebot11_{meta_type}"
|
|
567
|
+
|
|
568
|
+
base_event.update(
|
|
569
|
+
{
|
|
570
|
+
"type": "meta_event",
|
|
571
|
+
"detail_type": detail_type,
|
|
572
|
+
"onebot11_meta": raw_event,
|
|
573
|
+
}
|
|
574
|
+
)
|
|
575
|
+
|
|
576
|
+
if meta_type == "lifecycle":
|
|
577
|
+
base_event["sub_type"] = raw_event.get("sub_type", "")
|
|
578
|
+
elif meta_type == "heartbeat":
|
|
579
|
+
base_event["interval"] = raw_event.get("interval", 0)
|
|
580
|
+
base_event["status"] = raw_event.get("status", {})
|
|
581
|
+
|
|
582
|
+
return base_event
|