@karinjs/adapter-qqbot 1.3.1 → 2.1.0
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.
- package/README.md +105 -802
- package/dist/apps/cleanup.d.ts +5 -0
- package/dist/apps/cleanup.js +22 -0
- package/dist/apps/login.d.ts +18 -0
- package/dist/apps/login.js +106 -0
- package/dist/common-by1GpV0b.js +49 -0
- package/dist/config-DKa7596f.js +170 -0
- package/dist/index.d.ts +1060 -418
- package/dist/index.js +4742 -97
- package/dist/message-O73AeL_P.js +1739 -0
- package/dist/onboard-DPWgX39H.js +252 -0
- package/dist/utils-BPbnNAix.js +4 -0
- package/dist/web.config.d.ts +21 -24
- package/dist/web.config.js +186 -221
- package/package.json +19 -18
- package/dist/chunk-PYOUSZ6B.js +0 -1501
package/README.md
CHANGED
|
@@ -1,870 +1,173 @@
|
|
|
1
1
|
# @karinjs/adapter-qqbot
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## 功能特性
|
|
6
|
-
|
|
7
|
-
- ✅ 支持 QQ 群聊消息收发
|
|
8
|
-
- ✅ 支持 QQ 好友消息收发
|
|
9
|
-
- ✅ 支持 QQ 频道消息收发
|
|
10
|
-
- ✅ 支持 WebSocket 和 Webhook 两种连接方式
|
|
11
|
-
- ✅ 支持多种 Markdown 模板(原生、图文模板、纯文模板)
|
|
12
|
-
- ✅ 支持沙盒环境和正式环境
|
|
13
|
-
- ✅ 完整的 TypeScript 类型定义
|
|
14
|
-
- ✅ 自动消息签名验证
|
|
3
|
+
Karin 的 QQ 官方机器人适配器。
|
|
15
4
|
|
|
16
5
|
## 安装
|
|
17
6
|
|
|
18
|
-
### 使用 pnpm(推荐)
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
pnpm add @karinjs/adapter-qqbot -w
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
### 使用 npm
|
|
25
|
-
|
|
26
7
|
```bash
|
|
27
|
-
|
|
8
|
+
pnpm add @karinjs/adapter-qqbot
|
|
28
9
|
```
|
|
29
10
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
yarn add @karinjs/adapter-qqbot
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## 快速开始
|
|
37
|
-
|
|
38
|
-
### 前置要求
|
|
39
|
-
|
|
40
|
-
- 已安装并配置好 [Karin 框架](https://github.com/KarinJS/Karin)
|
|
41
|
-
- Node.js >= 16
|
|
42
|
-
- 有QQ开放平台的机器人应用
|
|
43
|
-
|
|
44
|
-
### 5分钟快速配置
|
|
45
|
-
|
|
46
|
-
1. **安装插件**
|
|
47
|
-
```bash
|
|
48
|
-
pnpm add @karinjs/adapter-qqbot -w
|
|
49
|
-
```
|
|
11
|
+
要求:Node.js >= 22、Karin >= 1.15
|
|
50
12
|
|
|
51
|
-
|
|
52
|
-
- 访问 [QQ开放平台](https://bot.q.qq.com/)
|
|
53
|
-
- 创建机器人应用,获取 AppID 和 Secret
|
|
13
|
+
## 配置
|
|
54
14
|
|
|
55
|
-
|
|
56
|
-
```json
|
|
57
|
-
[
|
|
58
|
-
{
|
|
59
|
-
"appId": "你的AppID",
|
|
60
|
-
"secret": "你的Secret",
|
|
61
|
-
"event": { "type": 1 }
|
|
62
|
-
}
|
|
63
|
-
]
|
|
64
|
-
```
|
|
15
|
+
首次启动没有 QQBot 配置时,使用**任意已连接的机器人**或在**控制台中**发送 `#QQ登录` 完成扫码授权。
|
|
65
16
|
|
|
66
|
-
|
|
67
|
-
- 在QQ开放平台设置**统一**回调地址:`https://你的域名/qqbot/webhook`
|
|
68
|
-
- **必须使用HTTPS协议**,端口必须为443(默认HTTPS端口)
|
|
69
|
-
- 该地址接收所有事件:群聊、C2C私聊、频道消息等
|
|
70
|
-
|
|
71
|
-
5. **启动服务**
|
|
72
|
-
```bash
|
|
73
|
-
npm start
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
完成!现在可以邀请机器人到群聊测试了。
|
|
77
|
-
|
|
78
|
-
## 详细配置指南
|
|
79
|
-
|
|
80
|
-
### 第一步:获取机器人凭证
|
|
81
|
-
|
|
82
|
-
1. 访问 [QQ开放平台](https://bot.q.qq.com/)
|
|
83
|
-
2. 登录并创建新的机器人应用
|
|
84
|
-
3. 获取 `AppID` 和 `Secret`
|
|
85
|
-
4. 记录这些信息,后续配置需要用到
|
|
86
|
-
|
|
87
|
-
### 第二步:创建配置文件
|
|
88
|
-
|
|
89
|
-
配置文件位置:`@karinjs/@karinjs-adapter-qqbot/config/config.json`
|
|
90
|
-
|
|
91
|
-
如果文件不存在,插件会自动创建一个空的配置文件。
|
|
92
|
-
|
|
93
|
-
### 第三步:基本配置
|
|
94
|
-
|
|
95
|
-
#### 最简配置示例
|
|
17
|
+
也可以访问 Karin WebUI 可视化编辑 或者 手动编辑:`@karinjs-adapter-qqbot/config/config.json`。
|
|
96
18
|
|
|
97
19
|
```json
|
|
98
20
|
[
|
|
99
21
|
{
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
|
|
103
|
-
]
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
#### 完整配置示例
|
|
107
|
-
|
|
108
|
-
```json
|
|
109
|
-
[
|
|
110
|
-
{
|
|
111
|
-
"appId": "你的机器人AppID",
|
|
112
|
-
"secret": "你的机器人Secret",
|
|
113
|
-
"prodApi": "https://api.sgroup.qq.com",
|
|
114
|
-
"sandboxApi": "https://sandbox.api.sgroup.qq.com",
|
|
115
|
-
"tokenApi": "",
|
|
22
|
+
"name": "我的机器人",
|
|
23
|
+
"appId": "1234567890",
|
|
24
|
+
"secret": "your-secret",
|
|
116
25
|
"sandbox": false,
|
|
117
26
|
"qqEnable": true,
|
|
118
27
|
"guildEnable": true,
|
|
119
28
|
"guildMode": 0,
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
{
|
|
123
|
-
"reg": "^/",
|
|
124
|
-
"rep": "#"
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
"markdown": {
|
|
128
|
-
"mode": 0,
|
|
129
|
-
"id": "",
|
|
130
|
-
"kv": [
|
|
131
|
-
"text_start",
|
|
132
|
-
"img_dec",
|
|
133
|
-
"img_url",
|
|
134
|
-
"text_end"
|
|
135
|
-
]
|
|
136
|
-
},
|
|
137
|
-
"event": {
|
|
138
|
-
"type": 1,
|
|
139
|
-
"wsUrl": "",
|
|
140
|
-
"wsToken": ""
|
|
141
|
-
}
|
|
29
|
+
"keyboard": { "enable": true },
|
|
30
|
+
"event": { "type": 2 }
|
|
142
31
|
}
|
|
143
32
|
]
|
|
144
33
|
```
|
|
145
34
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
#### 方式一:Webhook(推荐)
|
|
149
|
-
|
|
150
|
-
**适用场景:** 有公网IP或域名的服务器
|
|
151
|
-
|
|
152
|
-
1. 在配置文件中设置:
|
|
153
|
-
```json
|
|
154
|
-
{
|
|
155
|
-
"event": {
|
|
156
|
-
"type": 1
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
2. 在QQ开放平台配置回调地址:
|
|
162
|
-
- 回调地址格式:`https://你的域名/qqbot/webhook`
|
|
163
|
-
- 例如:`https://your-domain.com/qqbot/webhook`
|
|
164
|
-
- **⚠️ 重要限制:**
|
|
165
|
-
- 必须使用 **HTTPS** 协议
|
|
166
|
-
- 端口必须为 **443**(标准HTTPS端口)
|
|
167
|
-
- 不支持自定义端口(如:8080、:3000等)
|
|
168
|
-
|
|
169
|
-
> **重要说明:** 这是**统一的回调地址**,QQ开放平台会将所有配置的事件类型(群聊、C2C私聊、频道消息等)都发送到这个地址。您不需要为不同的消息类型配置不同的回调地址。
|
|
170
|
-
|
|
171
|
-
#### 方式二:WebSocket
|
|
172
|
-
|
|
173
|
-
**适用场景:** 内网环境,需要通过中转服务连接
|
|
174
|
-
|
|
175
|
-
1. 在配置文件中设置:
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"event": {
|
|
179
|
-
"type": 2,
|
|
180
|
-
"wsUrl": "wss://your-websocket-server/ws",
|
|
181
|
-
"wsToken": "你的ws认证token"
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### 第五步:反向代理配置(重要)
|
|
187
|
-
|
|
188
|
-
> **为什么需要反向代理?**
|
|
189
|
-
>
|
|
190
|
-
> QQ开放平台对Webhook回调地址有严格要求:
|
|
191
|
-
> - **必须使用HTTPS协议**(不支持HTTP)
|
|
192
|
-
> - **端口必须为443**(标准HTTPS端口,不支持自定义端口)
|
|
193
|
-
> - 必须有有效的SSL证书
|
|
194
|
-
>
|
|
195
|
-
> 如果你的Karin服务运行在:
|
|
196
|
-
> - 内网服务器(如家用电脑、局域网服务器)
|
|
197
|
-
> - 云服务器的内网端口(如3000端口)
|
|
198
|
-
> - Docker容器内部
|
|
199
|
-
>
|
|
200
|
-
> 就需要通过反向代理将内网服务暴露到公网的443端口,并配置SSL证书。
|
|
201
|
-
|
|
202
|
-
#### 反向代理的目标
|
|
203
|
-
|
|
204
|
-
**反向代理要代理的地址:** `http://127.0.0.1:3000/qqbot/webhook`
|
|
205
|
-
|
|
206
|
-
这是Karin QQBot适配器监听的统一webhook接收地址,用于接收**所有类型**的QQ机器人事件,包括:
|
|
207
|
-
- 群聊消息(GROUP_AT_MESSAGE_CREATE)
|
|
208
|
-
- C2C私聊消息(C2C_MESSAGE_CREATE)
|
|
209
|
-
- 频道消息(GUILD_MESSAGE_CREATE)
|
|
210
|
-
- 频道私信(DIRECT_MESSAGE_CREATE)
|
|
211
|
-
- 其他机器人事件
|
|
212
|
-
|
|
213
|
-
QQ开放平台会将所有配置的事件都发送到这个统一的回调地址,然后由适配器内部根据事件类型进行分发处理。
|
|
214
|
-
|
|
215
|
-
#### 方案一:Nginx 反向代理(推荐)
|
|
216
|
-
|
|
217
|
-
**1. 安装Nginx**
|
|
218
|
-
```bash
|
|
219
|
-
# Ubuntu/Debian
|
|
220
|
-
sudo apt update && sudo apt install nginx
|
|
221
|
-
|
|
222
|
-
# CentOS/RHEL
|
|
223
|
-
sudo yum install nginx
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
**2. 创建配置文件**
|
|
227
|
-
|
|
228
|
-
创建 `/etc/nginx/sites-available/karin-qqbot`:
|
|
229
|
-
|
|
230
|
-
```nginx
|
|
231
|
-
server {
|
|
232
|
-
listen 80;
|
|
233
|
-
server_name your-domain.com; # 替换为你的域名或公网IP
|
|
234
|
-
|
|
235
|
-
# QQ机器人webhook接收地址
|
|
236
|
-
location /qqbot/webhook {
|
|
237
|
-
# 代理到本地Karin服务
|
|
238
|
-
proxy_pass http://127.0.0.1:3000/qqbot/webhook;
|
|
239
|
-
|
|
240
|
-
# 必要的代理头设置
|
|
241
|
-
proxy_set_header Host $host;
|
|
242
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
243
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
244
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
245
|
-
|
|
246
|
-
# 关键配置:保持原始请求体用于签名验证
|
|
247
|
-
proxy_buffering off;
|
|
248
|
-
proxy_request_buffering off;
|
|
249
|
-
proxy_read_timeout 300;
|
|
250
|
-
proxy_connect_timeout 300;
|
|
251
|
-
proxy_send_timeout 300;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
# 可选:为Karin的其他功能添加代理
|
|
255
|
-
location /karin/ {
|
|
256
|
-
proxy_pass http://127.0.0.1:3000/;
|
|
257
|
-
proxy_set_header Host $host;
|
|
258
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
259
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
260
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
**获取免费SSL证书(Let's Encrypt):**
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
# 1. 安装certbot
|
|
269
|
-
sudo apt update
|
|
270
|
-
sudo apt install certbot python3-certbot-nginx
|
|
271
|
-
|
|
272
|
-
# 2. 获取SSL证书(自动配置Nginx)
|
|
273
|
-
sudo certbot --nginx -d your-domain.com
|
|
274
|
-
|
|
275
|
-
# 3. 测试自动续期
|
|
276
|
-
sudo certbot renew --dry-run
|
|
277
|
-
|
|
278
|
-
# 4. 设置自动续期(可选)
|
|
279
|
-
sudo crontab -e
|
|
280
|
-
# 添加以下行:
|
|
281
|
-
# 0 12 * * * /usr/bin/certbot renew --quiet
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
**手动配置SSL证书:**
|
|
285
|
-
|
|
286
|
-
如果你有其他SSL证书提供商的证书,按以下格式配置:
|
|
287
|
-
|
|
288
|
-
```nginx
|
|
289
|
-
ssl_certificate /path/to/your/certificate.crt; # 证书文件
|
|
290
|
-
ssl_certificate_key /path/to/your/private.key; # 私钥文件
|
|
291
|
-
```
|
|
292
|
-
|
|
293
|
-
**3. 启用配置**
|
|
294
|
-
```bash
|
|
295
|
-
# 创建软链接启用站点
|
|
296
|
-
sudo ln -s /etc/nginx/sites-available/karin-qqbot /etc/nginx/sites-enabled/
|
|
297
|
-
|
|
298
|
-
# 测试配置文件语法
|
|
299
|
-
sudo nginx -t
|
|
35
|
+
- `event.type`: `0` 关闭、`1` Webhook、`2` WebSocket(默认)。
|
|
36
|
+
- `guildMode`: `0` 公域,只收 @ 消息;`1` 私域,接收全部频道消息。
|
|
300
37
|
|
|
301
|
-
|
|
302
|
-
sudo systemctl reload nginx
|
|
38
|
+
## 按钮
|
|
303
39
|
|
|
304
|
-
|
|
305
|
-
sudo systemctl enable nginx
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
**4. 配置HTTPS(必需)**
|
|
309
|
-
|
|
310
|
-
> **⚠️ 重要:** QQ开放平台**强制要求**使用HTTPS协议和443端口,以下配置是**必需的**,不是可选的。
|
|
311
|
-
|
|
312
|
-
```nginx
|
|
313
|
-
server {
|
|
314
|
-
listen 443 ssl http2;
|
|
315
|
-
server_name your-domain.com;
|
|
316
|
-
|
|
317
|
-
# SSL证书配置(使用Let's Encrypt免费证书)
|
|
318
|
-
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
|
319
|
-
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
|
320
|
-
|
|
321
|
-
# 如果没有SSL证书,可以使用以下命令获取Let's Encrypt免费证书:
|
|
322
|
-
# sudo apt install certbot python3-certbot-nginx
|
|
323
|
-
# sudo certbot --nginx -d your-domain.com
|
|
324
|
-
|
|
325
|
-
# SSL优化配置
|
|
326
|
-
ssl_protocols TLSv1.2 TLSv1.3;
|
|
327
|
-
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
|
|
328
|
-
ssl_prefer_server_ciphers on;
|
|
329
|
-
|
|
330
|
-
location /qqbot/webhook {
|
|
331
|
-
proxy_pass http://127.0.0.1:3000/qqbot/webhook;
|
|
332
|
-
proxy_set_header Host $host;
|
|
333
|
-
proxy_set_header X-Real-IP $remote_addr;
|
|
334
|
-
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
335
|
-
proxy_set_header X-Forwarded-Proto $scheme;
|
|
336
|
-
|
|
337
|
-
# 保持原始请求体
|
|
338
|
-
proxy_buffering off;
|
|
339
|
-
proxy_request_buffering off;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
# HTTP自动跳转HTTPS(推荐配置)
|
|
344
|
-
server {
|
|
345
|
-
listen 80;
|
|
346
|
-
server_name your-domain.com;
|
|
347
|
-
return 301 https://$server_name$request_uri;
|
|
348
|
-
}
|
|
349
|
-
```
|
|
350
|
-
|
|
351
|
-
#### 方案二:宝塔面板配置
|
|
40
|
+
按钮一般和 Markdown 一起发送,常用有三种:
|
|
352
41
|
|
|
353
|
-
|
|
354
|
-
-
|
|
355
|
-
-
|
|
42
|
+
- 跳转按钮:点击后打开 `link`。
|
|
43
|
+
- 指令按钮:点击后把 `data` 发送成一条普通消息。
|
|
44
|
+
- 回调按钮:点击后不会在聊天框发消息,但适配器会下发一条 Karin 消息事件,消息内容就是 `data`。
|
|
356
45
|
|
|
357
|
-
|
|
358
|
-
- 进入网站设置 → SSL
|
|
359
|
-
- 申请Let's Encrypt免费证书或上传自有证书
|
|
360
|
-
- 开启"强制HTTPS"
|
|
46
|
+
下面这个示例先发送一组按钮,然后分别接住“指令按钮”和“回调按钮”的点击结果:
|
|
361
47
|
|
|
362
|
-
|
|
48
|
+
```ts
|
|
49
|
+
import karin, { segment } from 'node-karin'
|
|
363
50
|
|
|
364
|
-
|
|
51
|
+
export const buttonDemo = karin.command(/^按钮示例$/, async (e) => {
|
|
52
|
+
await e.reply([
|
|
53
|
+
segment.markdown('#### 按钮示例\n请选择一个操作:'),
|
|
54
|
+
segment.button([
|
|
55
|
+
{ text: '打开文档', link: 'https://bot.q.qq.com/wiki/' },
|
|
56
|
+
{ text: '发送指令', data: '按钮示例 帮助', enter: true },
|
|
57
|
+
{ text: '回调确认', callback: true, data: '按钮示例 确认' },
|
|
58
|
+
]),
|
|
59
|
+
])
|
|
60
|
+
})
|
|
365
61
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
- **发送域名:** `$host`
|
|
370
|
-
- **代理目录:** `/`
|
|
62
|
+
export const buttonHelp = karin.command(/^按钮示例 帮助$/, async (e) => {
|
|
63
|
+
await e.reply('这是指令按钮发送出来的消息。')
|
|
64
|
+
})
|
|
371
65
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
- **发送域名:** `$host`
|
|
376
|
-
- **代理目录:** `/qqbot/webhook`
|
|
377
|
-
|
|
378
|
-
> **推荐使用方式一**,这样整个域名都会指向您的Karin服务,QQ开放平台访问 `https://your-domain.com/qqbot/webhook` 时会被代理到 `http://127.0.0.1:3000/qqbot/webhook`。
|
|
379
|
-
|
|
380
|
-
**4. 高级设置**
|
|
381
|
-
添加以下配置到反向代理的配置文件中:
|
|
382
|
-
```nginx
|
|
383
|
-
proxy_buffering off;
|
|
384
|
-
proxy_request_buffering off;
|
|
66
|
+
export const buttonConfirm = karin.command(/^按钮示例 确认$/, async (e) => {
|
|
67
|
+
await e.reply(`收到回调按钮:${e.msg}`)
|
|
68
|
+
})
|
|
385
69
|
```
|
|
386
70
|
|
|
387
|
-
|
|
71
|
+
如果你希望回复自动带上一组按钮,可以把按钮单独注册出来。下面这个分页示例会根据当前消息生成“上一页 / 下一页”:
|
|
388
72
|
|
|
389
|
-
|
|
73
|
+
```ts
|
|
74
|
+
import karin, { segment } from 'node-karin'
|
|
390
75
|
|
|
391
|
-
|
|
392
|
-
```bash
|
|
393
|
-
# 参考官方文档安装Caddy
|
|
394
|
-
```
|
|
76
|
+
const getPage = (msg = '') => Number(msg.match(/^菜单(?:\s+(\d+))?$/)?.[1] || 1)
|
|
395
77
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
# 自动HTTPS
|
|
402
|
-
tls {
|
|
403
|
-
on_demand
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
#### 方案四:Cloudflare Tunnel(内网穿透)
|
|
78
|
+
export const menuDemo = karin.command(/^菜单(?:\s+\d+)?$/, async (e) => {
|
|
79
|
+
const page = getPage(e.msg)
|
|
80
|
+
await e.reply(segment.markdown(`#### 菜单\n当前第 ${page} 页`))
|
|
81
|
+
})
|
|
409
82
|
|
|
410
|
-
|
|
83
|
+
export const menuKeyboard = karin.button(/^菜单(?:\s+\d+)?$/, (next, args) => {
|
|
84
|
+
const page = getPage(args?.e?.msg)
|
|
411
85
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
**2. 登录Cloudflare**
|
|
420
|
-
```bash
|
|
421
|
-
cloudflared tunnel login
|
|
422
|
-
```
|
|
423
|
-
|
|
424
|
-
**3. 创建隧道**
|
|
425
|
-
```bash
|
|
426
|
-
cloudflared tunnel create karin-qqbot
|
|
427
|
-
```
|
|
428
|
-
|
|
429
|
-
**4. 配置DNS**
|
|
430
|
-
```bash
|
|
431
|
-
cloudflared tunnel route dns karin-qqbot your-subdomain.your-domain.com
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
**5. 运行隧道**
|
|
435
|
-
```bash
|
|
436
|
-
cloudflared tunnel run --url http://localhost:3000 karin-qqbot
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
#### 方案五:frp 内网穿透
|
|
440
|
-
|
|
441
|
-
**适用场景:** 使用自建或第三方frp服务
|
|
442
|
-
|
|
443
|
-
**客户端配置 (frpc.ini):**
|
|
444
|
-
```ini
|
|
445
|
-
[common]
|
|
446
|
-
server_addr = your-frp-server.com
|
|
447
|
-
server_port = 7000
|
|
448
|
-
token = your_token
|
|
449
|
-
|
|
450
|
-
[karin-qqbot]
|
|
451
|
-
type = http
|
|
452
|
-
local_ip = 127.0.0.1
|
|
453
|
-
local_port = 3000
|
|
454
|
-
custom_domains = your-domain.com
|
|
455
|
-
```
|
|
456
|
-
|
|
457
|
-
### 第六步:QQ开放平台回调地址要求
|
|
458
|
-
|
|
459
|
-
#### 官方限制条件
|
|
460
|
-
|
|
461
|
-
QQ开放平台对Webhook回调地址有以下**强制要求**:
|
|
462
|
-
|
|
463
|
-
| 要求项 | 限制 | 说明 |
|
|
464
|
-
|--------|------|------|
|
|
465
|
-
| **协议** | 必须HTTPS | 不支持HTTP协议 |
|
|
466
|
-
| **端口** | 必须443 | 不支持自定义端口(如:8080、:3000等) |
|
|
467
|
-
| **SSL证书** | 必须有效 | 需要被浏览器信任的证书 |
|
|
468
|
-
| **域名** | 必须有域名 | 不支持IP地址直接访问 |
|
|
469
|
-
| **响应时间** | 3秒内 | 超时会重试 |
|
|
470
|
-
|
|
471
|
-
#### 正确的回调地址格式
|
|
472
|
-
|
|
473
|
-
✅ **正确格式:**
|
|
474
|
-
- `https://your-domain.com/qqbot/webhook`
|
|
475
|
-
- `https://bot.your-company.com/qqbot/webhook`
|
|
476
|
-
|
|
477
|
-
❌ **错误格式:**
|
|
478
|
-
- `http://your-domain.com/qqbot/webhook` (不支持HTTP)
|
|
479
|
-
- `https://your-domain.com:3000/qqbot/webhook` (不支持自定义端口)
|
|
480
|
-
- `https://123.456.789.10/qqbot/webhook` (不支持IP地址)
|
|
481
|
-
|
|
482
|
-
### 第七步:域名和防火墙配置
|
|
483
|
-
|
|
484
|
-
#### 域名解析配置
|
|
485
|
-
|
|
486
|
-
确保域名正确解析到你的服务器:
|
|
487
|
-
```bash
|
|
488
|
-
# 检查域名解析
|
|
489
|
-
nslookup your-domain.com
|
|
490
|
-
dig your-domain.com
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
#### 防火墙配置
|
|
494
|
-
|
|
495
|
-
**Ubuntu/Debian (ufw):**
|
|
496
|
-
```bash
|
|
497
|
-
# 开放HTTP和HTTPS端口
|
|
498
|
-
sudo ufw allow 80
|
|
499
|
-
sudo ufw allow 443
|
|
500
|
-
|
|
501
|
-
# 如果直接暴露端口
|
|
502
|
-
sudo ufw allow 3000
|
|
503
|
-
```
|
|
504
|
-
|
|
505
|
-
**CentOS/RHEL (firewalld):**
|
|
506
|
-
```bash
|
|
507
|
-
# 开放端口
|
|
508
|
-
sudo firewall-cmd --permanent --add-port=80/tcp
|
|
509
|
-
sudo firewall-cmd --permanent --add-port=443/tcp
|
|
510
|
-
sudo firewall-cmd --reload
|
|
511
|
-
```
|
|
512
|
-
|
|
513
|
-
**云服务器安全组:**
|
|
514
|
-
- 阿里云:安全组规则添加入方向 80、443 端口
|
|
515
|
-
- 腾讯云:防火墙规则添加入站 80、443 端口
|
|
516
|
-
- AWS:Security Group 添加 HTTP、HTTPS 规则
|
|
517
|
-
|
|
518
|
-
### 第九步:配置参数说明
|
|
519
|
-
|
|
520
|
-
| 参数 | 说明 | 默认值 |
|
|
521
|
-
|------|------|--------|
|
|
522
|
-
| `appId` | 机器人ID(必填) | "" |
|
|
523
|
-
| `secret` | 机器人密钥(必填) | "" |
|
|
524
|
-
| `sandbox` | 是否使用沙盒环境 | false |
|
|
525
|
-
| `qqEnable` | 是否启用QQ场景 | true |
|
|
526
|
-
| `guildEnable` | 是否启用频道场景 | true |
|
|
527
|
-
| `guildMode` | 频道模式(0公域,1私域) | 0 |
|
|
528
|
-
| `event.type` | 事件接收方式(0关闭,1webhook,2ws) | 0 |
|
|
529
|
-
|
|
530
|
-
#### Markdown 模式说明
|
|
531
|
-
|
|
532
|
-
| 模式 | 说明 | 适用场景 |
|
|
533
|
-
|------|------|----------|
|
|
534
|
-
| 0 | 直接发送 | 简单文本和图片消息 |
|
|
535
|
-
| 1 | 原生Markdown | 需要富文本格式 |
|
|
536
|
-
| 3 | 旧图文模板 | 复杂图文混排 |
|
|
537
|
-
| 4 | 纯文模板 | 多段文本消息 |
|
|
538
|
-
| 5 | 自定义处理 | 完全自定义逻辑 |
|
|
539
|
-
|
|
540
|
-
#### 支持的事件类型
|
|
541
|
-
|
|
542
|
-
QQ机器人适配器通过统一的webhook地址接收以下事件类型:
|
|
543
|
-
|
|
544
|
-
| 事件类型 | 说明 | 处理函数 |
|
|
545
|
-
|---------|------|---------|
|
|
546
|
-
| `GROUP_AT_MESSAGE_CREATE` | 群聊@机器人消息 | `onGroupMsg` |
|
|
547
|
-
| `C2C_MESSAGE_CREATE` | C2C私聊消息 | `onFriendMsg` |
|
|
548
|
-
| `GUILD_MESSAGE_CREATE` | 频道消息 | `onChannelMsg` |
|
|
549
|
-
| `DIRECT_MESSAGE_CREATE` | 频道私信 | `onDirectMsg` |
|
|
550
|
-
|
|
551
|
-
所有这些事件都通过同一个回调地址 `/qqbot/webhook` 接收,适配器内部会根据事件类型自动分发到对应的处理函数。
|
|
552
|
-
|
|
553
|
-
## 使用说明
|
|
554
|
-
|
|
555
|
-
### 连接方式说明
|
|
556
|
-
|
|
557
|
-
#### 1. Webhook 方式
|
|
558
|
-
|
|
559
|
-
- **优点**:配置简单,不需要额外的中转服务
|
|
560
|
-
- **缺点**:需要有公网IP或域名
|
|
561
|
-
- **适用场景**:有固定服务器或云服务器的用户
|
|
562
|
-
|
|
563
|
-
配置完成后,需要在 QQ 开放平台配置 Webhook 回调地址。
|
|
564
|
-
|
|
565
|
-
#### 2. WebSocket 方式
|
|
566
|
-
|
|
567
|
-
- **优点**:适合内网环境,通过中转服务连接
|
|
568
|
-
- **缺点**:需要额外部署中转服务
|
|
569
|
-
- **适用场景**:没有公网IP的本地开发环境
|
|
570
|
-
|
|
571
|
-
### 发送模式说明
|
|
572
|
-
|
|
573
|
-
#### 模式 0:直接发送(推荐)
|
|
574
|
-
|
|
575
|
-
最简单的模式,直接发送纯文本和图片消息。
|
|
576
|
-
|
|
577
|
-
#### 模式 1:原生 Markdown
|
|
578
|
-
|
|
579
|
-
使用 QQ 官方的原生 Markdown 格式发送消息。
|
|
580
|
-
|
|
581
|
-
#### 模式 3:旧图文模板 Markdown
|
|
582
|
-
|
|
583
|
-
使用旧版图文混排模板,适合需要复杂排版的场景。
|
|
584
|
-
|
|
585
|
-
#### 模式 4:纯文模板 Markdown
|
|
586
|
-
|
|
587
|
-
使用纯文本模板,支持多个文本字段。
|
|
588
|
-
|
|
589
|
-
#### 模式 5:自定义处理
|
|
590
|
-
|
|
591
|
-
完全自定义消息处理逻辑。
|
|
592
|
-
|
|
593
|
-
## 开发指南
|
|
594
|
-
|
|
595
|
-
### 环境要求
|
|
596
|
-
|
|
597
|
-
- Node.js >= 16
|
|
598
|
-
- TypeScript >= 5.0
|
|
599
|
-
- Karin 框架
|
|
600
|
-
|
|
601
|
-
### 本地开发
|
|
602
|
-
|
|
603
|
-
1. 克隆仓库
|
|
604
|
-
|
|
605
|
-
```bash
|
|
606
|
-
git clone https://github.com/KarinJS/karin-plugin-adapter-qqbot.git
|
|
607
|
-
cd karin-plugin-adapter-qqbot
|
|
86
|
+
return segment.keyboard([
|
|
87
|
+
[
|
|
88
|
+
{ text: '上一页', data: `菜单 ${Math.max(1, page - 1)}`, enter: true },
|
|
89
|
+
{ text: '下一页', data: `菜单 ${page + 1}`, enter: true },
|
|
90
|
+
],
|
|
91
|
+
])
|
|
92
|
+
})
|
|
608
93
|
```
|
|
609
94
|
|
|
610
|
-
|
|
95
|
+
简单理解:`karin.button` 是“自动追加按钮”的规则。适配器回复时会自动用 `buttonHandle(e.msg, { e })` 查找匹配规则,所以用户发送 `菜单 2`,就会命中 `/^菜单(?:\s+\d+)?$/`,按钮函数再通过 `args?.e?.msg` 算出当前页。
|
|
611
96
|
|
|
612
|
-
|
|
613
|
-
npm install
|
|
614
|
-
```
|
|
97
|
+
自己调用 `buttonHandle` 时只记三点:
|
|
615
98
|
|
|
616
|
-
|
|
99
|
+
- 参数一是匹配文本,通常填 `e.msg`,也可以是 `'菜单'`。
|
|
100
|
+
- 参数二是给按钮函数的上下文,常用 `{ e }`;需要状态可以写 `{ e, page: 2 }`。
|
|
101
|
+
- 一个规则里调用 `next()`,才会继续匹配后面的规则。
|
|
617
102
|
|
|
618
|
-
|
|
619
|
-
npm run dev
|
|
620
|
-
```
|
|
103
|
+
回调按钮的 `data` 会变成一条 Karin 消息内容,所以建议直接写成插件能识别的命令,例如 `按钮示例 确认`、`菜单 下一页`。
|
|
621
104
|
|
|
622
|
-
|
|
105
|
+
## 发送消息与资源文件
|
|
623
106
|
|
|
624
|
-
|
|
107
|
+
适配器会尽量帮你发送图片、视频、语音和文件。推荐配置 `fileToUrl` 上传处理器,把本地文件、截图、Base64 等资源上传到你的图床、对象存储或 CDN,并返回一个 QQ 能访问的链接。
|
|
625
108
|
|
|
626
|
-
|
|
627
|
-
npm run build
|
|
628
|
-
```
|
|
629
|
-
|
|
630
|
-
构建产物会输出到 `dist` 目录。
|
|
109
|
+
配置 `fileToUrl` 后:
|
|
631
110
|
|
|
632
|
-
|
|
111
|
+
- 本地图片可以正常嵌入 Markdown 消息。
|
|
112
|
+
- 视频、语音和文件会优先使用你返回的链接发送,通常比直接上传给 QQ 更稳定。
|
|
113
|
+
- 如果资源本身已经是 `http` / `https` 链接,适配器会直接使用它。
|
|
633
114
|
|
|
634
|
-
|
|
635
|
-
npm run lint
|
|
636
|
-
```
|
|
115
|
+
没有配置 `fileToUrl` 时:
|
|
637
116
|
|
|
638
|
-
|
|
117
|
+
- 单独发送图片、视频、语音、文件时,适配器会尝试直接交给 QQ 发送。
|
|
118
|
+
- 较大的资源会使用 QQ 的大文件上传流程,优先保证消息能发出去。
|
|
119
|
+
- 较大的图片或视频直接交给 QQ 发送时,QQ 客户端可能会把它显示成群文件,而不是图片或视频卡片;配置 `fileToUrl` 后通常可以避免这种显示问题。
|
|
120
|
+
- 直接交给 QQ 只是兜底方案,生产环境仍然建议准备自己的文件服务。
|
|
639
121
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
# 发布测试版
|
|
645
|
-
npm run pub-beta
|
|
646
|
-
```
|
|
122
|
+
> **注意:Markdown 里的图片必须配置 `fileToUrl`。**
|
|
123
|
+
>
|
|
124
|
+
> 只要你发送的内容包含 Markdown,并且 Markdown 里有图片、本地生成图、Base64 图等资源,就必须配置 `fileToUrl`。因为 Markdown 里的图片只能写成 QQ 能访问的链接,适配器不能把 Markdown 文本里的图片自动当成附件上传。
|
|
647
125
|
|
|
648
|
-
|
|
126
|
+
你可以在自己的 Karin 插件中编写并注册 `fileToUrl` Handler:
|
|
649
127
|
|
|
650
|
-
```
|
|
651
|
-
karin-plugin-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
│ ├── core/ # 核心功能(适配器、事件处理、API)
|
|
655
|
-
│ ├── types/ # TypeScript 类型定义
|
|
656
|
-
│ └── utils/ # 工具函数
|
|
657
|
-
├── dist/ # 构建产物
|
|
658
|
-
├── config/ # 配置文件目录
|
|
659
|
-
├── package.json
|
|
660
|
-
├── tsconfig.json # TypeScript 配置
|
|
661
|
-
└── tsup.config.ts # 打包配置
|
|
662
|
-
```
|
|
128
|
+
```js
|
|
129
|
+
// plugins/karin-plugin-example/fileToUrl.js
|
|
130
|
+
import karin, { common } from 'node-karin'
|
|
131
|
+
import size from 'image-size'
|
|
663
132
|
|
|
664
|
-
|
|
133
|
+
export const uploadResource = karin.handler('fileToUrl', async (args) => {
|
|
134
|
+
const { file, type, filename } = args
|
|
135
|
+
const buffer = await common.buffer(file)
|
|
665
136
|
|
|
666
|
-
|
|
137
|
+
// 由你实现:上传到图床/对象存储,返回可公开访问的 URL。
|
|
138
|
+
const url = await uploadToYourStorage(buffer, filename || 'file.bin')
|
|
667
139
|
|
|
668
|
-
|
|
669
|
-
import type { AdapterQQBot } from '@karinjs/adapter-qqbot'
|
|
140
|
+
if (type !== 'image') return { url }
|
|
670
141
|
|
|
671
|
-
//
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
await bot.SendMessage(e.contact, [
|
|
677
|
-
{ type: 'text', text: 'Hello, World!' }
|
|
678
|
-
])
|
|
142
|
+
const dimension = size(buffer) // 获取图片宽高
|
|
143
|
+
return {
|
|
144
|
+
url,
|
|
145
|
+
width: dimension.width || 100,
|
|
146
|
+
height: dimension.height || 100
|
|
679
147
|
}
|
|
680
|
-
}
|
|
148
|
+
})
|
|
681
149
|
```
|
|
682
150
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
await bot.recallMsg(e.contact, messageId)
|
|
687
|
-
```
|
|
151
|
+
> **注意:Handler 插件的 key 必须精确为 `fileToUrl`。**
|
|
152
|
+
>
|
|
153
|
+
> 图片必须返回 `{ url, width, height }`;其他资源返回 `{ url }`。
|
|
688
154
|
|
|
689
|
-
|
|
155
|
+
建议生产环境都配置 `fileToUrl`。这样图片、视频和文件都可以先上传到你自己的文件服务,再交给 QQ 发送,成功率和可控性都会更好。
|
|
690
156
|
|
|
691
|
-
|
|
157
|
+
## 事件
|
|
692
158
|
|
|
693
|
-
|
|
159
|
+
- 支持 QQ 单聊、群聊、频道、频道私信和按钮回调。
|
|
160
|
+
- 支持 `GROUP_MESSAGE_CREATE` 全量群消息和 `author.member_role` 身份字段。
|
|
161
|
+
- 支持 `GROUP_MEMBER_ADD`、`GROUP_MEMBER_REMOVE` 群成员进退群事件。
|
|
162
|
+
- 单聊同一 `msg_id` 最多回复 4 次;群聊规则保持官方限制。
|
|
694
163
|
|
|
695
|
-
|
|
164
|
+
## 开发
|
|
696
165
|
|
|
697
166
|
```bash
|
|
698
|
-
|
|
699
|
-
|
|
167
|
+
pnpm install
|
|
168
|
+
pnpm build
|
|
700
169
|
```
|
|
701
170
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
```bash
|
|
705
|
-
# 启动 Karin 服务
|
|
706
|
-
npm start
|
|
707
|
-
# 或者
|
|
708
|
-
node app.js
|
|
709
|
-
```
|
|
710
|
-
|
|
711
|
-
#### 3. 查看日志
|
|
712
|
-
|
|
713
|
-
检查日志文件,确认机器人连接成功:
|
|
714
|
-
|
|
715
|
-
```bash
|
|
716
|
-
# 查看最新日志
|
|
717
|
-
tail -f logs/error/*.log
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
正常情况下应该看到类似信息:
|
|
721
|
-
- `QQBot [AppID] 连接成功`
|
|
722
|
-
- `Webhook服务已启动,端口: 3000`
|
|
723
|
-
|
|
724
|
-
#### 4. 测试机器人
|
|
725
|
-
|
|
726
|
-
1. 将机器人邀请到测试群
|
|
727
|
-
2. 发送消息测试机器人响应
|
|
728
|
-
3. 检查日志确认消息接收正常
|
|
729
|
-
|
|
730
|
-
### 第十一步:常见问题排查
|
|
731
|
-
|
|
732
|
-
#### 问题1:Webhook接收不到消息
|
|
733
|
-
|
|
734
|
-
**检查清单:**
|
|
735
|
-
- [ ] QQ开放平台回调地址配置正确
|
|
736
|
-
- [ ] 服务器防火墙开放对应端口
|
|
737
|
-
- [ ] Nginx反向代理配置正确
|
|
738
|
-
- [ ] 域名解析正确指向服务器IP
|
|
739
|
-
|
|
740
|
-
**排查命令:**
|
|
741
|
-
```bash
|
|
742
|
-
# 检查端口是否监听
|
|
743
|
-
netstat -tlnp | grep :3000
|
|
744
|
-
|
|
745
|
-
# 检查防火墙状态
|
|
746
|
-
sudo ufw status
|
|
747
|
-
|
|
748
|
-
# 测试本地接口
|
|
749
|
-
curl -X POST http://localhost:3000/qqbot/webhook
|
|
750
|
-
```
|
|
751
|
-
|
|
752
|
-
#### 问题2:签名验证失败
|
|
753
|
-
|
|
754
|
-
**可能原因:**
|
|
755
|
-
- Secret配置错误
|
|
756
|
-
- 反向代理修改了请求体
|
|
757
|
-
- 时间戳差异过大
|
|
758
|
-
|
|
759
|
-
**解决方案:**
|
|
760
|
-
```nginx
|
|
761
|
-
# Nginx配置中添加
|
|
762
|
-
proxy_buffering off;
|
|
763
|
-
proxy_request_buffering off;
|
|
764
|
-
```
|
|
765
|
-
|
|
766
|
-
#### 问题3:消息发送失败
|
|
767
|
-
|
|
768
|
-
**检查清单:**
|
|
769
|
-
- [ ] AppID和Secret正确
|
|
770
|
-
- [ ] 机器人有发送消息权限
|
|
771
|
-
- [ ] API地址配置正确
|
|
772
|
-
- [ ] 网络连接正常
|
|
773
|
-
|
|
774
|
-
#### 问题4:频道消息收不到
|
|
775
|
-
|
|
776
|
-
**可能原因:**
|
|
777
|
-
- 频道机器人权限不足
|
|
778
|
-
- guildEnable配置为false
|
|
779
|
-
- 私域机器人未正确配置
|
|
780
|
-
|
|
781
|
-
**解决方案:**
|
|
782
|
-
```json
|
|
783
|
-
{
|
|
784
|
-
"guildEnable": true,
|
|
785
|
-
"guildMode": 1 // 私域机器人使用1
|
|
786
|
-
}
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
### 第十二步:进阶配置
|
|
790
|
-
|
|
791
|
-
#### 多机器人配置
|
|
792
|
-
|
|
793
|
-
```json
|
|
794
|
-
[
|
|
795
|
-
{
|
|
796
|
-
"appId": "机器人1的AppID",
|
|
797
|
-
"secret": "机器人1的Secret",
|
|
798
|
-
"event": { "type": 1 }
|
|
799
|
-
},
|
|
800
|
-
{
|
|
801
|
-
"appId": "机器人2的AppID",
|
|
802
|
-
"secret": "机器人2的Secret",
|
|
803
|
-
"event": { "type": 1 }
|
|
804
|
-
}
|
|
805
|
-
]
|
|
806
|
-
```
|
|
807
|
-
|
|
808
|
-
#### 环境分离配置
|
|
809
|
-
|
|
810
|
-
开发环境使用沙盒:
|
|
811
|
-
```json
|
|
812
|
-
{
|
|
813
|
-
"sandbox": true,
|
|
814
|
-
"sandboxApi": "https://sandbox.api.sgroup.qq.com"
|
|
815
|
-
}
|
|
816
|
-
```
|
|
817
|
-
|
|
818
|
-
生产环境使用正式API:
|
|
819
|
-
```json
|
|
820
|
-
{
|
|
821
|
-
"sandbox": false,
|
|
822
|
-
"prodApi": "https://api.sgroup.qq.com"
|
|
823
|
-
}
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
#### 消息过滤配置
|
|
827
|
-
|
|
828
|
-
```json
|
|
829
|
-
{
|
|
830
|
-
"exclude": [
|
|
831
|
-
"https://example.com",
|
|
832
|
-
"https://trusted-site.com"
|
|
833
|
-
],
|
|
834
|
-
"regex": [
|
|
835
|
-
{
|
|
836
|
-
"reg": "^/",
|
|
837
|
-
"rep": "#"
|
|
838
|
-
},
|
|
839
|
-
{
|
|
840
|
-
"reg": "\\[图片\\]",
|
|
841
|
-
"rep": ""
|
|
842
|
-
}
|
|
843
|
-
]
|
|
844
|
-
}
|
|
845
|
-
```
|
|
846
|
-
|
|
847
|
-
## 更新日志
|
|
848
|
-
|
|
849
|
-
查看 [CHANGELOG.md](./CHANGELOG.md) 了解版本更新历史。
|
|
850
|
-
|
|
851
|
-
## 贡献
|
|
852
|
-
|
|
853
|
-
欢迎提交 Issue 和 Pull Request!
|
|
854
|
-
|
|
855
|
-
## 许可证
|
|
856
|
-
|
|
857
|
-
本项目基于 [项目许可证] 开源。
|
|
858
|
-
|
|
859
|
-
## 相关链接
|
|
860
|
-
|
|
861
|
-
- [Karin 框架](https://github.com/KarinJS/Karin)
|
|
862
|
-
- [QQ 机器人开放平台](https://bot.q.qq.com/)
|
|
863
|
-
- [QQ 机器人开发文档](https://bot.q.qq.com/wiki/)
|
|
864
|
-
|
|
865
|
-
## 技术支持
|
|
866
|
-
|
|
867
|
-
如有问题,请通过以下方式获取帮助:
|
|
171
|
+
## License
|
|
868
172
|
|
|
869
|
-
|
|
870
|
-
- 加入 Karin 开发者社群
|
|
173
|
+
MIT
|