ErisPulse 1.2.4__tar.gz → 1.2.7__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.
Files changed (46) hide show
  1. {erispulse-1.2.4 → erispulse-1.2.7}/.github/tools/update-api-docs.py +1 -1
  2. {erispulse-1.2.4 → erispulse-1.2.7}/PKG-INFO +6 -5
  3. {erispulse-1.2.4 → erispulse-1.2.7}/README.md +1 -2
  4. erispulse-1.2.7/devs/test_adapter.py +225 -0
  5. {erispulse-1.2.4 → erispulse-1.2.7}/docs/ADAPTERS.md +48 -79
  6. {erispulse-1.2.4 → erispulse-1.2.7}/docs/CHANGELOG.md +18 -0
  7. {erispulse-1.2.4 → erispulse-1.2.7}/docs/DEVELOPMENT.md +12 -0
  8. {erispulse-1.2.4 → erispulse-1.2.7}/docs/ForAIDocs/ErisPulseDevelop.md +94 -113
  9. {erispulse-1.2.4 → erispulse-1.2.7}/docs/REFERENCE.md +33 -33
  10. {erispulse-1.2.4 → erispulse-1.2.7}/pyproject.toml +6 -4
  11. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/__init__.py +10 -9
  12. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/__main__.py +52 -2
  13. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/adapter.py +23 -20
  14. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/db.py +85 -67
  15. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/logger.py +27 -14
  16. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/mods.py +2 -2
  17. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/raiserr.py +5 -4
  18. {erispulse-1.2.4 → erispulse-1.2.7}/src/ErisPulse/util.py +7 -6
  19. erispulse-1.2.4/devs/test_adapter.py +0 -130
  20. {erispulse-1.2.4 → erispulse-1.2.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  21. {erispulse-1.2.4 → erispulse-1.2.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  22. {erispulse-1.2.4 → erispulse-1.2.7}/.github/assets/erispulse_logo.png +0 -0
  23. {erispulse-1.2.4 → erispulse-1.2.7}/.github/config/notify.json +0 -0
  24. {erispulse-1.2.4 → erispulse-1.2.7}/.github/tools/merge_md.py +0 -0
  25. {erispulse-1.2.4 → erispulse-1.2.7}/.github/workflows/notifications.yml +0 -0
  26. {erispulse-1.2.4 → erispulse-1.2.7}/.github/workflows/pypi-publish.yml +0 -0
  27. {erispulse-1.2.4 → erispulse-1.2.7}/.github/workflows/send-email/action.yml +0 -0
  28. {erispulse-1.2.4 → erispulse-1.2.7}/.github/workflows/send-email/send_mail.py +0 -0
  29. {erispulse-1.2.4 → erispulse-1.2.7}/.github/workflows/send-email/send_mail_old.py +0 -0
  30. {erispulse-1.2.4 → erispulse-1.2.7}/.gitignore +0 -0
  31. {erispulse-1.2.4 → erispulse-1.2.7}/.python-version +0 -0
  32. {erispulse-1.2.4 → erispulse-1.2.7}/LICENSE +0 -0
  33. {erispulse-1.2.4 → erispulse-1.2.7}/devs/test.py +0 -0
  34. {erispulse-1.2.4 → erispulse-1.2.7}/devs/test_files/test.docx +0 -0
  35. {erispulse-1.2.4 → erispulse-1.2.7}/devs/test_files/test.jpg +0 -0
  36. {erispulse-1.2.4 → erispulse-1.2.7}/devs/test_files/test.mp4 +0 -0
  37. {erispulse-1.2.4 → erispulse-1.2.7}/docs/AI-Module-Generation.md +0 -0
  38. {erispulse-1.2.4 → erispulse-1.2.7}/docs/CLI.md +0 -0
  39. {erispulse-1.2.4 → erispulse-1.2.7}/docs/ORIGIN.md +0 -0
  40. {erispulse-1.2.4 → erispulse-1.2.7}/docs/quick-start.md +0 -0
  41. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/cd_branch.sh +0 -0
  42. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/commit.sh +0 -0
  43. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/create_branch.sh +0 -0
  44. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/create_pr.sh +0 -0
  45. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/merge_dev.sh +0 -0
  46. {erispulse-1.2.4 → erispulse-1.2.7}/gitc/usage.md +0 -0
@@ -26,7 +26,7 @@ def update_reference_docs(module_name, docs, reference_path, module_path):
26
26
  with open(reference_path, 'r', encoding='utf-8') as f:
27
27
  content = f.read()
28
28
 
29
- github_base_url = "https://raw.githubusercontent.com/ErisPulse/ErisPulse/refs/heads/main/"
29
+ github_base_url = "https://raw.githubusercontent.com/ErisPulse/ErisPulse/refs/heads/main/src/"
30
30
  github_source_url = github_base_url + module_path.replace('\\', '/')
31
31
 
32
32
  section_header = f"## {module_name} (source: [{module_path}]({github_source_url}))"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ErisPulse
3
- Version: 1.2.4
3
+ Version: 1.2.7
4
4
  Summary: ErisPulse 是一个模块化、可扩展的异步 Python SDK 框架,主要用于构建高效、可维护的机器人应用程序。
5
5
  Author-email: "艾莉丝·格雷拉特(WSu2059)" <wsu2059@qq.com>, runoneall <runoobsteve@gmail.com>
6
6
  License: MIT License
@@ -38,13 +38,15 @@ Classifier: License :: OSI Approved :: MIT License
38
38
  Classifier: Operating System :: OS Independent
39
39
  Classifier: Programming Language :: Python :: 3
40
40
  Classifier: Programming Language :: Python :: 3 :: Only
41
+ Classifier: Programming Language :: Python :: 3.8
42
+ Classifier: Programming Language :: Python :: 3.9
41
43
  Classifier: Programming Language :: Python :: 3.10
42
44
  Classifier: Programming Language :: Python :: 3.11
43
45
  Classifier: Programming Language :: Python :: 3.12
44
46
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
45
- Requires-Python: >=3.10
47
+ Requires-Python: >=3.8
46
48
  Requires-Dist: aiohttp
47
- Requires-Dist: importlib>=1.0.4
49
+ Requires-Dist: importlib
48
50
  Requires-Dist: pip
49
51
  Requires-Dist: watchdog
50
52
  Description-Content-Type: text/markdown
@@ -54,7 +56,6 @@ Description-Content-Type: text/markdown
54
56
  ![ErisPulse Logo](.github/assets/erispulse_logo.png)
55
57
 
56
58
  [![FramerOrg](https://img.shields.io/badge/合作伙伴-FramerOrg-blue?style=flat-square)](https://github.com/FramerOrg)
57
- [![License](https://img.shields.io/github/license/ErisPulse/ErisPulse?style=flat-square)](https://github.com/ErisPulse/ErisPulse/blob/main/LICENSE)
58
59
  [![Python Versions](https://img.shields.io/pypi/pyversions/ErisPulse?style=flat-square)](https://pypi.org/project/ErisPulse/)
59
60
 
60
61
  > 文档站:
@@ -203,4 +204,4 @@ epsdk run your_script.py --reload
203
204
 
204
205
  ---
205
206
 
206
- [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
207
+ [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
@@ -3,7 +3,6 @@
3
3
  ![ErisPulse Logo](.github/assets/erispulse_logo.png)
4
4
 
5
5
  [![FramerOrg](https://img.shields.io/badge/合作伙伴-FramerOrg-blue?style=flat-square)](https://github.com/FramerOrg)
6
- [![License](https://img.shields.io/github/license/ErisPulse/ErisPulse?style=flat-square)](https://github.com/ErisPulse/ErisPulse/blob/main/LICENSE)
7
6
  [![Python Versions](https://img.shields.io/pypi/pyversions/ErisPulse?style=flat-square)](https://pypi.org/project/ErisPulse/)
8
7
 
9
8
  > 文档站:
@@ -152,4 +151,4 @@ epsdk run your_script.py --reload
152
151
 
153
152
  ---
154
153
 
155
- [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
154
+ [加入社区讨论 →](https://github.com/ErisPulse/ErisPulse/discussions)
@@ -0,0 +1,225 @@
1
+ from ErisPulse import sdk
2
+ import asyncio
3
+ from pathlib import Path
4
+
5
+ # 测试文件路径
6
+ CURRENT_DIR = Path(__file__).parent / "test_files"
7
+ TEST_IMAGE_PATH = CURRENT_DIR / "test.jpg"
8
+ TEST_VIDEO_PATH = CURRENT_DIR / "test.mp4"
9
+ TEST_DOCUMENT_PATH = CURRENT_DIR / "test.docx"
10
+
11
+ # 各平台测试配置
12
+ TELEGRAM_USER_ID = "6117725680"
13
+ TELEGRAM_GROUP_ID = "-1001234567890" # None 表示不发群聊
14
+
15
+ QQ_USER_ID = "123456789"
16
+ QQ_GROUP_ID = "782199153" # None 表示不发群聊
17
+
18
+ YUNHU_USER_ID = "5197892"
19
+ YUNHU_GROUP_ID = "635409929" # None 表示不发群聊
20
+
21
+ async def telegram_test(startup: bool):
22
+ if not hasattr(sdk.adapter, "telegram"):
23
+ return
24
+ telegram = sdk.adapter.telegram
25
+ if startup:
26
+ await telegram.Send.To("user", TELEGRAM_USER_ID).Text("【启动通知】SDK已启动 - Telegram文本消息")
27
+ if TEST_IMAGE_PATH.exists():
28
+ with open(TEST_IMAGE_PATH, "rb") as f:
29
+ await telegram.Send.To("user", TELEGRAM_USER_ID).Image(f.read())
30
+ if TEST_VIDEO_PATH.exists():
31
+ with open(TEST_VIDEO_PATH, "rb") as f:
32
+ await telegram.Send.To("user", TELEGRAM_USER_ID).Video(f.read())
33
+ if TEST_DOCUMENT_PATH.exists():
34
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
35
+ await telegram.Send.To("user", TELEGRAM_USER_ID).Document(f.read())
36
+ if TELEGRAM_GROUP_ID:
37
+ await telegram.Send.To("group", TELEGRAM_GROUP_ID).Text("【启动通知】SDK已启动 - Telegram群聊文本消息")
38
+ if TEST_IMAGE_PATH.exists():
39
+ with open(TEST_IMAGE_PATH, "rb") as f:
40
+ await telegram.Send.To("group", TELEGRAM_GROUP_ID).Image(f.read())
41
+ if TEST_VIDEO_PATH.exists():
42
+ with open(TEST_VIDEO_PATH, "rb") as f:
43
+ await telegram.Send.To("group", TELEGRAM_GROUP_ID).Video(f.read())
44
+ if TEST_DOCUMENT_PATH.exists():
45
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
46
+ await telegram.Send.To("group", TELEGRAM_GROUP_ID).Document(f.read())
47
+ else:
48
+ await telegram.Send.To("user", TELEGRAM_USER_ID).Text("【关闭通知】SDK已关闭")
49
+ if TELEGRAM_GROUP_ID:
50
+ await telegram.Send.To("group", TELEGRAM_GROUP_ID).Text("【关闭通知】SDK已关闭")
51
+
52
+ async def qq_test(startup: bool):
53
+ if not hasattr(sdk.adapter, "QQ"):
54
+ return
55
+ qq = sdk.adapter.QQ
56
+ if startup:
57
+ await asyncio.sleep(5)
58
+ await qq.Send.To("user", QQ_USER_ID).Text("【启动通知】SDK已启动 - QQ文本消息")
59
+ if TEST_IMAGE_PATH.exists():
60
+ with open(TEST_IMAGE_PATH, "rb") as f:
61
+ await qq.Send.To("user", QQ_USER_ID).Image(f.read())
62
+ if TEST_VIDEO_PATH.exists():
63
+ with open(TEST_VIDEO_PATH, "rb") as f:
64
+ await qq.Send.To("user", QQ_USER_ID).Video(f.read())
65
+ if TEST_DOCUMENT_PATH.exists():
66
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
67
+ await qq.Send.To("user", QQ_USER_ID).Document(f.read())
68
+ if QQ_GROUP_ID:
69
+ await qq.Send.To("group", QQ_GROUP_ID).Text("【启动通知】SDK已启动 - QQ群聊文本消息")
70
+ if TEST_IMAGE_PATH.exists():
71
+ with open(TEST_IMAGE_PATH, "rb") as f:
72
+ await qq.Send.To("group", QQ_GROUP_ID).Image(f.read())
73
+ if TEST_VIDEO_PATH.exists():
74
+ with open(TEST_VIDEO_PATH, "rb") as f:
75
+ await qq.Send.To("group", QQ_GROUP_ID).Video(f.read())
76
+ if TEST_DOCUMENT_PATH.exists():
77
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
78
+ await qq.Send.To("group", QQ_GROUP_ID).Document(f.read())
79
+ else:
80
+ await qq.Send.To("user", QQ_USER_ID).Text("【关闭通知】SDK已关闭")
81
+ if QQ_GROUP_ID:
82
+ await qq.Send.To("group", QQ_GROUP_ID).Text("【关闭通知】SDK已关闭")
83
+
84
+ async def yunhu_test(startup: bool):
85
+ if not hasattr(sdk.adapter, "Yunhu"):
86
+ return
87
+ yunhu = sdk.adapter.Yunhu
88
+ if startup:
89
+ buttons = [
90
+ [{"text": "复制", "actionType": 2, "value": "xxxx"}],
91
+ [{"text": "点击跳转", "actionType": 1, "url": "http://www.baidu.com"}]
92
+ ]
93
+
94
+ # 文本消息 + 按钮
95
+ response_text = await yunhu.Send.To("user", YUNHU_USER_ID).Text("【启动通知】SDK已启动 - 带按钮文本消息", buttons=buttons)
96
+ print("文本消息发送返回值:", response_text)
97
+
98
+ # HTML 消息
99
+ response_html = await yunhu.Send.To("user", YUNHU_USER_ID).Html("<b>这是一条HTML消息</b>")
100
+ print("HTML消息发送返回值:", response_html)
101
+
102
+ # Markdown 消息
103
+ response_md = await yunhu.Send.To("user", YUNHU_USER_ID).Markdown("# 这是一条Markdown消息")
104
+ print("Markdown消息发送返回值:", response_md)
105
+
106
+ # 图片消息
107
+ if TEST_IMAGE_PATH.exists():
108
+ with open(TEST_IMAGE_PATH, "rb") as f:
109
+ image_data = f.read()
110
+ response_image = await yunhu.Send.To("user", YUNHU_USER_ID).Image(image_data)
111
+ print("图片消息发送返回值:", response_image)
112
+
113
+ # 视频消息
114
+ if TEST_VIDEO_PATH.exists():
115
+ with open(TEST_VIDEO_PATH, "rb") as f:
116
+ video_data = f.read()
117
+ response_video = await yunhu.Send.To("user", YUNHU_USER_ID).Video(video_data)
118
+ print("视频消息发送返回值:", response_video)
119
+
120
+ # 文件消息
121
+ if TEST_DOCUMENT_PATH.exists():
122
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
123
+ file_data = f.read()
124
+ response_file = await yunhu.Send.To("user", YUNHU_USER_ID).File(file_data)
125
+ print("文件消息发送返回值:", response_file)
126
+
127
+ # 批量发送测试
128
+ test_user_ids = [YUNHU_USER_ID, "5197893", "5197894"] # 模拟多个用户ID
129
+
130
+ # 1. 文本消息批量发送
131
+ response_batch_text = await yunhu.Send.To("user", test_user_ids).Text("批量文本测试消息")
132
+ print("批量文本消息发送返回值:", response_batch_text)
133
+
134
+ # 2. HTML消息批量发送
135
+ response_batch_html = await yunhu.Send.To("user", test_user_ids).Html("<b>批量HTML测试消息</b>")
136
+ print("批量HTML消息发送返回值:", response_batch_html)
137
+
138
+ # 3. Markdown消息批量发送
139
+ response_batch_md = await yunhu.Send.To("user", test_user_ids).Markdown("# 批量Markdown测试消息")
140
+ print("批量Markdown消息发送返回值:", response_batch_md)
141
+
142
+ # 4. 图片批量发送
143
+ if TEST_IMAGE_PATH.exists():
144
+ with open(TEST_IMAGE_PATH, "rb") as f:
145
+ image_data = f.read()
146
+ response_batch_image = await yunhu.Send.To("user", test_user_ids).Image(image_data)
147
+ print("批量图片消息发送返回值:", response_batch_image)
148
+ # 5. 文件批量发送
149
+ if TEST_DOCUMENT_PATH.exists():
150
+ with open(TEST_DOCUMENT_PATH, "rb") as f:
151
+ file_data = f.read()
152
+ response_batch_file = await yunhu.Send.To("user", test_user_ids).File(file_data)
153
+ print("批量文件消息发送返回值:", response_batch_file)
154
+
155
+ # 6. 保留原Batch方法测试(已弃用)
156
+ response_batch_old = await yunhu.Send.To("user", YUNHU_USER_ID).Batch([YUNHU_USER_ID], "旧批量方法测试消息")
157
+ print("旧批量方法发送返回值:", response_batch_old)
158
+
159
+ # 编辑消息(需要 msg_id)
160
+ if 'response_text' in locals() and 'msgId' in response_text.get('data', {}).get('messageInfo', {}):
161
+ msg_id = response_text['data']['messageInfo']['msgId']
162
+ response_edit = await yunhu.Send.To("user", YUNHU_USER_ID).Edit(msg_id, "这是编辑后的消息")
163
+ print("编辑消息发送返回值:", response_edit)
164
+
165
+ # 撤回消息(需要 msg_id)
166
+ if 'msg_id' in locals():
167
+ response_recall = await yunhu.Send.To("user", YUNHU_USER_ID).Recall(msg_id)
168
+ print("撤回消息发送返回值:", response_recall)
169
+
170
+ # 流式消息
171
+ async def stream_generator():
172
+ for i in range(3):
173
+ yield f"流式片段{i}".encode('utf-8')
174
+ await asyncio.sleep(1)
175
+
176
+ response_stream = await yunhu.Send.To("user", YUNHU_USER_ID).Stream("text", stream_generator())
177
+ print("流式消息发送返回值:", response_stream)
178
+
179
+ # 群聊消息
180
+ if YUNHU_GROUP_ID:
181
+ response_group_text = await yunhu.Send.To("group", YUNHU_GROUP_ID).Text("【群聊通知】SDK已启动")
182
+ print("群聊文本消息发送返回值:", response_group_text)
183
+
184
+ if TEST_IMAGE_PATH.exists():
185
+ with open(TEST_IMAGE_PATH, "rb") as f:
186
+ image_data = f.read()
187
+ response_group_image = await yunhu.Send.To("group", YUNHU_GROUP_ID).Image(image_data)
188
+ print("群聊图片消息发送返回值:", response_group_image)
189
+
190
+ if TEST_VIDEO_PATH.exists() is None:
191
+ with open(TEST_VIDEO_PATH, "rb") as f:
192
+ video_data = f.read()
193
+ response_group_video = await yunhu.Send.To("group", YUNHU_GROUP_ID).Video(video_data)
194
+ print("群聊视频消息发送返回值:", response_group_video)
195
+
196
+ else:
197
+ # 关闭时发送关闭通知
198
+ response_shutdown = await yunhu.Send.To("user", YUNHU_USER_ID).Text("【关闭通知】SDK已关闭")
199
+ print("关闭通知消息发送返回值:", response_shutdown)
200
+
201
+ if YUNHU_GROUP_ID:
202
+ response_group_shutdown = await yunhu.Send.To("group", YUNHU_GROUP_ID).Text("【关闭通知】SDK已关闭")
203
+ print("群聊关闭通知消息发送返回值:", response_group_shutdown)
204
+ async def main():
205
+ sdk.init()
206
+ try:
207
+ sdk.logger.set_output_file("test.log")
208
+ await sdk.adapter.startup()
209
+ await asyncio.sleep(1)
210
+ # await telegram_test(True)
211
+ # await qq_test(True)
212
+ await yunhu_test(True)
213
+ while True:
214
+ await asyncio.sleep(1)
215
+ except KeyboardInterrupt:
216
+ sdk.logger.info("收到关闭信号,准备发送关闭通知...")
217
+ await telegram_test(False)
218
+ await qq_test(False)
219
+ await yunhu_test(False)
220
+ except Exception as e:
221
+ sdk.logger.error(f"测试过程中发生错误: {str(e)}")
222
+ raise # 重新抛出异常以便调试
223
+
224
+ if __name__ == "__main__":
225
+ asyncio.run(main())
@@ -48,6 +48,10 @@ await yunhu.Send.To("user", user_id).Text("Hello World!")
48
48
  - `.Board(board_type: str, content: str, **kwargs)`:发布公告看板。
49
49
  - `.Stream(content_type: str, generator: AsyncGenerator)`:发送流式消息。
50
50
 
51
+ Borard board_type 支持以下类型:
52
+ - `local`:指定用户看板
53
+ - `global`:全局看板
54
+
51
55
  #### 按钮参数说明
52
56
  `buttons` 参数是一个嵌套列表,表示按钮的布局和功能。每个按钮对象包含以下字段:
53
57
 
@@ -63,11 +67,44 @@ await yunhu.Send.To("user", user_id).Text("Hello World!")
63
67
  buttons = [
64
68
  [
65
69
  {"text": "复制", "actionType": 2, "value": "xxxx"},
66
- {"text": "点击跳转", "actionType": 1, "url": "http://www.baidu.com"}
70
+ {"text": "点击跳转", "actionType": 1, "url": "http://www.baidu.com"},
71
+ {"text": "汇报事件", "actionType": 3, "value", "xxxxx"}
67
72
  ]
68
73
  ]
69
74
  await yunhu.Send.To("user", user_id).Text("带按钮的消息", buttons=buttons)
70
75
  ```
76
+ > **注意:**
77
+ > - 只有用户点击了**按钮汇报事件**的按钮才会收到推送,**复制***和**跳转URL**均无法收到推送。
78
+
79
+ #### 主要方法返回值示例(Send.To(Type, ID).)
80
+ 1. .Text/.Html/Markdown/.Image/.Video/.File
81
+ ```json
82
+ {
83
+ "code": 1,
84
+ "data": {
85
+ "messageInfo": {
86
+ "msgId": "65a314006db348be97a09eb065985d2d",
87
+ "recvId": "5197892",
88
+ "recvType": "user"
89
+ }
90
+ },
91
+ "msg": "success"
92
+ }
93
+ ```
94
+
95
+ 2. .Batch
96
+ ```json
97
+ {
98
+ "code": 1,
99
+ "data": {
100
+ "successCount": 1,
101
+ "successList": [
102
+ {"msgId": "65a314006db348be97a09eb065985d2d", "recvId": "5197892", "recvType": "user"}
103
+ ]
104
+ },
105
+ "msg": "success"
106
+ }
107
+ ```
71
108
 
72
109
  #### env.py 配置示例
73
110
  ```python
@@ -101,7 +138,6 @@ sdk.env.set("YunhuAdapter", {
101
138
  |bot.unfollowed|机器人取关|
102
139
  |bot.shortcut.menu|快捷菜单|
103
140
  |button.report.inline|按钮汇报|
104
- |bot.setting|机器人设置|
105
141
 
106
142
  每个事件的触发条件以及数据结构如下:
107
143
 
@@ -184,14 +220,14 @@ sdk.env.set("YunhuAdapter", {
184
220
  }
185
221
  }
186
222
  ```
187
- ##### 用户加群事件
223
+ ##### 用户加群/退群事件
188
224
  当用户加入机器人所在的群聊后,将会触发该事件。
189
225
  ```json
190
226
  {
191
227
  "version": "1.0",
192
228
  "header": {
193
229
  "eventId": "d5429cb5e4654fbcaeee9e4adb244741",
194
- "eventType": "group.join",
230
+ "eventType": "group.join", // 或 group.leave
195
231
  "eventTime": 1749442891943
196
232
  },
197
233
  "event": {
@@ -204,33 +240,14 @@ sdk.env.set("YunhuAdapter", {
204
240
  }
205
241
  }
206
242
  ```
207
- ##### 用户退群事件
208
- ```json
209
- {
210
- "version": "1.0",
211
- "header": {
212
- "eventId": "06959e95aaf547078367104ba754c554",
213
- "eventType": "group.leave",
214
- "eventTime": 1749442644367
215
- },
216
- "event": {
217
- "time": 1749442644343,
218
- "chatId": "985140593",
219
- "chatType": "group",
220
- "userId": "3707697",
221
- "nickname": "ShanFishApp",
222
- "avatarUrl": "https://chat-storage1.jwznb.com/defalut-avatars/Ma%20Rainey.png?sign=92fdef22a240a05de78b13afdab5ac51&t=68466e64"
223
- }
224
- }
225
- ```
226
- ##### 用户关注机器人事件
243
+ ##### 用户关注/取关机器人事件
227
244
  当用户在机器人ID或机器人推荐处添加机器人后,将会触发该事件。
228
245
  ```json
229
246
  {
230
247
  "version": "1.0",
231
248
  "header": {
232
249
  "eventId": "3fe280a400f9460daa03a642d1fad39b",
233
- "eventType": "bot.followed",
250
+ "eventType": "bot.followed", // 或 bot.unfollowed
234
251
  "eventTime": 1749443049592
235
252
  },
236
253
  "event": {
@@ -243,26 +260,6 @@ sdk.env.set("YunhuAdapter", {
243
260
  }
244
261
  }
245
262
  ```
246
- ##### 用户取关机器人事件
247
- 当用户点击删除机器人按钮后,将会触发该事件。
248
- ```json
249
- {
250
- "version": "1.0",
251
- "header": {
252
- "eventId": "b4f51386d916464b99782052c030c5b7",
253
- "eventType": "bot.unfollowed",
254
- "eventTime": 1749443036382
255
- },
256
- "event": {
257
- "time": 1749443036373,
258
- "chatId": "49871624",
259
- "chatType": "bot",
260
- "userId": "3707697",
261
- "nickname": "ShanFishApp",
262
- "avatarUrl": "https://chat-storage1.jwznb.com/defalut-avatars/Ma%20Rainey.png?sign=07cf8e9d6ca0875835f9a4a6811b6b4c&t=68466fec"
263
- }
264
- }
265
- ```
266
263
  ##### 按钮汇报事件
267
264
  机器人可以发送带按钮的消息。当用户按下按钮actionType为3(汇报类按钮)的按钮时,将会触发该事件。
268
265
  ```json
@@ -308,35 +305,7 @@ sdk.env.set("YunhuAdapter", {
308
305
  }
309
306
 
310
307
  ```
311
- ##### 机器人设置事件
312
- 当开发者配置了机器人设置项时,在机器人列表处将会出现"设置"按钮。用户设置完成后,将会触发本事件。
313
- ```json
314
- {
315
- "version": "1.0",
316
- "header": {
317
- "eventId": "5ad7e23399ef46a685cead1abe2efa19",
318
- "eventType": "bot.setting",
319
- "eventTime": 1749446299131
320
- },
321
- "event": {
322
- "time": 1749446299128,
323
- "chatId": "49871624",
324
- "chatType": "bot",
325
- "groupId": "985140593",
326
- "groupName": "云湖测试群",
327
- "avatarUrl": "https://chat-img.jwznb.com/77db590d9cee77de13e7c8cf0887b5ba.jpg",
328
- "settingJson": {
329
- "wezzrm": {
330
- "id": "wezzrm",
331
- "type": "switch",
332
- "label": "测试",
333
- "value": true
334
- }
335
- }
336
- }
337
- }
338
308
 
339
- ```
340
309
 
341
310
  #### 注意:`chat` 与 `sender` 的误区
342
311
 
@@ -344,9 +313,9 @@ sdk.env.set("YunhuAdapter", {
344
313
 
345
314
  | 字段 | 含义 |
346
315
  |------|------|
347
- | `data.event.chatType` | 当前聊天类型(`user`/`bot` 或 `group`) |
348
- | `data.event.sender.senderType` | 发送者类型(通常为 `user`) |
349
- | `data.event.sender.senderId` | 发送者唯一 ID |
316
+ | `data.get("event", {}).get("chat", {}).get("chatType", "")` | 当前聊天类型(`user`/`bot` 或 `group`) |
317
+ | `data.get("event", {}).get("sender", {}).get("senderType", "")` | 发送者类型(通常为 `user`) |
318
+ | `data.get("event", {}).get("sender", {}).get("senderId", "")` | 发送者唯一 ID |
350
319
 
351
320
  > **注意:**
352
321
  > - 使用 `chatType` 判断消息是私聊还是群聊
@@ -360,11 +329,11 @@ sdk.env.set("YunhuAdapter", {
360
329
  ```python
361
330
  @sdk.adapter.Yunhu.on("message")
362
331
  async def handle_message(data):
363
- if data.event.chatType == "group":
364
- targetId = data.event.chat.chatId
332
+ if data.get("event", {}).get("chat", {}).get("chatType", "") == "group":
333
+ targetId = data.get("event", {}).get("chat", {}).get("chatId", "")
365
334
  targeType = "group"
366
335
  else:
367
- targetId = data.event.sender.senderId
336
+ targetId = data.get("event", {}).get("sender", {}).get("senderId", "")
368
337
  targeType = "user"
369
338
 
370
339
  await sdk.adapter.Yunhu.Send.To(targeType, targetId).Text("收到你的消息!")
@@ -8,6 +8,24 @@
8
8
  > **贡献日志**
9
9
  > 如需为新版本添加日志,请在对应版本号下补充内容,并注明日期和主要贡献者。
10
10
 
11
+ ## [1.2.6]
12
+ > 这是一个兼容性控制版本
13
+ ### 新增
14
+ - 新增 sdk.logger.get_logs([ModuleName]) 方法,用于获取底层日志内容
15
+ ### 变更
16
+ - 优化部分注解类型以兼容更多Python版本
17
+ - 注解从 py3.10+ 的原生注解改为typings注解 | 已在 py3.8+ 版本中测试通过
18
+
19
+ ---
20
+
21
+ ## [1.2.5]
22
+ ### 修复
23
+ - 现在CLI更新模块时会进行依赖检测并自动补全
24
+ ### 变更
25
+ - 调整Adapter类引用关系(不影响其他模块)
26
+
27
+ ---
28
+
11
29
  ## [1.2.4]
12
30
  ### 修复
13
31
  - 恢复 raiserr 的加载以解决兼容性问题
@@ -80,6 +80,18 @@ sdk.env.set_snapshot_interval(3600) # 设置自动快照间隔(秒)
80
80
  # - 快照适合在重大变更前创建
81
81
  ```
82
82
 
83
+ 须知:
84
+ 模块在env.py中的定义的配置项是硬加载的,每次重启都会被重新加载覆盖原来的key值,不会保留之前的配置;所以谨慎使用您的env.py中的配置项进行任何存储行为!
85
+ 如,一个屏蔽词模块在env.py中存储着全局屏蔽词列表,如果使用env.py中的配置项存储,那么每次重启都会丢失屏蔽词列表,导致屏蔽词失效!
86
+ 这时建议的方法是:使用一个全新的key存储,每次初始化的时候使用类似以下代码获取配置项:
87
+ ```python
88
+ a = env.get("模块在env.py中存储的key", "default_value")
89
+ b = env.get("一个用来存储动态屏蔽词的全新的key", "default_value")
90
+
91
+ # 那么我们使用的屏蔽词列表为:
92
+ self.band_words = a + b
93
+ ```
94
+
83
95
  #### 注册自定义错误类型:
84
96
 
85
97
  ```python