ErisPulse-QQBotAdapter 4.0.2__tar.gz → 5.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_qqbotadapter-5.0.1/ErisPulse_QQBotAdapter.egg-info/PKG-INFO +295 -0
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/ErisPulse_QQBotAdapter.egg-info/SOURCES.txt +2 -0
- erispulse_qqbotadapter-5.0.1/ErisPulse_QQBotAdapter.egg-info/requires.txt +1 -0
- erispulse_qqbotadapter-5.0.1/PKG-INFO +295 -0
- erispulse_qqbotadapter-5.0.1/QQBotAdapter/Converter.py +563 -0
- erispulse_qqbotadapter-5.0.1/QQBotAdapter/Core.py +2042 -0
- erispulse_qqbotadapter-5.0.1/QQBotAdapter/WebSocket.py +281 -0
- erispulse_qqbotadapter-5.0.1/QQBotAdapter/Webhook.py +196 -0
- erispulse_qqbotadapter-5.0.1/QQBotAdapter/__init__.py +3 -0
- erispulse_qqbotadapter-5.0.1/README.md +285 -0
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/pyproject.toml +4 -2
- erispulse_qqbotadapter-4.0.2/ErisPulse_QQBotAdapter.egg-info/PKG-INFO +0 -258
- erispulse_qqbotadapter-4.0.2/PKG-INFO +0 -258
- erispulse_qqbotadapter-4.0.2/QQBotAdapter/Converter.py +0 -278
- erispulse_qqbotadapter-4.0.2/QQBotAdapter/Core.py +0 -523
- erispulse_qqbotadapter-4.0.2/QQBotAdapter/WebSocket.py +0 -284
- erispulse_qqbotadapter-4.0.2/QQBotAdapter/__init__.py +0 -1
- erispulse_qqbotadapter-4.0.2/README.md +0 -249
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/ErisPulse_QQBotAdapter.egg-info/dependency_links.txt +0 -0
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/ErisPulse_QQBotAdapter.egg-info/entry_points.txt +0 -0
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/ErisPulse_QQBotAdapter.egg-info/top_level.txt +0 -0
- {erispulse_qqbotadapter-4.0.2 → erispulse_qqbotadapter-5.0.1}/setup.cfg +0 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ErisPulse-QQBotAdapter
|
|
3
|
+
Version: 5.0.1
|
|
4
|
+
Summary: ErisPulse的QQ官方机器人适配模块
|
|
5
|
+
Author-email: wsu2059 <wsu2059@qq.com>
|
|
6
|
+
Project-URL: homepage, https://github.com/ErisPulse/ErisPulse-QQBotAdapter
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: cryptography>=41.0
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
|
|
13
|
+
<img src=".github/assets/ErisPulseLogo.png" width="180" alt="ErisPulse QQBotAdapter" />
|
|
14
|
+
|
|
15
|
+
# ErisPulse QQBotAdapter
|
|
16
|
+
|
|
17
|
+
**QQ 官方机器人平台适配器 —— 群聊 / 私聊 / 频道一站接入。**
|
|
18
|
+
|
|
19
|
+
基于 ErisPulse 架构的 QQ 官方机器人协议适配器,支持 WebSocket / Webhook 双接入模式与多账户并行,整合群聊、私聊、频道等场景,提供 OneBot12 标准事件、标准Api动作与请求操作接口。
|
|
20
|
+
|
|
21
|
+
<p>
|
|
22
|
+
<a href="https://pypi.org/project/ErisPulse-QQBotAdapter/"><img src="https://img.shields.io/pypi/v/ErisPulse-QQBotAdapter?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"></a>
|
|
23
|
+
<a href="https://pypi.org/project/ErisPulse-QQBotAdapter/"><img src="https://img.shields.io/badge/Python-3.10+-FFD43B?style=for-the-badge&logo=python&logoColor=blue" alt="Python"></a>
|
|
24
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge" alt="License"></a>
|
|
25
|
+
<a href="https://github.com/ErisPulse/ErisPulse-QQBotAdapter"><img src="https://img.shields.io/github/stars/ErisPulse/ErisPulse-QQBotAdapter?style=for-the-badge&logo=github&color=brightgreen" alt="Stars"></a>
|
|
26
|
+
<a href="https://pepy.tech/project/ErisPulse-QQBotAdapter"><img src="https://img.shields.io/pepy/dt/ErisPulse-QQBotAdapter?style=for-the-badge&color=blue" alt="Downloads"></a>
|
|
27
|
+
<a href="https://github.com/ErisPulse/ErisPulse"><img src="https://img.shields.io/badge/Powered_by-ErisPulse-FF6B9D?style=for-the-badge&logo=bookstack&logoColor=white" alt="ErisPulse"></a>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 简介
|
|
35
|
+
|
|
36
|
+
QQBotAdapter 是基于 [ErisPulse](https://github.com/ErisPulse/ErisPulse/) 架构的QQ官方机器人协议适配器,整合群聊、私聊、频道等多种场景的功能模块,提供统一的事件处理和消息操作接口。
|
|
37
|
+
|
|
38
|
+
**v5.0 亮点:**
|
|
39
|
+
- 🌐 对齐官方最新 API:统一域名 `api.bot.qq.com`、新增 `X-Union-Appid` 头、sandbox 废弃
|
|
40
|
+
- 🔌 **双接入模式**:WebSocket 长连接 / Webhook HTTP 回调(Ed25519 验签)
|
|
41
|
+
- 👥 **多账户并行**:每账户独立连接与 token 管理,`Using()` 灵活切换
|
|
42
|
+
- 📡 **OneBot12 标准Api动作**:`Api.get_group_info()` / `Api.delete_message()` 等跨平台统一调用
|
|
43
|
+
- 🤝 **请求操作**:入群申请(GROUP_JOIN_REQUEST)标准化 `accept()/reject()` 审批
|
|
44
|
+
- 🚀 **流式消息**:单聊流式输出(stream_messages)
|
|
45
|
+
- 📦 全量平台API方法族:群管理、菜单面板、日程、帖子、表态、分片上传等
|
|
46
|
+
|
|
47
|
+
## 平台原生事件映射关系
|
|
48
|
+
|
|
49
|
+
| 官方事件命名 | Adapter事件命名 |
|
|
50
|
+
|--------------|----------------|
|
|
51
|
+
| C2C_MESSAGE_CREATE | private_message |
|
|
52
|
+
| GROUP_AT_MESSAGE_CREATE | group_message |
|
|
53
|
+
| GROUP_MESSAGE_CREATE | group_message(非@群消息,需后台开通接收全部消息权限) |
|
|
54
|
+
| AT_MESSAGE_CREATE | channel_message |
|
|
55
|
+
| MESSAGE_CREATE | channel_message |
|
|
56
|
+
| DIRECT_MESSAGE_CREATE | direct_message |
|
|
57
|
+
| FRIEND_ADD | friend_add |
|
|
58
|
+
| FRIEND_DEL | friend_del |
|
|
59
|
+
| GROUP_ADD_ROBOT | group_add |
|
|
60
|
+
| GROUP_DEL_ROBOT | group_del |
|
|
61
|
+
| GROUP_MSG_REJECT | group_block |
|
|
62
|
+
| GROUP_MSG_RECEIVE | group_allow |
|
|
63
|
+
| C2C_MSG_REJECT | private_block |
|
|
64
|
+
| C2C_MSG_RECEIVE | private_allow |
|
|
65
|
+
| GROUP_MEMBER_ADD | group_member_add(v5新增) |
|
|
66
|
+
| GROUP_MEMBER_REMOVE | group_member_remove(v5新增) |
|
|
67
|
+
| GROUP_JOIN_REQUEST | group_join_request(v5新增,request事件) |
|
|
68
|
+
| GUILD_MEMBER_ADD | guild_member_add |
|
|
69
|
+
| GUILD_MEMBER_UPDATE | guild_member_update |
|
|
70
|
+
| GUILD_MEMBER_REMOVE | guild_member_remove |
|
|
71
|
+
| INTERACTION_CREATE | interaction |
|
|
72
|
+
| MESSAGE_AUDIT_PASS | audit_pass |
|
|
73
|
+
| MESSAGE_AUDIT_REJECT | audit_reject |
|
|
74
|
+
|
|
75
|
+
这仅仅在 `sdk.adapter.qqbot.on()` 的时候生效,你完全可以使用标准OneBot12事件(`sdk.adapter.on`)来获取信息。
|
|
76
|
+
|
|
77
|
+
### OneBot12标准事件类型
|
|
78
|
+
|
|
79
|
+
| 事件类型 | detail_type | 说明 |
|
|
80
|
+
|----------|-------------|------|
|
|
81
|
+
| 消息事件(私聊) | private | 用户发送的私聊消息 |
|
|
82
|
+
| 消息事件(群聊) | group | 群内消息(@或非@) |
|
|
83
|
+
| 消息事件(频道) | channel | 频道内消息 |
|
|
84
|
+
| 请求事件(入群申请) | group | **type=request**,含 request_id,支持审批 |
|
|
85
|
+
| 好友增加/删除 | friend_add / friend_del | 用户添加/删除机器人好友 |
|
|
86
|
+
| 群增加/减少 | group_increase / group_decrease | 群添加/移除机器人 |
|
|
87
|
+
| 群消息屏蔽/允许 | group_block / group_allow | 群拒绝/允许机器人消息 |
|
|
88
|
+
| 私聊屏蔽/允许 | private_block / private_allow | 用户拒绝/允许机器人私聊 |
|
|
89
|
+
| 群成员增加/减少 | group_member_increase / group_member_decrease | **群**成员变更(v5新增) |
|
|
90
|
+
| 频道成员增加/更新/减少 | guild_member_increase / guild_member_update / guild_member_decrease | **频道**成员变更 |
|
|
91
|
+
| 频道服务器创建/更新/删除 | guild_create / guild_update / guild_delete | 频道服务器变更 |
|
|
92
|
+
| 子频道创建/更新/删除 | channel_create / channel_update / channel_delete | 子频道变更 |
|
|
93
|
+
| 音频子频道进出 | qqbot_channel_enter / qqbot_channel_exit | 用户进入/离开音频直播子频道(v5新增) |
|
|
94
|
+
| QQBot交互事件 | qqbot_interaction | 按钮点击等交互 |
|
|
95
|
+
| QQBot审核通过/拒绝 | qqbot_audit_pass / qqbot_audit_reject | 消息审核结果 |
|
|
96
|
+
| QQBot表情回应添加/移除 | qqbot_reaction_add / qqbot_reaction_remove | 消息表情回应 |
|
|
97
|
+
| QQBot音频开始/结束 | qqbot_audio_start / qqbot_audio_finish | 音频播放 |
|
|
98
|
+
| QQBot消息删除 | qqbot_message_delete | 消息被删除 |
|
|
99
|
+
| QQBot论坛事件 | qqbot_forum_* | 论坛主帖/帖子/回复/审核(私域) |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 消息发送示例
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from ErisPulse import sdk
|
|
107
|
+
qqbot = sdk.adapter.get("qqbot")
|
|
108
|
+
|
|
109
|
+
# 发送文本消息
|
|
110
|
+
await qqbot.Send.To("user", user_openid).Text("Hello World!")
|
|
111
|
+
|
|
112
|
+
# 发送带@的消息(群/私聊自动使用 qqbot-at-user 格式)
|
|
113
|
+
await qqbot.Send.To("group", group_openid).At("member_openid").Text("@你")
|
|
114
|
+
await qqbot.Send.To("group", group_openid).AtAll().Text("公告通知")
|
|
115
|
+
|
|
116
|
+
# 发送回复消息(被动回复)
|
|
117
|
+
await qqbot.Send.To("group", group_openid).Reply("msg_id").Text("回复内容")
|
|
118
|
+
|
|
119
|
+
# 发送图片(URL / 本地路径 / 二进制三态;超过5MB自动分片上传)
|
|
120
|
+
await qqbot.Send.To("group", group_openid).Image("https://example.com/image.png")
|
|
121
|
+
|
|
122
|
+
# 发送 Markdown(原生 / 模板)
|
|
123
|
+
await qqbot.Send.To("group", group_openid).Markdown("# 标题\n- 列表项")
|
|
124
|
+
await qqbot.Send.To("user", user_openid).Markdown(template_id=1, kv=[{"key": "title", "value": "通知"}])
|
|
125
|
+
|
|
126
|
+
# 发送 Ark 模板消息
|
|
127
|
+
await qqbot.Send.To("user", user_openid).Ark(template_id=1, kv=[{"key": "title", "value": "标题"}])
|
|
128
|
+
|
|
129
|
+
# 发送 Embed 消息(频道)
|
|
130
|
+
await qqbot.Send.To("channel", channel_id).Embed({"title": "标题", "content": "内容"})
|
|
131
|
+
|
|
132
|
+
# 发送带键盘的消息(自动置为 markdown 类型并附带 bot_appid)
|
|
133
|
+
keyboard = {"content": {"rows": [[{"label": "确认", "type": 2, "data": "confirm"}]]}}
|
|
134
|
+
await qqbot.Send.To("group", group_openid).Keyboard(keyboard).Text("请选择")
|
|
135
|
+
|
|
136
|
+
# 流式消息(单聊)
|
|
137
|
+
await qqbot.Send.To("user", user_openid).Stream("回答内容")
|
|
138
|
+
|
|
139
|
+
# 多账户
|
|
140
|
+
await qqbot.Send.Using("account2").To("group", group_openid).Text("来自第二个机器人")
|
|
141
|
+
|
|
142
|
+
# 使用 Raw_ob12 发送 OneBot12 格式消息
|
|
143
|
+
message = [
|
|
144
|
+
{"type": "text", "data": {"text": "第一行"}},
|
|
145
|
+
{"type": "image", "data": {"file": "https://example.com/img.jpg"}},
|
|
146
|
+
]
|
|
147
|
+
await qqbot.Send.To("group", group_openid).Raw_ob12(message)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 标准Api动作与请求操作(v5 新增)
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# OneBot12 标准Api动作(跨平台统一调用)
|
|
156
|
+
result = await qqbot.Api.get_self_info() # 机器人信息
|
|
157
|
+
result = await qqbot.Api.get_group_info(group_openid) # 群信息
|
|
158
|
+
result = await qqbot.Api.get_group_member_list(group_openid) # 群成员列表(自动分页)
|
|
159
|
+
result = await qqbot.Api.get_guild_list() # 频道列表
|
|
160
|
+
result = await qqbot.Api.get_channel_list(guild_id) # 子频道列表
|
|
161
|
+
await qqbot.Api.delete_message(message_id) # 撤回消息(自动路由端点)
|
|
162
|
+
result = await qqbot.Api.get_status() # 运行状态
|
|
163
|
+
|
|
164
|
+
# 请求操作:入群申请审批
|
|
165
|
+
from ErisPulse.Core.Event import request as request_event
|
|
166
|
+
|
|
167
|
+
@request_event.on_request()
|
|
168
|
+
async def handle_join(event):
|
|
169
|
+
if event.get("platform") == "qqbot":
|
|
170
|
+
await event.approve() # 同意
|
|
171
|
+
# await event.reject(comment="理由") # 拒绝
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### 配置说明
|
|
177
|
+
|
|
178
|
+
首次运行会自动生成默认配置。
|
|
179
|
+
|
|
180
|
+
```toml
|
|
181
|
+
# config.toml
|
|
182
|
+
[QQBot_Adapter]
|
|
183
|
+
intents = "[0, 9, 12, 25, 26, 27]" # 订阅的事件 intents(JSON数组,支持事件名)
|
|
184
|
+
|
|
185
|
+
[QQBot_Adapter.accounts.default]
|
|
186
|
+
appid = "YOUR_APPID" # QQ机器人应用ID(必填)
|
|
187
|
+
secret = "YOUR_CLIENT_SECRET" # QQ机器人客户端密钥(必填)
|
|
188
|
+
mode = "websocket" # websocket / webhook
|
|
189
|
+
bot_id = "" # 留空自动获取(可手动填写用于 Using() 定位)
|
|
190
|
+
gateway_url = "" # WebSocket网关(留空动态获取)
|
|
191
|
+
api_base_url = "https://api.bot.qq.com"
|
|
192
|
+
webhook_path = "/webhook" # mode=webhook 时生效
|
|
193
|
+
enabled = true
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**配置项说明:**
|
|
197
|
+
- `appid` / `secret`:从 [QQ开放平台](https://q.qq.com/) 获取(必填)
|
|
198
|
+
- `mode`:事件接收方式,`websocket`(默认,长连接)或 `webhook`(HTTP 回调 + Ed25519 验签)
|
|
199
|
+
- `intents`:事件订阅,支持位序号或事件名,常用:`0` 频道 / `9,30` 频道消息 / `12` 频道私信 / `24` 群成员 / `25` 群私聊 / `26` 交互 / `27` 审核
|
|
200
|
+
- `gateway_url`:WebSocket 网关地址,留空时通过 `/gateway/bot` 动态获取(支持代理/私有部署)
|
|
201
|
+
- `api_base_url`:OpenAPI 根地址,默认 `https://api.bot.qq.com`
|
|
202
|
+
- 多账户:在 `accounts` 下添加多个账户即可并行接入(可混合 websocket/webhook 模式)
|
|
203
|
+
|
|
204
|
+
> ⚠️ **v5 破坏性变更**:官方已统一使用 `api.bot.qq.com`,`sandbox` 配置废弃(自动迁移忽略);旧版扁平配置自动迁移到 `accounts.default`。
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## QQBot平台特有功能
|
|
209
|
+
|
|
210
|
+
请参考 [QQBot平台特性文档](platform-features.md) 了解QQBot平台的特有功能,包括openid体系、频道系统、群管理API、菜单面板、流式消息、消息审核、交互事件、Webhook接入等内容。
|
|
211
|
+
|
|
212
|
+
详细的事件转换对照请参考 [转换对照文档](CoverToOnebot12.md)。
|
|
213
|
+
|
|
214
|
+
## 事件监听示例
|
|
215
|
+
|
|
216
|
+
### 使用 Event 模块(推荐)
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from ErisPulse.Core.Event import message, notice, request
|
|
220
|
+
|
|
221
|
+
# @消息(群内@机器人触发,适配器自动注入机器人 mention 段)
|
|
222
|
+
@message.on_at_message()
|
|
223
|
+
async def handle_at(event):
|
|
224
|
+
if event["platform"] == "qqbot":
|
|
225
|
+
text = event.get_text()
|
|
226
|
+
if text == "签到":
|
|
227
|
+
await event.reply("已签到")
|
|
228
|
+
|
|
229
|
+
@message.on_message()
|
|
230
|
+
async def handle_message(event):
|
|
231
|
+
if event["platform"] == "qqbot":
|
|
232
|
+
detail_type = event["detail_type"]
|
|
233
|
+
if detail_type == "private":
|
|
234
|
+
pass # 处理私聊消息
|
|
235
|
+
elif detail_type == "group":
|
|
236
|
+
pass # 处理群消息
|
|
237
|
+
elif detail_type == "channel":
|
|
238
|
+
pass # 处理频道消息
|
|
239
|
+
|
|
240
|
+
@notice.on_notice()
|
|
241
|
+
async def handle_notice(event):
|
|
242
|
+
if event["platform"] == "qqbot":
|
|
243
|
+
detail_type = event["detail_type"]
|
|
244
|
+
if detail_type == "qqbot_interaction":
|
|
245
|
+
button_id = event.get("qqbot_button_id", "")
|
|
246
|
+
|
|
247
|
+
@request.on_request()
|
|
248
|
+
async def handle_request(event):
|
|
249
|
+
if event["platform"] == "qqbot":
|
|
250
|
+
await event.approve() # 自动审批入群申请
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 使用平台原生事件
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
qqbot = sdk.adapter.get("qqbot")
|
|
257
|
+
|
|
258
|
+
@qqbot.on("C2C_MESSAGE_CREATE")
|
|
259
|
+
async def handle_private_message(data):
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
@qqbot.on("GROUP_JOIN_REQUEST")
|
|
263
|
+
async def handle_join_request(data):
|
|
264
|
+
pass
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 使用 OneBot12 标准事件
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
@sdk.adapter.on("message")
|
|
271
|
+
async def handle_message(event):
|
|
272
|
+
if event["platform"] == "qqbot":
|
|
273
|
+
bot_id = event["self"]["user_id"]
|
|
274
|
+
print(f"消息来自Bot: {bot_id}")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 注意事项:
|
|
278
|
+
|
|
279
|
+
1. 确保在调用 `startup()` 前完成所有处理器的注册
|
|
280
|
+
2. QQBot使用 openid 体系而非QQ号,用户和群的标识均为 openid 字符串
|
|
281
|
+
3. 群消息默认仅在用户@机器人时才会收到(`GROUP_AT_MESSAGE_CREATE`);如需接收全部群消息,请在 [QQ开放平台](https://q.qq.com/) 机器人管理后台开启权限(无API),非@消息将以 `GROUP_MESSAGE_CREATE` 推送
|
|
282
|
+
4. **@检测已支持**:适配器自动解析 `<@openid>`/`<qqbot-at-user>` 两种标记并注入/归一化机器人 mention 段,`on_at_message()`/`event.is_at_message()` 可直接使用;同时自动学习机器人在各群的 openid,"接收全部群消息"模式下 `GROUP_MESSAGE_CREATE` 中的@消息也能识别
|
|
283
|
+
5. 发送的消息可能需要经过审核,通过 `qqbot_audit_pass`/`qqbot_audit_reject` 事件通知结果
|
|
284
|
+
6. 媒体文件(图片、视频等)会上传后通过 file_info 发送,支持URL、本地路径和二进制数据;超过5MB自动分片上传
|
|
285
|
+
7. 程序退出时请调用 `shutdown()` 确保资源释放
|
|
286
|
+
8. access_token 有效期为7200秒,适配器提前45秒自动刷新
|
|
287
|
+
9. 群管理部分API(成员列表、入群审批等)仅对白名单机器人开放
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 参考链接
|
|
292
|
+
|
|
293
|
+
- [ErisPulse 主库](https://github.com/ErisPulse/ErisPulse/)
|
|
294
|
+
- [QQBot 官方文档](https://bot.q.qq.com/wiki/)
|
|
295
|
+
- [模块开发指南](https://www.erisdev.com/#docs/developer-guide/README.md)
|
|
@@ -4,8 +4,10 @@ ErisPulse_QQBotAdapter.egg-info/PKG-INFO
|
|
|
4
4
|
ErisPulse_QQBotAdapter.egg-info/SOURCES.txt
|
|
5
5
|
ErisPulse_QQBotAdapter.egg-info/dependency_links.txt
|
|
6
6
|
ErisPulse_QQBotAdapter.egg-info/entry_points.txt
|
|
7
|
+
ErisPulse_QQBotAdapter.egg-info/requires.txt
|
|
7
8
|
ErisPulse_QQBotAdapter.egg-info/top_level.txt
|
|
8
9
|
QQBotAdapter/Converter.py
|
|
9
10
|
QQBotAdapter/Core.py
|
|
10
11
|
QQBotAdapter/WebSocket.py
|
|
12
|
+
QQBotAdapter/Webhook.py
|
|
11
13
|
QQBotAdapter/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cryptography>=41.0
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ErisPulse-QQBotAdapter
|
|
3
|
+
Version: 5.0.1
|
|
4
|
+
Summary: ErisPulse的QQ官方机器人适配模块
|
|
5
|
+
Author-email: wsu2059 <wsu2059@qq.com>
|
|
6
|
+
Project-URL: homepage, https://github.com/ErisPulse/ErisPulse-QQBotAdapter
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
Requires-Dist: cryptography>=41.0
|
|
10
|
+
|
|
11
|
+
<div align="center">
|
|
12
|
+
|
|
13
|
+
<img src=".github/assets/ErisPulseLogo.png" width="180" alt="ErisPulse QQBotAdapter" />
|
|
14
|
+
|
|
15
|
+
# ErisPulse QQBotAdapter
|
|
16
|
+
|
|
17
|
+
**QQ 官方机器人平台适配器 —— 群聊 / 私聊 / 频道一站接入。**
|
|
18
|
+
|
|
19
|
+
基于 ErisPulse 架构的 QQ 官方机器人协议适配器,支持 WebSocket / Webhook 双接入模式与多账户并行,整合群聊、私聊、频道等场景,提供 OneBot12 标准事件、标准Api动作与请求操作接口。
|
|
20
|
+
|
|
21
|
+
<p>
|
|
22
|
+
<a href="https://pypi.org/project/ErisPulse-QQBotAdapter/"><img src="https://img.shields.io/pypi/v/ErisPulse-QQBotAdapter?style=for-the-badge&logo=pypi&logoColor=white" alt="PyPI"></a>
|
|
23
|
+
<a href="https://pypi.org/project/ErisPulse-QQBotAdapter/"><img src="https://img.shields.io/badge/Python-3.10+-FFD43B?style=for-the-badge&logo=python&logoColor=blue" alt="Python"></a>
|
|
24
|
+
<a href="./LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue?style=for-the-badge" alt="License"></a>
|
|
25
|
+
<a href="https://github.com/ErisPulse/ErisPulse-QQBotAdapter"><img src="https://img.shields.io/github/stars/ErisPulse/ErisPulse-QQBotAdapter?style=for-the-badge&logo=github&color=brightgreen" alt="Stars"></a>
|
|
26
|
+
<a href="https://pepy.tech/project/ErisPulse-QQBotAdapter"><img src="https://img.shields.io/pepy/dt/ErisPulse-QQBotAdapter?style=for-the-badge&color=blue" alt="Downloads"></a>
|
|
27
|
+
<a href="https://github.com/ErisPulse/ErisPulse"><img src="https://img.shields.io/badge/Powered_by-ErisPulse-FF6B9D?style=for-the-badge&logo=bookstack&logoColor=white" alt="ErisPulse"></a>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## 简介
|
|
35
|
+
|
|
36
|
+
QQBotAdapter 是基于 [ErisPulse](https://github.com/ErisPulse/ErisPulse/) 架构的QQ官方机器人协议适配器,整合群聊、私聊、频道等多种场景的功能模块,提供统一的事件处理和消息操作接口。
|
|
37
|
+
|
|
38
|
+
**v5.0 亮点:**
|
|
39
|
+
- 🌐 对齐官方最新 API:统一域名 `api.bot.qq.com`、新增 `X-Union-Appid` 头、sandbox 废弃
|
|
40
|
+
- 🔌 **双接入模式**:WebSocket 长连接 / Webhook HTTP 回调(Ed25519 验签)
|
|
41
|
+
- 👥 **多账户并行**:每账户独立连接与 token 管理,`Using()` 灵活切换
|
|
42
|
+
- 📡 **OneBot12 标准Api动作**:`Api.get_group_info()` / `Api.delete_message()` 等跨平台统一调用
|
|
43
|
+
- 🤝 **请求操作**:入群申请(GROUP_JOIN_REQUEST)标准化 `accept()/reject()` 审批
|
|
44
|
+
- 🚀 **流式消息**:单聊流式输出(stream_messages)
|
|
45
|
+
- 📦 全量平台API方法族:群管理、菜单面板、日程、帖子、表态、分片上传等
|
|
46
|
+
|
|
47
|
+
## 平台原生事件映射关系
|
|
48
|
+
|
|
49
|
+
| 官方事件命名 | Adapter事件命名 |
|
|
50
|
+
|--------------|----------------|
|
|
51
|
+
| C2C_MESSAGE_CREATE | private_message |
|
|
52
|
+
| GROUP_AT_MESSAGE_CREATE | group_message |
|
|
53
|
+
| GROUP_MESSAGE_CREATE | group_message(非@群消息,需后台开通接收全部消息权限) |
|
|
54
|
+
| AT_MESSAGE_CREATE | channel_message |
|
|
55
|
+
| MESSAGE_CREATE | channel_message |
|
|
56
|
+
| DIRECT_MESSAGE_CREATE | direct_message |
|
|
57
|
+
| FRIEND_ADD | friend_add |
|
|
58
|
+
| FRIEND_DEL | friend_del |
|
|
59
|
+
| GROUP_ADD_ROBOT | group_add |
|
|
60
|
+
| GROUP_DEL_ROBOT | group_del |
|
|
61
|
+
| GROUP_MSG_REJECT | group_block |
|
|
62
|
+
| GROUP_MSG_RECEIVE | group_allow |
|
|
63
|
+
| C2C_MSG_REJECT | private_block |
|
|
64
|
+
| C2C_MSG_RECEIVE | private_allow |
|
|
65
|
+
| GROUP_MEMBER_ADD | group_member_add(v5新增) |
|
|
66
|
+
| GROUP_MEMBER_REMOVE | group_member_remove(v5新增) |
|
|
67
|
+
| GROUP_JOIN_REQUEST | group_join_request(v5新增,request事件) |
|
|
68
|
+
| GUILD_MEMBER_ADD | guild_member_add |
|
|
69
|
+
| GUILD_MEMBER_UPDATE | guild_member_update |
|
|
70
|
+
| GUILD_MEMBER_REMOVE | guild_member_remove |
|
|
71
|
+
| INTERACTION_CREATE | interaction |
|
|
72
|
+
| MESSAGE_AUDIT_PASS | audit_pass |
|
|
73
|
+
| MESSAGE_AUDIT_REJECT | audit_reject |
|
|
74
|
+
|
|
75
|
+
这仅仅在 `sdk.adapter.qqbot.on()` 的时候生效,你完全可以使用标准OneBot12事件(`sdk.adapter.on`)来获取信息。
|
|
76
|
+
|
|
77
|
+
### OneBot12标准事件类型
|
|
78
|
+
|
|
79
|
+
| 事件类型 | detail_type | 说明 |
|
|
80
|
+
|----------|-------------|------|
|
|
81
|
+
| 消息事件(私聊) | private | 用户发送的私聊消息 |
|
|
82
|
+
| 消息事件(群聊) | group | 群内消息(@或非@) |
|
|
83
|
+
| 消息事件(频道) | channel | 频道内消息 |
|
|
84
|
+
| 请求事件(入群申请) | group | **type=request**,含 request_id,支持审批 |
|
|
85
|
+
| 好友增加/删除 | friend_add / friend_del | 用户添加/删除机器人好友 |
|
|
86
|
+
| 群增加/减少 | group_increase / group_decrease | 群添加/移除机器人 |
|
|
87
|
+
| 群消息屏蔽/允许 | group_block / group_allow | 群拒绝/允许机器人消息 |
|
|
88
|
+
| 私聊屏蔽/允许 | private_block / private_allow | 用户拒绝/允许机器人私聊 |
|
|
89
|
+
| 群成员增加/减少 | group_member_increase / group_member_decrease | **群**成员变更(v5新增) |
|
|
90
|
+
| 频道成员增加/更新/减少 | guild_member_increase / guild_member_update / guild_member_decrease | **频道**成员变更 |
|
|
91
|
+
| 频道服务器创建/更新/删除 | guild_create / guild_update / guild_delete | 频道服务器变更 |
|
|
92
|
+
| 子频道创建/更新/删除 | channel_create / channel_update / channel_delete | 子频道变更 |
|
|
93
|
+
| 音频子频道进出 | qqbot_channel_enter / qqbot_channel_exit | 用户进入/离开音频直播子频道(v5新增) |
|
|
94
|
+
| QQBot交互事件 | qqbot_interaction | 按钮点击等交互 |
|
|
95
|
+
| QQBot审核通过/拒绝 | qqbot_audit_pass / qqbot_audit_reject | 消息审核结果 |
|
|
96
|
+
| QQBot表情回应添加/移除 | qqbot_reaction_add / qqbot_reaction_remove | 消息表情回应 |
|
|
97
|
+
| QQBot音频开始/结束 | qqbot_audio_start / qqbot_audio_finish | 音频播放 |
|
|
98
|
+
| QQBot消息删除 | qqbot_message_delete | 消息被删除 |
|
|
99
|
+
| QQBot论坛事件 | qqbot_forum_* | 论坛主帖/帖子/回复/审核(私域) |
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 消息发送示例
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from ErisPulse import sdk
|
|
107
|
+
qqbot = sdk.adapter.get("qqbot")
|
|
108
|
+
|
|
109
|
+
# 发送文本消息
|
|
110
|
+
await qqbot.Send.To("user", user_openid).Text("Hello World!")
|
|
111
|
+
|
|
112
|
+
# 发送带@的消息(群/私聊自动使用 qqbot-at-user 格式)
|
|
113
|
+
await qqbot.Send.To("group", group_openid).At("member_openid").Text("@你")
|
|
114
|
+
await qqbot.Send.To("group", group_openid).AtAll().Text("公告通知")
|
|
115
|
+
|
|
116
|
+
# 发送回复消息(被动回复)
|
|
117
|
+
await qqbot.Send.To("group", group_openid).Reply("msg_id").Text("回复内容")
|
|
118
|
+
|
|
119
|
+
# 发送图片(URL / 本地路径 / 二进制三态;超过5MB自动分片上传)
|
|
120
|
+
await qqbot.Send.To("group", group_openid).Image("https://example.com/image.png")
|
|
121
|
+
|
|
122
|
+
# 发送 Markdown(原生 / 模板)
|
|
123
|
+
await qqbot.Send.To("group", group_openid).Markdown("# 标题\n- 列表项")
|
|
124
|
+
await qqbot.Send.To("user", user_openid).Markdown(template_id=1, kv=[{"key": "title", "value": "通知"}])
|
|
125
|
+
|
|
126
|
+
# 发送 Ark 模板消息
|
|
127
|
+
await qqbot.Send.To("user", user_openid).Ark(template_id=1, kv=[{"key": "title", "value": "标题"}])
|
|
128
|
+
|
|
129
|
+
# 发送 Embed 消息(频道)
|
|
130
|
+
await qqbot.Send.To("channel", channel_id).Embed({"title": "标题", "content": "内容"})
|
|
131
|
+
|
|
132
|
+
# 发送带键盘的消息(自动置为 markdown 类型并附带 bot_appid)
|
|
133
|
+
keyboard = {"content": {"rows": [[{"label": "确认", "type": 2, "data": "confirm"}]]}}
|
|
134
|
+
await qqbot.Send.To("group", group_openid).Keyboard(keyboard).Text("请选择")
|
|
135
|
+
|
|
136
|
+
# 流式消息(单聊)
|
|
137
|
+
await qqbot.Send.To("user", user_openid).Stream("回答内容")
|
|
138
|
+
|
|
139
|
+
# 多账户
|
|
140
|
+
await qqbot.Send.Using("account2").To("group", group_openid).Text("来自第二个机器人")
|
|
141
|
+
|
|
142
|
+
# 使用 Raw_ob12 发送 OneBot12 格式消息
|
|
143
|
+
message = [
|
|
144
|
+
{"type": "text", "data": {"text": "第一行"}},
|
|
145
|
+
{"type": "image", "data": {"file": "https://example.com/img.jpg"}},
|
|
146
|
+
]
|
|
147
|
+
await qqbot.Send.To("group", group_openid).Raw_ob12(message)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## 标准Api动作与请求操作(v5 新增)
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
# OneBot12 标准Api动作(跨平台统一调用)
|
|
156
|
+
result = await qqbot.Api.get_self_info() # 机器人信息
|
|
157
|
+
result = await qqbot.Api.get_group_info(group_openid) # 群信息
|
|
158
|
+
result = await qqbot.Api.get_group_member_list(group_openid) # 群成员列表(自动分页)
|
|
159
|
+
result = await qqbot.Api.get_guild_list() # 频道列表
|
|
160
|
+
result = await qqbot.Api.get_channel_list(guild_id) # 子频道列表
|
|
161
|
+
await qqbot.Api.delete_message(message_id) # 撤回消息(自动路由端点)
|
|
162
|
+
result = await qqbot.Api.get_status() # 运行状态
|
|
163
|
+
|
|
164
|
+
# 请求操作:入群申请审批
|
|
165
|
+
from ErisPulse.Core.Event import request as request_event
|
|
166
|
+
|
|
167
|
+
@request_event.on_request()
|
|
168
|
+
async def handle_join(event):
|
|
169
|
+
if event.get("platform") == "qqbot":
|
|
170
|
+
await event.approve() # 同意
|
|
171
|
+
# await event.reject(comment="理由") # 拒绝
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### 配置说明
|
|
177
|
+
|
|
178
|
+
首次运行会自动生成默认配置。
|
|
179
|
+
|
|
180
|
+
```toml
|
|
181
|
+
# config.toml
|
|
182
|
+
[QQBot_Adapter]
|
|
183
|
+
intents = "[0, 9, 12, 25, 26, 27]" # 订阅的事件 intents(JSON数组,支持事件名)
|
|
184
|
+
|
|
185
|
+
[QQBot_Adapter.accounts.default]
|
|
186
|
+
appid = "YOUR_APPID" # QQ机器人应用ID(必填)
|
|
187
|
+
secret = "YOUR_CLIENT_SECRET" # QQ机器人客户端密钥(必填)
|
|
188
|
+
mode = "websocket" # websocket / webhook
|
|
189
|
+
bot_id = "" # 留空自动获取(可手动填写用于 Using() 定位)
|
|
190
|
+
gateway_url = "" # WebSocket网关(留空动态获取)
|
|
191
|
+
api_base_url = "https://api.bot.qq.com"
|
|
192
|
+
webhook_path = "/webhook" # mode=webhook 时生效
|
|
193
|
+
enabled = true
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**配置项说明:**
|
|
197
|
+
- `appid` / `secret`:从 [QQ开放平台](https://q.qq.com/) 获取(必填)
|
|
198
|
+
- `mode`:事件接收方式,`websocket`(默认,长连接)或 `webhook`(HTTP 回调 + Ed25519 验签)
|
|
199
|
+
- `intents`:事件订阅,支持位序号或事件名,常用:`0` 频道 / `9,30` 频道消息 / `12` 频道私信 / `24` 群成员 / `25` 群私聊 / `26` 交互 / `27` 审核
|
|
200
|
+
- `gateway_url`:WebSocket 网关地址,留空时通过 `/gateway/bot` 动态获取(支持代理/私有部署)
|
|
201
|
+
- `api_base_url`:OpenAPI 根地址,默认 `https://api.bot.qq.com`
|
|
202
|
+
- 多账户:在 `accounts` 下添加多个账户即可并行接入(可混合 websocket/webhook 模式)
|
|
203
|
+
|
|
204
|
+
> ⚠️ **v5 破坏性变更**:官方已统一使用 `api.bot.qq.com`,`sandbox` 配置废弃(自动迁移忽略);旧版扁平配置自动迁移到 `accounts.default`。
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## QQBot平台特有功能
|
|
209
|
+
|
|
210
|
+
请参考 [QQBot平台特性文档](platform-features.md) 了解QQBot平台的特有功能,包括openid体系、频道系统、群管理API、菜单面板、流式消息、消息审核、交互事件、Webhook接入等内容。
|
|
211
|
+
|
|
212
|
+
详细的事件转换对照请参考 [转换对照文档](CoverToOnebot12.md)。
|
|
213
|
+
|
|
214
|
+
## 事件监听示例
|
|
215
|
+
|
|
216
|
+
### 使用 Event 模块(推荐)
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from ErisPulse.Core.Event import message, notice, request
|
|
220
|
+
|
|
221
|
+
# @消息(群内@机器人触发,适配器自动注入机器人 mention 段)
|
|
222
|
+
@message.on_at_message()
|
|
223
|
+
async def handle_at(event):
|
|
224
|
+
if event["platform"] == "qqbot":
|
|
225
|
+
text = event.get_text()
|
|
226
|
+
if text == "签到":
|
|
227
|
+
await event.reply("已签到")
|
|
228
|
+
|
|
229
|
+
@message.on_message()
|
|
230
|
+
async def handle_message(event):
|
|
231
|
+
if event["platform"] == "qqbot":
|
|
232
|
+
detail_type = event["detail_type"]
|
|
233
|
+
if detail_type == "private":
|
|
234
|
+
pass # 处理私聊消息
|
|
235
|
+
elif detail_type == "group":
|
|
236
|
+
pass # 处理群消息
|
|
237
|
+
elif detail_type == "channel":
|
|
238
|
+
pass # 处理频道消息
|
|
239
|
+
|
|
240
|
+
@notice.on_notice()
|
|
241
|
+
async def handle_notice(event):
|
|
242
|
+
if event["platform"] == "qqbot":
|
|
243
|
+
detail_type = event["detail_type"]
|
|
244
|
+
if detail_type == "qqbot_interaction":
|
|
245
|
+
button_id = event.get("qqbot_button_id", "")
|
|
246
|
+
|
|
247
|
+
@request.on_request()
|
|
248
|
+
async def handle_request(event):
|
|
249
|
+
if event["platform"] == "qqbot":
|
|
250
|
+
await event.approve() # 自动审批入群申请
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 使用平台原生事件
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
qqbot = sdk.adapter.get("qqbot")
|
|
257
|
+
|
|
258
|
+
@qqbot.on("C2C_MESSAGE_CREATE")
|
|
259
|
+
async def handle_private_message(data):
|
|
260
|
+
pass
|
|
261
|
+
|
|
262
|
+
@qqbot.on("GROUP_JOIN_REQUEST")
|
|
263
|
+
async def handle_join_request(data):
|
|
264
|
+
pass
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### 使用 OneBot12 标准事件
|
|
268
|
+
|
|
269
|
+
```python
|
|
270
|
+
@sdk.adapter.on("message")
|
|
271
|
+
async def handle_message(event):
|
|
272
|
+
if event["platform"] == "qqbot":
|
|
273
|
+
bot_id = event["self"]["user_id"]
|
|
274
|
+
print(f"消息来自Bot: {bot_id}")
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## 注意事项:
|
|
278
|
+
|
|
279
|
+
1. 确保在调用 `startup()` 前完成所有处理器的注册
|
|
280
|
+
2. QQBot使用 openid 体系而非QQ号,用户和群的标识均为 openid 字符串
|
|
281
|
+
3. 群消息默认仅在用户@机器人时才会收到(`GROUP_AT_MESSAGE_CREATE`);如需接收全部群消息,请在 [QQ开放平台](https://q.qq.com/) 机器人管理后台开启权限(无API),非@消息将以 `GROUP_MESSAGE_CREATE` 推送
|
|
282
|
+
4. **@检测已支持**:适配器自动解析 `<@openid>`/`<qqbot-at-user>` 两种标记并注入/归一化机器人 mention 段,`on_at_message()`/`event.is_at_message()` 可直接使用;同时自动学习机器人在各群的 openid,"接收全部群消息"模式下 `GROUP_MESSAGE_CREATE` 中的@消息也能识别
|
|
283
|
+
5. 发送的消息可能需要经过审核,通过 `qqbot_audit_pass`/`qqbot_audit_reject` 事件通知结果
|
|
284
|
+
6. 媒体文件(图片、视频等)会上传后通过 file_info 发送,支持URL、本地路径和二进制数据;超过5MB自动分片上传
|
|
285
|
+
7. 程序退出时请调用 `shutdown()` 确保资源释放
|
|
286
|
+
8. access_token 有效期为7200秒,适配器提前45秒自动刷新
|
|
287
|
+
9. 群管理部分API(成员列表、入群审批等)仅对白名单机器人开放
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
### 参考链接
|
|
292
|
+
|
|
293
|
+
- [ErisPulse 主库](https://github.com/ErisPulse/ErisPulse/)
|
|
294
|
+
- [QQBot 官方文档](https://bot.q.qq.com/wiki/)
|
|
295
|
+
- [模块开发指南](https://www.erisdev.com/#docs/developer-guide/README.md)
|