@karinjs/adapter-qqbot 3.3.0 → 3.4.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.
@@ -0,0 +1,2688 @@
1
+ import { AdapterBase, AdapterType, Contact, CreateGroupFolderResponse, DownloadFileOptions, DownloadFileResponse, ElementTypes, ForwardOptions, GetAiCharactersResponse, GetAtAllCountResponse, GetGroupFileListResponse, GetGroupFileSystemInfoResponse, GetGroupHighlightsResponse, GetGroupMuteListResponse, GetRkeyResponse, GroupInfo, GroupMemberInfo, LogMethodNames, Message, MessageResponse, NodeElement, QQGroupHonorInfo, SendMsgResults, Sender, UserInfo } from "node-karin";
2
+ import { AxiosRequestConfig, AxiosResponse } from "node-karin/axios";
3
+ import FormData from "form-data";
4
+ //#region src/core/api/types.d.ts
5
+ /** 上传富媒体文件场景 */
6
+ type Scene = 'user' | 'group';
7
+ /** 上传富媒体文件类型 */
8
+ type MediaType = 'image' | 'video' | 'record' | 'file';
9
+ /** 发送QQ消息请求参数基类 */
10
+ interface SendQQMessageRequest {
11
+ /** 消息类型:0 是文本,2 是 markdown, 3 ark,4 embed,6 输入中状态(仅单聊),7 media 富媒体 */
12
+ msg_type: 0 | 2 | 3 | 4 | 6 | 7;
13
+ }
14
+ /** 消息引用对象 */
15
+ interface MessageReference {
16
+ /** 需要引用回复的消息 id */
17
+ message_id: string;
18
+ /** 是否忽略获取引用消息详情错误,默认否 */
19
+ ignore_get_message_error?: boolean;
20
+ }
21
+ /** 发送QQ被动消息参数 */
22
+ interface QQMessageID {
23
+ /** 前置收到的事件 ID,用于发送被动消息,支持事件:"INTERACTION_CREATE"、"C2C_MSG_RECEIVE"、"FRIEND_ADD" */
24
+ event_id?: string;
25
+ /** 前置收到的用户发送过来的消息 ID,用于发送被动(回复)消息 */
26
+ msg_id?: string;
27
+ /** 回复消息的序号,与 msg_id 联合使用,避免相同消息id回复重复发送,不填默认是1。相同的 msg_id + msg_seq 重复发送会失败。 */
28
+ msg_seq?: number;
29
+ /**
30
+ * 指明发送消息为互动召回消息,与 msg_id、event_id 互斥使用
31
+ *
32
+ * 接口文档 v1.28.0(2026-09-03)起该字段已从群消息发送接口移除,
33
+ * 目前仅单聊 `POST /v2/users/{user_openid}/messages` 可用。
34
+ */
35
+ is_wakeup?: boolean;
36
+ /** 引用消息对象,QQ单聊和群聊场景均支持 */
37
+ message_reference?: MessageReference;
38
+ }
39
+ /** 发送QQ文本消息请求参数 */
40
+ interface SendQQTextMessageRequest extends SendQQMessageRequest, QQMessageID {
41
+ msg_type: 0;
42
+ /**
43
+ * 消息内容 支持如下内嵌格式
44
+ * - `<qqbot-at-user id="" />` `@用户` **注意双引号不能省略**
45
+ * - `<qqbot-at-everyone />` `@所有人`
46
+ */
47
+ content: string;
48
+ }
49
+ /** markdown 消息结构(官方已全量开放原生 markdown,2.0 不再支持模板模式) */
50
+ interface Markdown {
51
+ /** markdown 文本 */
52
+ content: string;
53
+ }
54
+ /** keyboard 按钮渲染(Button.render_data) */
55
+ interface KeyboardButtonRenderData {
56
+ /** 按钮文字,最多 10 字符 */
57
+ label?: string;
58
+ /** 点击后文字,不传则保持不变 */
59
+ visited_label?: string;
60
+ /**
61
+ * 按钮样式
62
+ * - `0` 灰色线框
63
+ * - `1` 蓝色线框
64
+ * - `3` 白色背景 + 红色字体
65
+ * - `4` 蓝色背景 + 白色字体
66
+ *
67
+ * 接口文档 v1.28.0(2026-09-03)重定义了取值,旧文档中的 `2`(白字)已被移除。
68
+ */
69
+ style?: number;
70
+ }
71
+ /** keyboard 按钮点击权限(Button.action.permission) */
72
+ interface KeyboardButtonPermission {
73
+ /** 0 指定用户可操作,1 仅管理者可操作,2 所有人可操作,3 指定身份组可操作(仅频道可用) */
74
+ type?: number;
75
+ /** 有权限的用户 id 的列表 */
76
+ specify_user_ids?: string[];
77
+ /** 有权限的身份组 id 的列表(仅频道可用) */
78
+ specify_role_ids?: string[];
79
+ }
80
+ /**
81
+ * 按钮二次确认(Button.action.modal)
82
+ *
83
+ * 接口文档 v1.28.0(2026-09-03)新增:点击按钮后先弹确认框,确认后才触发按钮行为。
84
+ */
85
+ interface KeyboardButtonModal {
86
+ /** 二次确认的提示文本,不为空则进行二次确认;最多 40 个字符,不能有 URL */
87
+ content?: string;
88
+ /** 确认按钮上展示的文字,可为空,默认「确认」;最多 4 个字符 */
89
+ confirm_text?: string;
90
+ /** 取消按钮上展示的文字,可为空,默认「取消」;最多 4 个字符 */
91
+ cancel_text?: string;
92
+ }
93
+ /** keyboard 按钮点击行为(Button.action) */
94
+ interface KeyboardButtonAction {
95
+ /** 0 跳转按钮(http / 小程序 scheme),1 回调按钮(回调后台接口),2 指令按钮(在输入框插入 @bot data) */
96
+ type?: number;
97
+ /** 权限设置 */
98
+ permission?: KeyboardButtonPermission;
99
+ /** 操作相关的数据 */
100
+ data?: string;
101
+ /** 客户端不支持本 action 的时候,弹出的 toast 文案 */
102
+ unsupport_tips?: string;
103
+ /** 指令按钮可用,点击按钮后直接自动发送 data,仅单聊可用,默认 false(支持版本 8983) */
104
+ enter?: boolean;
105
+ /** 指令按钮可用,指令是否带引用回复本消息,默认 false(支持版本 8983) */
106
+ reply?: boolean;
107
+ /**
108
+ * 仅在指令按钮下有效,设置后会忽略 `enter` 配置。
109
+ * 设为 1 时点击按钮自动唤起手 Q 选图器(仅手机端 8983+ 的单聊场景)。
110
+ */
111
+ anchor?: number;
112
+ /** 用户点击后的二次确认操作 */
113
+ modal?: KeyboardButtonModal;
114
+ /** @deprecated 官方已弃用:可操作点击的次数 */
115
+ click_limit?: number;
116
+ /** @deprecated 官方已弃用:指令按钮弹出子频道选择器 */
117
+ at_bot_show_channel_list?: boolean;
118
+ }
119
+ /**
120
+ * keyboard 按钮(Button)
121
+ *
122
+ * 字段与官方文档一致,并且是 node-karin `QQBotButton` 的结构超集,
123
+ * 因此 `karinToQQBot()` 的输出可以直接放进 {@link Keyboard}。
124
+ */
125
+ interface KeyboardButton {
126
+ /** 按钮 ID,同一键盘内唯一 */
127
+ id?: string;
128
+ /** 按钮渲染 */
129
+ render_data?: KeyboardButtonRenderData;
130
+ /** 按钮点击行为 */
131
+ action?: KeyboardButtonAction;
132
+ /**
133
+ * 分组 ID,同一分组内有一个按钮被操作后,其它按钮变灰不可点击
134
+ *
135
+ * 接口文档 v1.28.0(2026-09-03)新增,仅当 `action.type = 1` 时有效。
136
+ */
137
+ group_id?: string;
138
+ }
139
+ /** keyboard 一行按钮 */
140
+ interface KeyboardRow {
141
+ /** 该行的按钮,官方限制每行最多 5 个 */
142
+ buttons: KeyboardButton[];
143
+ }
144
+ /** 按钮消息结构(官方已全量开放自定义 keyboard,2.0 不再支持模板按钮) */
145
+ interface Keyboard {
146
+ /** 键盘内容,官方限制最多 5 行 */
147
+ content: {
148
+ rows: KeyboardRow[];
149
+ };
150
+ }
151
+ /** 发送QQ Markdown 消息请求参数 */
152
+ interface SendQQMarkdownMessageRequest extends SendQQMessageRequest, QQMessageID {
153
+ msg_type: 2;
154
+ /**
155
+ * markdown 消息内容 支持如下内嵌格式
156
+ * - `<qqbot-cmd-enter text="xxx" />` `回车按钮: 点击后,文本直接发送`
157
+ * - `<qqbot-cmd-input text="xxx" show="xxx" reference="false" />` `点击后,文本输入框弹出`
158
+ * - `text 用户点击后插入输入框的文本,参数必填,最大限制 100 字符,传值时需要 urlencode`
159
+ * - `show 用户在消息内看到的文本,参数选填,默认取 text 值,最大限制 100 字符,传值时需要 urlencode。`
160
+ * - `reference 插入输入框时是否带消息原文回复引用,参数选填,默认为 false,填入 true 时则带引用回复到输入框中。`
161
+ *
162
+ * {@link https://bot.q.qq.com/wiki/develop/api-v2/server-inter/message/trans/text-chain.html}
163
+ */
164
+ markdown: Markdown;
165
+ /** 按钮 */
166
+ keyboard?: Keyboard;
167
+ }
168
+ /** 发送QQ Ark 消息请求参数 */
169
+ interface SendQQArkMessageRequest extends SendQQMessageRequest, QQMessageID {
170
+ msg_type: 3;
171
+ /** ark 消息内容 */
172
+ ark: {
173
+ /** ark 模版id */
174
+ template_id: number;
175
+ /** 模版内变量与填充值的kv映射 tips: 未经测试 先any */
176
+ kv: any[];
177
+ };
178
+ }
179
+ /** 发送QQ Embed 消息请求参数 文档没看到发送接口 */
180
+ /** 发送QQ Media 消息请求参数 */
181
+ interface SendQQMediaMessageRequest extends SendQQMessageRequest, QQMessageID {
182
+ msg_type: 7;
183
+ /** media 消息内容 */
184
+ media: {
185
+ /** 文件信息,用于发消息接口的 media 字段使用 */
186
+ file_info: string;
187
+ };
188
+ /**
189
+ * 按钮。
190
+ *
191
+ * `keyboard` 在官方发消息接口中是与 `content` / `markdown` / `media` 平级的独立字段,
192
+ * 文档未声明它与 `media` 互斥(互斥约束只写在 `content` / `markdown` / `ark` 之间),
193
+ * 接口说明也写明「支持文本/Markdown/富媒体等类型,可附带内嵌键盘」。
194
+ *
195
+ * 用于图片走 QQ 上传兜底(无法进入 markdown)时,让按钮随富媒体一起发出,
196
+ * 避免额外产生一条只有按钮的空消息。若平台拒绝(305007),发送层会去掉
197
+ * keyboard 重试一次,保证富媒体本身能送达。
198
+ */
199
+ keyboard?: Keyboard;
200
+ }
201
+ /** 发送QQ流式消息请求参数(POST /v2/users/{openid}/stream_messages,仅单聊) */
202
+ interface SendQQStreamMessageRequest {
203
+ /**
204
+ * 输入模式:
205
+ * - append 增量追加(默认),content_raw 为本次新增内容
206
+ * - replace 全量替换,content_raw 为全量内容,且必须保持已下发内容前缀不变
207
+ */
208
+ input_mode?: 'append' | 'replace';
209
+ /** 输入状态:1 生成中 / 10 正文结束 */
210
+ input_state: 1 | 10;
211
+ /** 流式序号,从 0 开始逐帧递增,同一次流的 msg_seq 保持一致 */
212
+ index: number;
213
+ /** 内容类型,默认 text */
214
+ content_type?: 'text' | 'markdown';
215
+ /** 内容原文 */
216
+ content_raw: string;
217
+ /** 首帧由服务端生成并返回,后续帧需携带 */
218
+ stream_msg_id?: string;
219
+ /** 前置事件 ID(被动消息,与 msg_id 二选一) */
220
+ event_id?: string;
221
+ /** 前置消息 ID(被动消息,与 event_id 二选一) */
222
+ msg_id?: string;
223
+ /** 回复序号,与 msg_id 联合使用 */
224
+ msg_seq?: number;
225
+ /** 互动召回消息,与 msg_id、event_id 互斥 */
226
+ is_wakeup?: boolean;
227
+ }
228
+ /** 发送QQ流式消息响应 */
229
+ interface SendQQStreamMessageResponse {
230
+ /** 流式消息 ID,后续帧作为 stream_msg_id 携带 */
231
+ id: string;
232
+ /** 发送时间 */
233
+ timestamp: number | string;
234
+ /** 剩余可发送字数 */
235
+ remain_msg_len?: number;
236
+ /** 扩展信息 */
237
+ ext_info?: {
238
+ /** 当前发送消息可被引用时使用的索引 */
239
+ ref_idx?: string;
240
+ };
241
+ }
242
+ /** 发送QQ消息请求参数 */
243
+ type SendQQMsg = SendQQTextMessageRequest | SendQQMarkdownMessageRequest | SendQQArkMessageRequest | SendQQMediaMessageRequest;
244
+ /** 发送频道被动消息参数 */
245
+ interface SendGuildMessageID {
246
+ /** 消息ID */
247
+ msg_id?: string;
248
+ /** 事件id */
249
+ event_id?: string;
250
+ /** 引用消息对象 */
251
+ message_reference?: MessageReference;
252
+ }
253
+ /** 发送频道引用消息参数 */
254
+ interface SendGuildQuoteMessage {
255
+ /** 引用消息的ID */
256
+ message_id?: string;
257
+ /** 是否忽略获取引用消息详情错误,默认否 */
258
+ ignore_get_message_error?: boolean;
259
+ }
260
+ /** 发送频道消息请求参数基类 */
261
+ interface SendGuildMessageRequest {
262
+ /** 单独加一个类型 用于区分不同的消息类型 */
263
+ type: 'text' | 'image' | 'embed' | 'ark' | 'markdown';
264
+ }
265
+ /** 发送频道 文本 消息请求参数 */
266
+ interface SendGuildTextMessageRequest extends SendGuildMessageID, SendGuildQuoteMessage, SendGuildMessageRequest {
267
+ type: 'text';
268
+ /**
269
+ * 消息内容 支持如下内嵌格式
270
+ * - `<@user_id>` `@用户`
271
+ * - `@everyone` `@所有人`
272
+ * - `<#channel_id>` `#子频道`
273
+ * - `<emoji:id>` `表情`
274
+ */
275
+ content: string;
276
+ /** 图片url地址 */
277
+ image?: string;
278
+ }
279
+ /** 发送频道 图片 消息请求参数 */
280
+ interface SendGuildImageMessageRequest extends SendGuildMessageID, SendGuildQuoteMessage, SendGuildMessageRequest {
281
+ type: 'image';
282
+ /** 图片url地址 */
283
+ image: string;
284
+ }
285
+ /** embeds消息结构 */
286
+ interface Embeds {
287
+ /** 标题 */
288
+ title: string;
289
+ /** 消息弹窗内容 */
290
+ prompt: string;
291
+ /** 缩略图 */
292
+ thumbnail: {
293
+ /** 图片地址 */
294
+ url: string;
295
+ };
296
+ /** embed 字段数据 */
297
+ fields: Record<string, any>[];
298
+ }
299
+ /** 发送频道 embed 消息请求参数 */
300
+ interface SendGuildEmbedMessageRequest extends SendGuildMessageID, SendGuildMessageRequest {
301
+ type: 'embed';
302
+ /** embed 消息内容 */
303
+ embed: Embeds;
304
+ }
305
+ /** ark消息结构 */
306
+ interface Ark {
307
+ /** 模版id */
308
+ template_id: number;
309
+ /** 模版内变量与填充值的kv映射 */
310
+ kv: {
311
+ key: string;
312
+ value: string;
313
+ /** 这个嵌套是认真的嘛... */
314
+ obj: {
315
+ obj_kv: {
316
+ key: string;
317
+ value: string;
318
+ }[];
319
+ }[];
320
+ }[];
321
+ }
322
+ /** 发送频道 ark 消息请求参数 */
323
+ interface SendGuildArkMessageRequest extends SendGuildMessageID, SendGuildMessageRequest {
324
+ type: 'ark';
325
+ /** ark 消息内容 */
326
+ ark: Ark;
327
+ }
328
+ /** 发送频道 markdown 消息请求参数 */
329
+ interface SendGuildMarkdownMessageRequest extends SendGuildMessageID, SendGuildMessageRequest {
330
+ type: 'markdown';
331
+ /** markdown 消息内容 */
332
+ markdown: Markdown;
333
+ /** 按钮 */
334
+ keyboard?: Keyboard;
335
+ }
336
+ /** 发送频道消息请求参数 */
337
+ type SendGuildMsg = SendGuildTextMessageRequest | SendGuildImageMessageRequest | SendGuildEmbedMessageRequest | SendGuildArkMessageRequest | SendGuildMarkdownMessageRequest;
338
+ /** 获取当前机器人详情接口响应 */
339
+ interface GetMeResponse {
340
+ /** 机器人的频道ID */
341
+ id: string;
342
+ /** 机器人的昵称 */
343
+ username: string;
344
+ /** 用户头像 */
345
+ avatar: string;
346
+ /** 特殊关联应用的 openid */
347
+ union_openid: string;
348
+ /** 机器人关联的互联应用的用户信息 */
349
+ union_user_account: string;
350
+ /** 机器人的分享url */
351
+ share_url: string;
352
+ /** 机器人介绍 */
353
+ welcome_msg: string;
354
+ }
355
+ /** 创建私信会话接口响应 */
356
+ interface DmsResponse {
357
+ /** 频道ID 用于私信会话使用 */
358
+ guild_id: string;
359
+ /** 子频道ID 用于私信会话使用 */
360
+ channel_id: string;
361
+ /** 创建时间 */
362
+ create_time: string;
363
+ }
364
+ /** 发送QQ消息后响应 */
365
+ interface SendQQMsgResponse {
366
+ /** 消息唯一 ID */
367
+ id: string;
368
+ /** 发送时间 */
369
+ timestamp: number | string;
370
+ /** 扩展信息;部分 QQ 消息发送响应会返回可用于 message_reference 的 REFIDX。 */
371
+ ext_info?: {
372
+ /** 当前发送消息可被引用时使用的索引。 */
373
+ ref_idx?: string;
374
+ };
375
+ }
376
+ /** 获取群基础信息接口响应(GET /v2/groups/{group_openid}/info,白名单接口) */
377
+ interface QQGroupInfoResponse {
378
+ /** 群 openid */
379
+ group_openid: string;
380
+ /** 群名称 */
381
+ group_name: string;
382
+ /** 群简介 */
383
+ group_finger_memo?: string;
384
+ /** 群分类文本 */
385
+ group_class_text?: string;
386
+ /** 群标签 */
387
+ group_tags?: string[];
388
+ /** 群成员人数 */
389
+ group_member_num?: number;
390
+ }
391
+ /** 获取机器人群内状态接口响应(GET /v2/groups/{group_openid}/bot_state,白名单接口) */
392
+ interface GroupBotStateResponse {
393
+ /** 机器人在群内的 member_openid */
394
+ member_openid: string;
395
+ /** 入群时间,RFC3339 格式 */
396
+ joined_at?: string;
397
+ /** 是否允许主动发消息 */
398
+ allow_proactive_msg?: boolean;
399
+ /** 接收消息设置:all / only_mention / mention_and_context */
400
+ recv_msg_setting?: string;
401
+ /** 机器人在群内的角色:owner / admin / member */
402
+ member_role?: 'owner' | 'admin' | 'member';
403
+ }
404
+ /**
405
+ * 获取群成员详情接口响应(GET /v2/groups/{group_openid}/members/{member_openid})
406
+ *
407
+ * 该接口在接口文档 v1.28.0(2026-09-03)转为公开文档,属「内邀接入」的白名单接口,
408
+ * 未获权限时平台返回错误码 11253。官方昵称字段为 `username`,`nick` 是转公开之前
409
+ * 腾讯官方 openclaw 插件(@tencent-connect/openclaw-qqbot v2.0.0)使用的字段名,
410
+ * 保留以兼容旧返回。
411
+ */
412
+ interface QQGroupMemberResponse {
413
+ /** 群成员 openid */
414
+ member_openid?: string;
415
+ /** 用户昵称 */
416
+ username?: string;
417
+ /**
418
+ * 群成员昵称
419
+ * @deprecated 官方公开文档中的字段名是 {@link QQGroupMemberResponse.username}
420
+ */
421
+ nick?: string;
422
+ /** 入群时间,RFC3339 格式 */
423
+ joined_at?: string;
424
+ /** 群内角色:owner / admin / member */
425
+ member_role?: 'owner' | 'admin' | 'member';
426
+ /** 是否机器人 */
427
+ bot?: boolean;
428
+ /** 用户在应用/开放平台下的统一标识(如有) */
429
+ union_openid?: string;
430
+ /** 其余未公开字段原样保留 */
431
+ [key: string]: unknown;
432
+ }
433
+ /** 发送频道消息后响应 */
434
+ interface SendGuildResponse {
435
+ /** 消息唯一 ID */
436
+ id: string;
437
+ /** 发送时间 ISO8601 timestamp */
438
+ timestamp: string;
439
+ }
440
+ /** 上传富媒体文件响应 */
441
+ interface UploadMediaResponse {
442
+ /** 文件 ID */
443
+ file_uuid: string;
444
+ /** 文件信息,用于发消息接口的 media 字段使用 */
445
+ file_info: string;
446
+ /** 有效期,表示剩余多少秒到期,到期后 file_info 失效,当等于 0 时,表示可长期使用 */
447
+ ttl: number;
448
+ /** 发送消息的唯一ID,当srv_send_msg设置为true时返回 */
449
+ id: string;
450
+ /**
451
+ * 文件下载链接(COS 预签名 GET URL),有效期与 `ttl` 一致。
452
+ *
453
+ * 仅分片上传合并(走 `upload_id` 路径)且 `file_type` 为图片/视频/语音时返回;
454
+ * URL 直传和文件类型(`file_type=4`)不返回该字段。
455
+ *
456
+ * 这是把 QQ 分片上传当图床用的关键:拿到该直链后,图片就能以 markdown
457
+ * 图片语法嵌入 msg_type=2,不必再走 msg_type=7 富媒体单独发送。
458
+ */
459
+ raw_url?: string;
460
+ }
461
+ /** 申请上传 Markdown 素材图片(POST /v2/media-images/prepare) */
462
+ interface MediaImagePrepareRequest {
463
+ /** 文件名(含扩展名) */
464
+ file_name: string;
465
+ /** 文件大小(字节) */
466
+ file_size: number;
467
+ /** 图片 MIME 类型:image/png / image/jpeg / image/gif / image/webp */
468
+ content_type: string;
469
+ /** 文件内容 MD5(32 位十六进制) */
470
+ md5: string;
471
+ /** 文件内容 SHA1(40 位十六进制) */
472
+ sha1: string;
473
+ }
474
+ /** 申请上传 Markdown 素材图片的响应 */
475
+ interface MediaImagePrepareResponse {
476
+ /** 上传任务 ID,4 小时内有效 */
477
+ upload_id: string;
478
+ /** 预签名上传 URL,使用 HTTP PUT 直传图片二进制 */
479
+ presigned_url: string;
480
+ /** 预签名 URL 有效期(秒) */
481
+ expires_in: number;
482
+ }
483
+ /** 完成 Markdown 素材图片上传(POST /v2/media-images/complete) */
484
+ interface MediaImageCompleteRequest {
485
+ /** prepare 返回的上传任务 ID */
486
+ upload_id: string;
487
+ /** 文件 MD5(32 位十六进制),服务端会与 COS 对象实际 ETag 比对 */
488
+ md5: string;
489
+ }
490
+ /** 完成 Markdown 素材图片上传的响应 */
491
+ interface MediaImageCompleteResponse {
492
+ /** 图片 ID,用于查询与删除 */
493
+ image_id: string;
494
+ /** Markdown 引用链接:`qqbot-media://image/v1/<token>` */
495
+ url: string;
496
+ /** 滑动有效期窗口(秒) */
497
+ ttl: number;
498
+ /** 临时预览链接,短时效,请勿持久化存储 */
499
+ preview_url?: string;
500
+ }
501
+ /** 查询 Markdown 素材图片列表的查询参数 */
502
+ interface MediaImageListParams {
503
+ /** 翻页游标;首页不传,末页返回空字符串 */
504
+ cursor?: string;
505
+ }
506
+ /** Markdown 素材图片列表项 */
507
+ interface MediaImageItem {
508
+ image_id: string;
509
+ url: string;
510
+ file_name: string;
511
+ preview_url?: string;
512
+ created_at: number;
513
+ expires_at: number;
514
+ }
515
+ /** 查询 Markdown 素材图片列表的响应 */
516
+ interface MediaImageListResponse {
517
+ images: MediaImageItem[];
518
+ next_cursor: string;
519
+ total: number;
520
+ }
521
+ /** 自定义菜单按钮类型 */
522
+ type MenuItemType = 'switch' | 'send_message' | 'link' | 'menu';
523
+ /** 自定义菜单开关配置(仅 type=switch 时有效) */
524
+ interface MenuSwitch {
525
+ /**
526
+ * 开关唯一标识
527
+ *
528
+ * 用户切换开关状态后会发送一条消息,消息 `ext` 字段中携带 `{switch_id}=1`;
529
+ * 关闭后不携带该标识。
530
+ */
531
+ switch_id?: string;
532
+ /** 开关的初始状态,true 默认打开 */
533
+ default?: boolean;
534
+ }
535
+ /** 自定义菜单二级菜单项(不支持再嵌套子菜单) */
536
+ interface SubMenuItem {
537
+ /** 按钮名称,最多 14 个字符(约 7 个中文汉字) */
538
+ name?: string;
539
+ /** 按钮类型,二级菜单仅支持 send_message / link */
540
+ type?: Extract<MenuItemType, 'send_message' | 'link'>;
541
+ /** 发送的内容,仅 type=send_message 时有效,用户点击后自动填入输入框 */
542
+ send_message?: string;
543
+ /** 跳转链接,仅 type=link 时有效,必须以 https:// 开头 */
544
+ link?: string;
545
+ }
546
+ /** 自定义菜单一级菜单项 */
547
+ interface MenuItem {
548
+ /** 按钮名称,最多 10 个字符(一个中文汉字算 2 个字符) */
549
+ name?: string;
550
+ /** 按钮类型 */
551
+ type?: MenuItemType;
552
+ /** 子菜单列表,仅 type=menu 时有效,最多 5 个 */
553
+ sub_menu_items?: SubMenuItem[];
554
+ /** 发送的内容,仅 type=send_message 时有效,用户点击后自动填入输入框 */
555
+ send_message?: string;
556
+ /** 跳转链接,仅 type=link 时有效,必须以 https:// 开头 */
557
+ link?: string;
558
+ /** 开关配置,仅 type=switch 时有效 */
559
+ switch?: MenuSwitch;
560
+ }
561
+ /** 自定义菜单配置 */
562
+ interface Menu {
563
+ /** 菜单项列表,最多 10 个,按列表顺序从左到右展示 */
564
+ items?: MenuItem[];
565
+ }
566
+ /** 查询全局自定义菜单响应(GET /v2/menu) */
567
+ interface GetMenuResponse {
568
+ /** 当前菜单的版本号 */
569
+ version: number;
570
+ /** 当前生效的菜单配置;未设置过菜单时该字段为空 */
571
+ menu?: Menu;
572
+ }
573
+ /** 修改全局自定义菜单响应(PUT /v2/menu) */
574
+ interface UpdateMenuResponse {
575
+ /** 本次修改后的菜单版本号,可用于后续判断配置是否有变更 */
576
+ version: number;
577
+ }
578
+ /** 指令面板生效场景:c2c 单聊 / group 群聊 / channel 文字子频道 / dm 频道私信 */
579
+ type PanelScope = 'c2c' | 'group' | 'channel' | 'dm';
580
+ /** 指令面板作用范围:all 全局生效 / specific 指定用户或群生效 */
581
+ type PanelTargetType = 'all' | 'specific';
582
+ /** 指令面板元素类型 */
583
+ type PanelItemType = 'command' | 'link';
584
+ /** 指令面板元素 */
585
+ interface PanelItem {
586
+ /**
587
+ * 元素名称,最多 14 个字符(约 7 个中文汉字)
588
+ *
589
+ * type=command 时用户点击后该内容会填入聊天输入框;type=link 时仅用于面板展示。
590
+ */
591
+ name?: string;
592
+ /** 元素描述,最多 30 个字符(约 15 个中文汉字),在面板中展示给用户 */
593
+ desc?: string;
594
+ /** 元素类型 */
595
+ type?: PanelItemType;
596
+ /** 是否仅管理员可操作,true 时仅频道/群管理员可点击 */
597
+ only_admin?: boolean;
598
+ /** 跳转链接,仅 type=link 时有效,必须以 https:// 开头 */
599
+ link?: string;
600
+ }
601
+ /** 指令面板配置内容 */
602
+ interface Panel {
603
+ /** 面板元素列表,一个面板最多配置 20 个元素 */
604
+ items?: PanelItem[];
605
+ /** 面板备注,最多 255 个字符,不对用户展示 */
606
+ remark?: string;
607
+ /** 当前版本号 */
608
+ version?: number;
609
+ }
610
+ /** 查询指令面板列表查询参数(GET /v2/panels) */
611
+ interface GetPanelListParams {
612
+ /** 生效场景,必填 */
613
+ scope: PanelScope;
614
+ /** 分页游标,首次请求不传或传空串,后续传上次响应的 next_cursor */
615
+ cursor?: string;
616
+ /** 每页拉取条数,默认 20,最大 50 */
617
+ limit?: number;
618
+ }
619
+ /** 指令面板记录 */
620
+ interface PanelRecord {
621
+ /** 面板 ID */
622
+ panel_id: string;
623
+ /** 生效场景 */
624
+ scope: PanelScope;
625
+ /** 作用范围,仅 c2c/group 场景可能为 specific */
626
+ target_type: PanelTargetType;
627
+ /** 面板配置内容 */
628
+ panel: Panel;
629
+ /** 面板创建时间,RFC3339 格式 */
630
+ created_at?: string;
631
+ /** 面板更新时间,RFC3339 格式 */
632
+ updated_at?: string;
633
+ /** 面板版本号 */
634
+ version: number;
635
+ }
636
+ /** 查询指令面板列表响应(GET /v2/panels) */
637
+ interface GetPanelListResponse {
638
+ /** 面板记录列表,按设置时间倒序排列 */
639
+ records: PanelRecord[];
640
+ /** 下一页游标,空串表示已到最后一页 */
641
+ next_cursor: string;
642
+ /** 是否已拉取到最后一页 */
643
+ is_end: boolean;
644
+ }
645
+ /** 创建指令面板请求体(POST /v2/panels) */
646
+ interface CreatePanelRequest {
647
+ /** 生效场景,channel / dm 场景 target_type 只能为 all */
648
+ scope: PanelScope;
649
+ /** 作用范围,仅 c2c / group 场景支持 specific */
650
+ target_type?: PanelTargetType;
651
+ /** 用户 openid 列表,仅 c2c 场景且 target_type=specific 时有效,一次最多 20 个 */
652
+ user_openids?: string[];
653
+ /** 群 openid 列表,仅 group 场景且 target_type=specific 时有效,一次最多 20 个 */
654
+ group_openids?: string[];
655
+ /** 面板配置内容 */
656
+ panel: Panel;
657
+ }
658
+ /** 创建指令面板响应(POST /v2/panels) */
659
+ interface CreatePanelResponse {
660
+ /** 新创建的面板 ID,后续修改、删除、查询详情均需使用此 ID */
661
+ panel_id: string;
662
+ }
663
+ /** 查询指令面板详情响应(GET /v2/panels/{panel_id}) */
664
+ interface GetPanelResponse extends PanelRecord {
665
+ /** 关联的用户 openid 列表,仅 c2c 场景且 target_type=specific 时返回,最多 1000 条 */
666
+ user_openids?: string[];
667
+ /** 关联的群 openid 列表,仅 group 场景且 target_type=specific 时返回,最多 1000 条 */
668
+ group_openids?: string[];
669
+ }
670
+ /** 修改指令面板响应(PUT /v2/panels/{panel_id}) */
671
+ interface UpdatePanelResponse {
672
+ /** 本次修改后的面板版本号 */
673
+ version: number;
674
+ }
675
+ /** 修改指令面板关联对象请求体(PUT /v2/panels/{panel_id}/target) */
676
+ interface UpdatePanelTargetRequest {
677
+ /** 操作类型:add 添加关联对象 / del 移除关联对象 */
678
+ op: 'add' | 'del';
679
+ /** 用户 openid 列表,仅 c2c 场景有效,一次最多 20 个 */
680
+ user_openids?: string[];
681
+ /** 群 openid 列表,仅 group 场景有效,一次最多 20 个 */
682
+ group_openids?: string[];
683
+ }
684
+ /** 频道信息 */
685
+ interface GuildInfo {
686
+ /** 频道 ID */
687
+ id: string;
688
+ /** 频道名称 */
689
+ name: string;
690
+ /** 频道头像 URL */
691
+ icon?: string;
692
+ /** 频道创建者 ID */
693
+ owner_id?: string;
694
+ /** 当前机器人是否为频道创建者 */
695
+ owner?: boolean;
696
+ /** 加入时间,ISO8601 格式 */
697
+ joined_at?: string;
698
+ /** 频道成员数 */
699
+ member_count?: number;
700
+ /** 频道成员上限 */
701
+ max_members?: number;
702
+ /** 频道简介 */
703
+ description?: string;
704
+ }
705
+ /** 获取机器人加入的频道列表查询参数(GET /users/@me/guilds) */
706
+ interface GetGuildListParams {
707
+ /** 读取此 guild_id 之前的数据,设置时先反序再分页 */
708
+ before?: string;
709
+ /** 读取此 guild_id 之后的数据,与 before 同时设置时 after 无效 */
710
+ after?: string;
711
+ /** 每次拉取条数,默认 100,最大 100 */
712
+ limit?: number;
713
+ }
714
+ /** 子频道类型:0=文字,2=语音,4=分组,10005=直播,10006=应用,10007=论坛 */
715
+ type ChannelType = 0 | 2 | 4 | 10005 | 10006 | 10007;
716
+ /** 文字子频道子类型:0=闲聊,1=公告,2=攻略,3=开黑 */
717
+ type ChannelSubType = 0 | 1 | 2 | 3;
718
+ /** 子频道私密类型:0=公开,1=群主管理员可见,2=群主管理员+指定成员 */
719
+ type ChannelPrivateType = 0 | 1 | 2;
720
+ /** 子频道发言权限:0=无效,1=所有人,2=群主管理员+指定成员 */
721
+ type ChannelSpeakPermission = 0 | 1 | 2;
722
+ /** 子频道信息 */
723
+ interface ChannelInfo {
724
+ /** 子频道 ID */
725
+ id: string;
726
+ /** 所属频道 ID */
727
+ guild_id: string;
728
+ /** 子频道名 */
729
+ name: string;
730
+ /** 子频道类型 */
731
+ type: ChannelType;
732
+ /** 子频道子类型(文字子频道) */
733
+ sub_type?: ChannelSubType;
734
+ /** 排序值,从 1 开始 */
735
+ position?: number;
736
+ /** 所属分组 ID(仅子频道有效) */
737
+ parent_id?: string;
738
+ /** 创建人 ID */
739
+ owner_id?: string;
740
+ /** 子频道私密类型 */
741
+ private_type?: ChannelPrivateType;
742
+ /** 子频道发言权限 */
743
+ speak_permission?: ChannelSpeakPermission;
744
+ /** 应用子频道标识 */
745
+ application_id?: string;
746
+ /** 用户拥有的子频道权限 */
747
+ permissions?: string;
748
+ }
749
+ /** 创建子频道请求体(POST /guilds/{guild_id}/channels) */
750
+ interface CreateChannelRequest {
751
+ /** 子频道名称 */
752
+ name?: string;
753
+ /** 子频道类型 */
754
+ type?: ChannelType;
755
+ /** 子频道子类型 */
756
+ sub_type?: ChannelSubType;
757
+ /** 排序值(分组类型必须 >= 2) */
758
+ position?: number;
759
+ /** 所属分组 ID */
760
+ parent_id?: string;
761
+ /** 私密类型 */
762
+ private_type?: ChannelPrivateType;
763
+ /** 私密成员 ID 列表 */
764
+ private_user_ids?: string[];
765
+ /** 发言权限 */
766
+ speak_permission?: ChannelSpeakPermission;
767
+ /** 应用子频道 AppID */
768
+ application_id?: string;
769
+ }
770
+ /** 修改子频道请求体(PATCH /channels/{channel_id}),只需传入要修改的字段 */
771
+ interface UpdateChannelRequest {
772
+ /** 子频道名 */
773
+ name?: string;
774
+ /** 排序 */
775
+ position?: number;
776
+ /** 分组 ID */
777
+ parent_id?: string;
778
+ /** 私密类型 */
779
+ private_type?: ChannelPrivateType;
780
+ /** 发言权限 */
781
+ speak_permission?: ChannelSpeakPermission;
782
+ }
783
+ /** 生成分享链接请求体(POST /v2/generate_url_link) */
784
+ interface GenerateUrlLinkRequest {
785
+ /**
786
+ * 开发者自定义回调数据,最长 32 字符
787
+ *
788
+ * 用户通过该链接添加机器人时会透传回 `FRIEND_ADD` 事件的 `scene_param`。
789
+ */
790
+ callback_data?: string;
791
+ }
792
+ /** 生成分享链接响应(POST /v2/generate_url_link) */
793
+ interface GenerateUrlLinkResponse {
794
+ /** 接口返回数据 */
795
+ data: {
796
+ /** 生成的分享链接 */
797
+ url: string;
798
+ };
799
+ }
800
+ /** 全员禁言模式:none 未开启 / always 始终禁言 / schedule 定时或周期性禁言 */
801
+ type GroupMuteMode = 'none' | 'always' | 'schedule';
802
+ /** 定时禁言规则 */
803
+ interface MuteScheduleRule {
804
+ /** 任务 ID */
805
+ task_id: string;
806
+ /** 禁言开始时间(RFC3339 格式) */
807
+ start_at: string;
808
+ /** 禁言结束时间(RFC3339 格式) */
809
+ end_at: string;
810
+ /** 此规则是否启用 */
811
+ enabled: boolean;
812
+ }
813
+ /** 周期禁言规则 */
814
+ interface MuteRecurringRule {
815
+ /** 任务 ID */
816
+ task_id: string;
817
+ /** 生效星期几列表,取值 1~7(1=周一,7=周日) */
818
+ weekdays: number[];
819
+ /** 时段开始时间,格式 HH:mm(北京时间) */
820
+ start_time: string;
821
+ /** 时段结束时间,格式 HH:mm(北京时间);小于 start_time 表示跨天到次日 */
822
+ end_time: string;
823
+ /** 此规则是否启用 */
824
+ enabled: boolean;
825
+ }
826
+ /** 群级禁言规则(全员禁言配置) */
827
+ interface GlobalMuteRule {
828
+ /** 全员禁言模式 */
829
+ mode: GroupMuteMode;
830
+ /** 定时禁言规则列表 */
831
+ schedule_rules?: MuteScheduleRule[];
832
+ /** 周期禁言规则列表 */
833
+ recurring_rules?: MuteRecurringRule[];
834
+ }
835
+ /** 成员禁言状态 */
836
+ interface MemberMuteState {
837
+ /** 被禁言成员的 openid */
838
+ member_openid: string;
839
+ /** 禁言到期时间(RFC3339 格式) */
840
+ mute_expire_at: string;
841
+ /** 被禁言成员的昵称 */
842
+ username?: string;
843
+ /** 用户在应用/开放平台下的统一标识 */
844
+ union_openid?: string;
845
+ }
846
+ /**
847
+ * 设置成员禁言项(POST /v2/groups/{group_openid}/restrict_chat_setting)
848
+ *
849
+ * 单次请求最多 20 项(接口文档 v1.28.0 由 10 提升至 20)。
850
+ */
851
+ interface SetMemberMuteState {
852
+ /** 操作类型:add 增加禁言,update 更新禁言到期时间,del 解除禁言 */
853
+ op: 'add' | 'update' | 'del';
854
+ /** 被禁言成员的 openid;增加 / 更新时只能操作普通成员,不能操作群主、管理员、机器人 */
855
+ member_openid: string;
856
+ /** 禁言到期时间(RFC3339 格式);op=del 时可传空串表示立即解除禁言 */
857
+ mute_expire_at?: string;
858
+ }
859
+ /** 查询群禁言状态响应(GET /v2/groups/{group_openid}/restrict_chat_setting) */
860
+ interface GetGroupMuteSettingResponse {
861
+ /** 群级禁言规则 */
862
+ global_rule?: GlobalMuteRule;
863
+ /** 当前处于禁言中的用户列表(不含已过期) */
864
+ members?: MemberMuteState[];
865
+ }
866
+ /** 入群验证方式 */
867
+ interface JoinRequestVerifyInfo {
868
+ /** 入群验证方式 */
869
+ method: 'verify_message' | 'admin_review_qa';
870
+ /** 验证消息内容,仅 method=verify_message 时可能携带 */
871
+ verify_message?: string;
872
+ /** 问答列表,仅 method=admin_review_qa 时可能携带 */
873
+ review_qa_list?: {
874
+ /** 管理员设置的问题 */
875
+ question: string;
876
+ /** 申请人填写的答案 */
877
+ answer: string;
878
+ }[];
879
+ }
880
+ /** 入群申请 */
881
+ interface JoinRequest {
882
+ /** 申请 ID,需要在审批接口回传 */
883
+ join_request_id: string;
884
+ /** 安全提示语 */
885
+ risk_tips?: string;
886
+ /** 用户在应用/开放平台下的统一标识 */
887
+ union_openid?: string;
888
+ /** 申请人 openid */
889
+ member_openid: string;
890
+ /** 申请人昵称 */
891
+ username?: string;
892
+ /** 申请时间戳(RFC3339 格式) */
893
+ apply_at?: string;
894
+ /** 申请来源:self_apply 主动申请,invited 被邀请 */
895
+ apply_source?: 'self_apply' | 'invited';
896
+ /** 邀请人 openid(apply_source=invited 时有效) */
897
+ invited_by?: string;
898
+ /** 是否为机器人账号 */
899
+ bot?: boolean;
900
+ /** 用户入群验证方式 */
901
+ verify_info?: JoinRequestVerifyInfo;
902
+ }
903
+ /** 入群申请列表查询参数(GET /v2/groups/{group_openid}/join_request_list) */
904
+ interface GetJoinRequestListParams {
905
+ /** 分页游标,首次请求可不传或传空串 */
906
+ cursor?: string;
907
+ /** 单页数量,默认 20,最大 50 */
908
+ limit?: number;
909
+ }
910
+ /** 入群申请列表响应(GET /v2/groups/{group_openid}/join_request_list) */
911
+ interface GetJoinRequestListResponse {
912
+ /** 入群申请列表 */
913
+ list: JoinRequest[];
914
+ /** 下一页游标,空串表示已到末页 */
915
+ next_cursor: string;
916
+ }
917
+ /** 入群申请审批请求体(POST /v2/groups/{group_openid}/approval_join_request/{member_openid}) */
918
+ interface ApprovalJoinRequestBody {
919
+ /** 审批动作:approve 通过,decline 拒绝 */
920
+ op: 'approve' | 'decline';
921
+ /** 申请 ID */
922
+ join_request_id?: string;
923
+ /** 拒绝理由,op=decline 时可填 */
924
+ reject_reason?: string;
925
+ /** 是否同时加入群黑名单,默认 false,op=decline 时可填 */
926
+ add_to_member_blacklist?: boolean;
927
+ }
928
+ /** 群成员(GET /v2/groups/{group_openid}/members 列表项) */
929
+ interface GroupMemberItem {
930
+ /** 成员 openid */
931
+ member_openid: string;
932
+ /** 用户昵称 */
933
+ username?: string;
934
+ /** 群成员角色:member 普通成员 / owner 群主 / admin 管理员 */
935
+ member_role?: 'owner' | 'admin' | 'member';
936
+ /** 是否机器人 */
937
+ bot?: boolean;
938
+ /** 入群时间戳(RFC3339 格式) */
939
+ joined_at?: string;
940
+ /** 用户在应用/开放平台下的统一标识(如有) */
941
+ union_openid?: string;
942
+ }
943
+ /** 群成员列表查询参数(GET /v2/groups/{group_openid}/members) */
944
+ interface GetGroupMemberListParams {
945
+ /** 分页游标,首次请求可不传或传空串;后续传上一次响应的 next_cursor */
946
+ cursor?: string;
947
+ }
948
+ /** 群成员列表响应(GET /v2/groups/{group_openid}/members) */
949
+ interface GetGroupMemberListResponse {
950
+ /** 成员列表,每次最多返回 30 条 */
951
+ members: GroupMemberItem[];
952
+ /** 下一页游标,空串表示已到末页 */
953
+ next_cursor: string;
954
+ }
955
+ /** 群成员批量移除请求体(POST /v2/groups/{group_openid}/batch_remove_members) */
956
+ interface BatchRemoveGroupMembersBody {
957
+ /** 需要移除的成员 member_openid 列表,单次最多 20 个 */
958
+ member_openids: string[];
959
+ /** 是否同时加入群黑名单,默认 false */
960
+ add_to_member_blacklist?: boolean;
961
+ }
962
+ /** 群成员批量移除响应 */
963
+ interface BatchRemoveGroupMembersResponse {
964
+ /** 成功时返回 success */
965
+ remove_members_result?: string;
966
+ /** 拉黑失败的 openid */
967
+ add_to_member_blacklist_fail_openids?: string[];
968
+ }
969
+ /** 群黑名单用户(GET /v2/groups/{group_openid}/member_blacklist 列表项) */
970
+ interface GroupBlacklistUser {
971
+ /** 用户在应用/开放平台下的统一标识(如有) */
972
+ union_openid?: string;
973
+ /** 用户 openid */
974
+ member_openid: string;
975
+ /** 用户昵称 */
976
+ username?: string;
977
+ /** 拉黑时间戳(RFC3339 格式) */
978
+ banned_at?: string;
979
+ /** 是否为机器人账号 */
980
+ bot?: boolean;
981
+ }
982
+ /** 群黑名单查询参数(GET /v2/groups/{group_openid}/member_blacklist) */
983
+ interface GetGroupMemberBlacklistParams {
984
+ /** 分页游标,首次请求可不传或传空串 */
985
+ cursor?: string;
986
+ /** 单页数量,默认 20,最大 100 */
987
+ limit?: number;
988
+ }
989
+ /** 群黑名单查询响应(GET /v2/groups/{group_openid}/member_blacklist) */
990
+ interface GetGroupMemberBlacklistResponse {
991
+ /** 黑名单用户列表 */
992
+ users: GroupBlacklistUser[];
993
+ /** 下一页游标,空串表示已到末页 */
994
+ next_cursor: string;
995
+ }
996
+ /** 群黑名单操作请求体(POST /v2/groups/{group_openid}/member_blacklist) */
997
+ interface SetGroupMemberBlacklistBody {
998
+ /** 操作类型:add 加入黑名单(目标成员在群中时无法加入),del 移出黑名单 */
999
+ op: 'add' | 'del';
1000
+ /** 目标成员 openid 列表,单次最多 20 个 */
1001
+ member_openids: string[];
1002
+ }
1003
+ /** 群黑名单操作响应 */
1004
+ interface SetGroupMemberBlacklistResponse {
1005
+ /** 操作失败的 openid 列表,op=add / op=del 同义 */
1006
+ fail_openids?: string[];
1007
+ }
1008
+ /** 入群自动审批策略 */
1009
+ interface JoinApprovalStrategy {
1010
+ /** 策略 ID */
1011
+ strategy_id: string;
1012
+ /** 关联的群 openid 列表(创建时使用 group_openids 时返回) */
1013
+ group_openids?: string[];
1014
+ /** 关联的 QQ 群号列表(创建时使用 group_ids 时返回) */
1015
+ group_ids?: string[];
1016
+ /** 白名单中的号码数量(估算,可能存在少量误差) */
1017
+ whitelist_user_count?: number;
1018
+ /** 策略是否启用:on 启用 / off 关闭 */
1019
+ is_enable: 'on' | 'off';
1020
+ /** 过期时间(RFC3339 格式) */
1021
+ expire_at?: string;
1022
+ /** 创建时间(RFC3339 格式) */
1023
+ created_at?: string;
1024
+ /** 最近更新时间(RFC3339 格式) */
1025
+ updated_at?: string;
1026
+ /** 策略备注 */
1027
+ remark?: string;
1028
+ }
1029
+ /** 查询入群自动审批策略列表查询参数(GET /v2/groups/join_approval_strategy) */
1030
+ interface GetJoinApprovalStrategyListParams {
1031
+ /** 分页游标,首次请求可不传或传空串 */
1032
+ cursor?: string;
1033
+ /** 单页数量,默认 20,最大 50 */
1034
+ limit?: number;
1035
+ }
1036
+ /** 查询入群自动审批策略列表响应 */
1037
+ interface GetJoinApprovalStrategyListResponse {
1038
+ /** 生效中的策略列表 */
1039
+ strategies: JoinApprovalStrategy[];
1040
+ /** 下一页游标,空串表示已到末页 */
1041
+ next_cursor: string;
1042
+ }
1043
+ /** 创建入群自动审批策略请求体(POST /v2/groups/join_approval_strategy) */
1044
+ interface CreateJoinApprovalStrategyRequest {
1045
+ /** 关联的群 openid 列表,最多 100 个;与 group_ids 互斥且二选一必填 */
1046
+ group_openids?: string[];
1047
+ /** 关联的 QQ 群号列表,最多 100 个;与 group_openids 互斥且二选一必填 */
1048
+ group_ids?: string[];
1049
+ /** 是否启用策略,默认 on */
1050
+ is_enable?: 'on' | 'off';
1051
+ /** 过期时间(RFC3339 格式),不传默认一年过期 */
1052
+ expire_at?: string;
1053
+ /** 策略备注,最多 255 个汉字 */
1054
+ remark?: string;
1055
+ }
1056
+ /** 创建入群自动审批策略响应 */
1057
+ interface CreateJoinApprovalStrategyResponse {
1058
+ /** 服务端生成的策略 ID */
1059
+ strategy_id: string;
1060
+ /** 是否启用 */
1061
+ is_enable: 'on' | 'off';
1062
+ /** 过期时间(RFC3339 格式) */
1063
+ expire_at?: string;
1064
+ }
1065
+ /** 修改入群自动审批策略请求体(PATCH /v2/groups/join_approval_strategy/{strategy_id}) */
1066
+ interface UpdateJoinApprovalStrategyRequest {
1067
+ /** 是否启用策略 */
1068
+ is_enable?: 'on' | 'off';
1069
+ /** 过期时间(RFC3339 格式) */
1070
+ expire_at?: string;
1071
+ /** 关联群增删操作;群标识形式须与创建时一致 */
1072
+ group_action?: {
1073
+ /** 操作类型:add 新增关联群,del 删除关联群 */
1074
+ op: 'add' | 'del';
1075
+ /** 待操作的群 openid 列表;与 group_ids 互斥 */
1076
+ group_openids?: string[];
1077
+ /** 待操作的 QQ 群号列表;与 group_openids 互斥 */
1078
+ group_ids?: string[];
1079
+ };
1080
+ /** 策略备注,最多 255 个汉字 */
1081
+ remark?: string;
1082
+ }
1083
+ /** 修改入群自动审批策略响应 */
1084
+ interface UpdateJoinApprovalStrategyResponse {
1085
+ /** 是否启用 */
1086
+ is_enable: 'on' | 'off';
1087
+ /** 过期时间(RFC3339 格式) */
1088
+ expire_at?: string;
1089
+ }
1090
+ /** 修改策略白名单号码请求体(POST /v2/groups/join_approval_strategy/{strategy_id}/whitelist_users) */
1091
+ interface UpdateWhitelistUsersRequest {
1092
+ /** 操作类型:add 新增号码,del 删除号码 */
1093
+ op: 'add' | 'del';
1094
+ /** QQ 号码列表,单次最多 10000 个;使用字符串类型避免 JS 精度问题 */
1095
+ whitelist_users: string[];
1096
+ }
1097
+ /** 修改策略白名单号码响应 */
1098
+ interface UpdateWhitelistUsersResponse {
1099
+ /** 策略 ID */
1100
+ strategy_id: string;
1101
+ /** 操作后策略当前白名单号码数(估算) */
1102
+ whitelist_user_count: number;
1103
+ /** 策略更新时间(RFC3339 格式) */
1104
+ updated_at?: string;
1105
+ }
1106
+ //#endregion
1107
+ //#region src/core/internal/axios.d.ts
1108
+ /**
1109
+ * 创建 axios 实例,自动从 tokens map 取最新 access_token
1110
+ */
1111
+ declare const createAxiosInstance: (appId: string) => import("node-karin/axios").AxiosInstance;
1112
+ //#endregion
1113
+ //#region src/core/api/http.d.ts
1114
+ type AxiosInstance = ReturnType<typeof createAxiosInstance>;
1115
+ /**
1116
+ * 单次请求的可选配置。
1117
+ *
1118
+ * 这是 axios 请求配置的常用子集;需要完整能力时用
1119
+ * {@link Http.request} 或直接使用 `axios` 实例。
1120
+ */
1121
+ interface RequestOptions {
1122
+ /** 追加请求头,会与实例默认头合并 */
1123
+ headers?: Record<string, string>;
1124
+ /** 超时毫秒数,默认取实例配置(5500ms) */
1125
+ timeout?: number;
1126
+ /** query 参数,axios 会自动序列化后拼到 URL */
1127
+ params?: Record<string, unknown>;
1128
+ /** 中断信号 */
1129
+ signal?: AbortSignal;
1130
+ /** 响应类型,下载二进制时可传 `arraybuffer` */
1131
+ responseType?: AxiosRequestConfig['responseType'];
1132
+ }
1133
+ /**
1134
+ * Http 基础类,子模块继承此类共享 axios 实例与错误格式化
1135
+ *
1136
+ * 各请求方法均为 `protected`,只供各领域 API 子类内部使用;
1137
+ * 需要给下游插件开放的裸请求入口见 {@link RequestApi}。
1138
+ */
1139
+ declare class Http {
1140
+ readonly axios: AxiosInstance;
1141
+ constructor(axios: AxiosInstance);
1142
+ protected get<T>(path: string, options?: RequestOptions): Promise<T>;
1143
+ protected post<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1144
+ protected put<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1145
+ protected patch<T>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1146
+ protected delete<T>(path: string, options?: RequestOptions): Promise<T>;
1147
+ /**
1148
+ * 任意 method 的裸请求,返回响应体。
1149
+ *
1150
+ * @param config axios 请求配置,`url` 相对 `baseURL`。
1151
+ * @returns 响应体 `data`。
1152
+ */
1153
+ protected request<T>(config: AxiosRequestConfig): Promise<T>;
1154
+ /**
1155
+ * 任意 method 的裸请求,返回完整 axios 响应。
1156
+ *
1157
+ * 需要读取响应头或状态码时使用。
1158
+ *
1159
+ * @param config axios 请求配置,`url` 相对 `baseURL`。
1160
+ * @returns 完整 axios 响应。
1161
+ */
1162
+ protected requestRaw<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
1163
+ }
1164
+ //#endregion
1165
+ //#region src/core/api/request.d.ts
1166
+ /**
1167
+ * 裸请求入口,供下游插件直接调用官方 OpenAPI。
1168
+ *
1169
+ * {@link Http} 的请求方法是 `protected`,只供各领域 API 子类内部使用;
1170
+ * 本类把同一套方法以 `public` 暴露出来,用于官方新接口尚未被适配器封装、
1171
+ * 或需要传自定义参数的场景:
1172
+ *
1173
+ * ```ts
1174
+ * const bot = e.bot as AdapterQQBot
1175
+ *
1176
+ * // GET,query 走 params
1177
+ * const menu = await bot.super.request.get('/v2/menu')
1178
+ * const list = await bot.super.request.get('/v2/panels', { params: { scope: 'group', limit: 20 } })
1179
+ *
1180
+ * // POST / PUT / PATCH / DELETE
1181
+ * await bot.super.request.post(`/v2/groups/${groupId}/messages`, { content: 'hi', msg_type: 0 })
1182
+ * await bot.super.request.put('/v2/menu', { menu })
1183
+ *
1184
+ * // 任意 method
1185
+ * await bot.super.request.request({ method: 'POST', url: '/v2/xxx', data: {} })
1186
+ * ```
1187
+ *
1188
+ * 与直接用 `bot.super.axios` 的区别:
1189
+ * - 自动解包 `response.data`;
1190
+ * - 失败时抛出的 Error 已带请求路径、脱敏请求体、QQ 错误码中文描述和 TraceID。
1191
+ *
1192
+ * 需要读响应头或状态码时用 {@link RequestApi.requestRaw};
1193
+ * 需要完全裸的 axios 时用 `bot.super.axios`。
1194
+ *
1195
+ * 路径相对官方 API baseURL,鉴权头由拦截器自动注入,无需自己传 Authorization。
1196
+ */
1197
+ declare class RequestApi extends Http {
1198
+ /**
1199
+ * GET 请求。
1200
+ *
1201
+ * @param path 接口路径,相对 baseURL。
1202
+ * @param options 可选配置(params / headers / timeout 等)。
1203
+ * @returns 响应体。
1204
+ */
1205
+ get<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
1206
+ /**
1207
+ * POST 请求。
1208
+ *
1209
+ * @param path 接口路径,相对 baseURL。
1210
+ * @param body 请求体,默认空对象。
1211
+ * @param options 可选配置(params / headers / timeout 等)。
1212
+ * @returns 响应体。
1213
+ */
1214
+ post<T = unknown>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1215
+ /**
1216
+ * PUT 请求。
1217
+ *
1218
+ * @param path 接口路径,相对 baseURL。
1219
+ * @param body 请求体,默认空对象。
1220
+ * @param options 可选配置(params / headers / timeout 等)。
1221
+ * @returns 响应体。
1222
+ */
1223
+ put<T = unknown>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1224
+ /**
1225
+ * PATCH 请求。
1226
+ *
1227
+ * @param path 接口路径,相对 baseURL。
1228
+ * @param body 请求体,默认空对象。
1229
+ * @param options 可选配置(params / headers / timeout 等)。
1230
+ * @returns 响应体。
1231
+ */
1232
+ patch<T = unknown>(path: string, body?: unknown, options?: RequestOptions): Promise<T>;
1233
+ /**
1234
+ * DELETE 请求。
1235
+ *
1236
+ * @param path 接口路径,相对 baseURL。
1237
+ * @param options 可选配置(params / headers / timeout 等)。
1238
+ * @returns 响应体。
1239
+ */
1240
+ delete<T = unknown>(path: string, options?: RequestOptions): Promise<T>;
1241
+ /**
1242
+ * 任意 method 的请求,返回响应体。
1243
+ *
1244
+ * @param config axios 请求配置,`url` 相对 baseURL。
1245
+ * @returns 响应体。
1246
+ */
1247
+ request<T = unknown>(config: AxiosRequestConfig): Promise<T>;
1248
+ /**
1249
+ * 任意 method 的请求,返回完整 axios 响应。
1250
+ *
1251
+ * 需要读取响应头或状态码时使用。
1252
+ *
1253
+ * @param config axios 请求配置,`url` 相对 baseURL。
1254
+ * @returns 完整 axios 响应。
1255
+ */
1256
+ requestRaw<T = unknown>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
1257
+ }
1258
+ //#endregion
1259
+ //#region src/core/api/messages.d.ts
1260
+ /**
1261
+ * 消息发送 + 撤回
1262
+ */
1263
+ declare class MessagesApi extends Http {
1264
+ /** 单聊消息 */
1265
+ sendFriendMsg(openid: string, body: SendQQMsg): Promise<SendQQMsgResponse>;
1266
+ /** 群聊消息 */
1267
+ sendGroupMsg(groupOpenid: string, body: SendQQMsg): Promise<SendQQMsgResponse>;
1268
+ /**
1269
+ * 单聊输入中状态(msg_type=6,仅单聊)
1270
+ * @param openid 用户 openid
1271
+ * @param inputSecond 展示时长(秒),默认 60
1272
+ * @param passive 被动消息参数(msg_id / event_id / msg_seq),可选
1273
+ */
1274
+ sendFriendInputNotify(openid: string, inputSecond?: number, passive?: QQMessageID): Promise<SendQQMsgResponse>;
1275
+ /**
1276
+ * 单聊流式消息(仅单聊)
1277
+ *
1278
+ * 首帧不带 stream_msg_id,响应的 id 作为后续帧的 stream_msg_id 回传;
1279
+ * 同一次流 index 从 0 递增、msg_seq 保持一致;建议帧间隔 300~500ms。
1280
+ * @param openid 用户 openid
1281
+ * @param body 流式消息帧
1282
+ */
1283
+ sendFriendStreamMsg(openid: string, body: SendQQStreamMessageRequest): Promise<SendQQStreamMessageResponse>;
1284
+ /** 文字子频道消息 */
1285
+ sendChannelMsg(channelId: string, body: SendGuildMsg | FormData): Promise<SendGuildResponse>;
1286
+ /**
1287
+ * 频道私信消息
1288
+ * - 单参 (guildId, body):guildId 已知
1289
+ * - 双参 (recipientId, srcGuildId, body):先创建会话再发送
1290
+ */
1291
+ sendDmsMsg(guildId: string, body: SendGuildMsg | FormData): Promise<SendGuildResponse>;
1292
+ sendDmsMsg(recipientId: string, srcGuildId: string, body: SendGuildMsg | FormData): Promise<SendGuildResponse>;
1293
+ /**
1294
+ * 撤回消息
1295
+ * - 'user' / 'group' 对应 QQ 单聊 / 群聊
1296
+ * - 'channels' / 'dms' 对应频道 / 频道私信,支持 hidetip
1297
+ */
1298
+ recall(type: 'user' | 'group', peer: string, messageId: string): Promise<true>;
1299
+ recall(type: 'channels' | 'dms', peer: string, messageId: string, hidetip?: boolean): Promise<true>;
1300
+ }
1301
+ //#endregion
1302
+ //#region src/core/api/media.d.ts
1303
+ /**
1304
+ * 富媒体上传
1305
+ */
1306
+ declare class MediaApi extends Http {
1307
+ /**
1308
+ * @param scene user(单聊) / group(群聊)
1309
+ * @param peer openid 或 group_openid
1310
+ * @param type 文件类型
1311
+ * @param source http url、本地路径或 base64 字符串
1312
+ * @param srvSendMsg 上传后是否由服务端直接发送
1313
+ * @param fileName 文件消息的展示文件名
1314
+ */
1315
+ upload(scene: Scene, peer: string, type: MediaType, source: string, srvSendMsg?: boolean, fileName?: string): Promise<UploadMediaResponse>;
1316
+ /**
1317
+ * 上传没有公网 URL 处理器可用时的 fallback 富媒体资源。
1318
+ *
1319
+ * 较大的 fallback 资源会优先使用 QQ 分片上传,提高直接发送成功率。
1320
+ * `srvSendMsg` 为 true 时保留普通上传路径,避免分片完成接口与服务端直接发送语义冲突。
1321
+ *
1322
+ * @param scene user(单聊) / group(群聊)
1323
+ * @param peer openid 或 group_openid
1324
+ * @param type 文件类型
1325
+ * @param source 本地路径、http url、data URL、base64:// 或裸 base64
1326
+ * @param srvSendMsg 上传后是否由服务端直接发送
1327
+ * @param fileName 文件消息的展示文件名
1328
+ * @param forceChunk 是否强制走分片上传,不按 5MB 阈值判断
1329
+ * @returns 上传结果,包含后续发送消息所需的 file_info
1330
+ */
1331
+ uploadFallback(scene: Scene, peer: string, type: MediaType, source: string, srvSendMsg?: boolean, fileName?: string, forceChunk?: boolean): Promise<UploadMediaResponse>;
1332
+ /**
1333
+ * 上传资源并取回它的公网直链。
1334
+ *
1335
+ * 分片上传的合并响应里带 `raw_url`,等价于一个临时图床:拿到地址后图片就能以
1336
+ * markdown 图片语法嵌进 msg_type=2,和文本、按钮合成一条消息,不必退化成
1337
+ * 独立的 msg_type=7 富媒体消息。
1338
+ *
1339
+ * 与 `uploadFallback` 的差别只有一处:那边按体积决定是否分片,目标是拿
1340
+ * `file_info`;这里必须无条件分片,否则服务端不会给出 `raw_url`。
1341
+ *
1342
+ * 直链的存活时间等于响应里的 `ttl`,属于临时地址,只适合当次发送使用。
1343
+ *
1344
+ * @param scene user(单聊) / group(群聊)
1345
+ * @param peer openid 或 group_openid,决定上传归属的会话
1346
+ * @param type 文件类型;`file` 无直链可取
1347
+ * @param source 本地路径、http url、data URL、base64:// 或裸 base64
1348
+ * @param fileName 文件名,同时用于推断直链声明的 MIME
1349
+ * @returns 可直接嵌入消息的直链,以及原始上传响应
1350
+ */
1351
+ uploadForUrl(scene: Scene, peer: string, type: MediaType, source: string, fileName?: string): Promise<{
1352
+ url: string;
1353
+ response: UploadMediaResponse;
1354
+ }>;
1355
+ /**
1356
+ * 确认单个分片已完成上传。
1357
+ *
1358
+ * QQ 有时会在分片刚 PUT 完时短暂返回 40093001,此时需要在服务端给出的
1359
+ * retry_timeout 窗口内持续重试,而不是直接判定整个大文件上传失败。
1360
+ *
1361
+ * @param scene user(单聊) / group(群聊)
1362
+ * @param peer openid 或 group_openid
1363
+ * @param body upload_part_finish 请求体
1364
+ * @param retryTimeout 服务端返回的持续重试秒数
1365
+ */
1366
+ private finishUploadPart;
1367
+ /**
1368
+ * 持续重试 upload_part_finish 的短暂服务端状态。
1369
+ *
1370
+ * @param scene user(单聊) / group(群聊)
1371
+ * @param peer openid 或 group_openid
1372
+ * @param body upload_part_finish 请求体
1373
+ * @param retryTimeout 服务端返回的持续重试秒数
1374
+ */
1375
+ private retryUploadPartFinish;
1376
+ /**
1377
+ * 完成 QQ 分片上传,并对短暂失败做有限重试。
1378
+ *
1379
+ * @param scene user(单聊) / group(群聊)
1380
+ * @param peer openid 或 group_openid
1381
+ * @param uploadId upload_prepare 返回的上传任务 ID
1382
+ * @returns 上传结果
1383
+ */
1384
+ private completeChunkedUpload;
1385
+ /**
1386
+ * 使用 QQ 官方分片协议上传 fallback 大资源。
1387
+ *
1388
+ * 流程为:准备上传 -> PUT 每个分片 -> 确认每个分片 -> 完成上传。
1389
+ *
1390
+ * @param scene user(单聊) / group(群聊)
1391
+ * @param peer openid 或 group_openid
1392
+ * @param type 文件类型
1393
+ * @param source 已归一化的 fallback 来源
1394
+ * @param preparedHashes 预计算的文件 hash
1395
+ * @returns 上传结果,包含后续发送消息所需的 file_info
1396
+ */
1397
+ private uploadChunked;
1398
+ }
1399
+ //#endregion
1400
+ //#region src/core/api/media-images.d.ts
1401
+ /**
1402
+ * Markdown 素材图片管理。
1403
+ *
1404
+ * 官方接口文档 v1.42.0 新增 `/v2/media-images` 系列接口,用于把本地图片
1405
+ * 上传为可长期复用的 `qqbot-media://` Markdown 引用。
1406
+ */
1407
+ declare class MediaImagesApi extends Http {
1408
+ /** 当前 bot 进程内按内容 MD5 复用的素材缓存。 */
1409
+ private readonly cache;
1410
+ /** 申请上传图片,获取 upload_id 与预签名 PUT 地址。 */
1411
+ prepare(body: MediaImagePrepareRequest): Promise<MediaImagePrepareResponse>;
1412
+ /** 完成图片上传,获取可写入 Markdown 的 `qqbot-media://` 引用。 */
1413
+ complete(body: MediaImageCompleteRequest): Promise<MediaImageCompleteResponse>;
1414
+ /** 查询当前机器人的有效素材图片。 */
1415
+ list(params?: MediaImageListParams): Promise<MediaImageListResponse>;
1416
+ /** 删除素材图片并释放数量配额。 */
1417
+ delete<T = Record<string, never>>(imageId: string): Promise<T>;
1418
+ /**
1419
+ * 上传图片并返回可写入 Markdown 的 `qqbot-media://` 引用。
1420
+ *
1421
+ * 自动完成文件头识别、文件名规范化、MD5/SHA1 计算、预签名 PUT 与 complete。
1422
+ *
1423
+ * @param source 图片来源:Buffer、URL、本地路径、data URL 或 base64://。
1424
+ * @param fileName 可选文件名;未提供时按真实图片格式生成。
1425
+ * @returns complete 接口响应。
1426
+ */
1427
+ upload(source: string | Buffer | Uint8Array, fileName?: string): Promise<MediaImageCompleteResponse>;
1428
+ }
1429
+ //#endregion
1430
+ //#region src/core/api/interaction.d.ts
1431
+ /** ack 返回码 */
1432
+ type AckCode = 0 | 1 | 2 | 3 | 4 | 5;
1433
+ /**
1434
+ * INTERACTION_CREATE 回应
1435
+ */
1436
+ declare class InteractionApi extends Http {
1437
+ /**
1438
+ * @param interactionId INTERACTION_CREATE 事件中的 id
1439
+ * @param code 0 成功 / 1 操作失败 / 2 操作频繁 / 3 重复操作 / 4 无权限 / 5 仅管理员
1440
+ */
1441
+ ack(interactionId: string, code?: AckCode): Promise<void>;
1442
+ }
1443
+ //#endregion
1444
+ //#region src/core/api/meta.d.ts
1445
+ /**
1446
+ * 元信息接口:@me / dms / gateway / 分享链接
1447
+ */
1448
+ declare class MetaApi extends Http {
1449
+ /** 当前机器人详情 */
1450
+ getMe(): Promise<GetMeResponse>;
1451
+ /** 创建频道私信会话 */
1452
+ createDms(recipientId: string, srcGuildId: string): Promise<DmsResponse>;
1453
+ /** 获取通用 WSS 地址 */
1454
+ getGateway(): Promise<{
1455
+ url: string;
1456
+ }>;
1457
+ /**
1458
+ * 生成机器人分享链接
1459
+ *
1460
+ * 用于邀请用户添加机器人为好友;`callback_data`(最长 32 字符)会在用户通过该
1461
+ * 链接添加机器人时透传到 `FRIEND_ADD` 事件的 `scene_param`。
1462
+ *
1463
+ * @param body 分享链接参数,均为可选
1464
+ */
1465
+ generateUrlLink(body?: GenerateUrlLinkRequest): Promise<GenerateUrlLinkResponse>;
1466
+ }
1467
+ //#endregion
1468
+ //#region src/core/api/groups.d.ts
1469
+ /**
1470
+ * QQ 群信息与群成员管理接口
1471
+ *
1472
+ * 注意:以下接口均为白名单接口,未开通权限时平台返回错误码 11253,
1473
+ * 需要向平台运营申请后可用。接口文档 v1.28.0(2026-09-03)新增的群成员管理
1474
+ * 接口(成员列表 / 批量移除 / 黑名单)官方标注为「正在内邀接入中」,
1475
+ * 开放范围可能比其它白名单接口更窄。
1476
+ */
1477
+ declare class GroupsApi extends Http {
1478
+ /**
1479
+ * 获取群基础信息
1480
+ * @param groupOpenid 群 openid
1481
+ */
1482
+ getGroupInfo(groupOpenid: string): Promise<QQGroupInfoResponse>;
1483
+ /**
1484
+ * 获取机器人在群内的状态(角色、入群时间、主动消息开关等)
1485
+ * @param groupOpenid 群 openid
1486
+ */
1487
+ getBotState(groupOpenid: string): Promise<GroupBotStateResponse>;
1488
+ /**
1489
+ * 获取群成员列表
1490
+ *
1491
+ * 每次最多返回 30 条,只支持 cursor 翻页:首次不传 `cursor`,之后回传上一次
1492
+ * 响应的 `next_cursor`,`next_cursor` 为空串表示已到末页。
1493
+ *
1494
+ * @param groupOpenid 群 openid
1495
+ * @param params 分页参数
1496
+ */
1497
+ getGroupMemberList(groupOpenid: string, params?: GetGroupMemberListParams): Promise<GetGroupMemberListResponse>;
1498
+ /**
1499
+ * 获取群成员详情
1500
+ *
1501
+ * 昵称字段为 `username`;`nick` 是该接口转为公开文档之前的字段名,仅作兼容。
1502
+ *
1503
+ * @param groupOpenid 群 openid
1504
+ * @param memberOpenid 群成员 openid
1505
+ */
1506
+ getGroupMember(groupOpenid: string, memberOpenid: string): Promise<QQGroupMemberResponse>;
1507
+ /**
1508
+ * 群成员批量移除
1509
+ *
1510
+ * 单次最多 20 个成员,可通过 `add_to_member_blacklist` 在移除的同时拉黑。
1511
+ * 机器人需拥有群管理员身份。
1512
+ *
1513
+ * @param groupOpenid 群 openid
1514
+ * @param body 待移除的成员列表与是否同时拉黑
1515
+ */
1516
+ batchRemoveGroupMembers(groupOpenid: string, body: BatchRemoveGroupMembersBody): Promise<BatchRemoveGroupMembersResponse>;
1517
+ /**
1518
+ * 查询群黑名单
1519
+ *
1520
+ * @param groupOpenid 群 openid
1521
+ * @param params 分页参数,`limit` 默认 20、最大 100
1522
+ */
1523
+ getGroupMemberBlacklist(groupOpenid: string, params?: GetGroupMemberBlacklistParams): Promise<GetGroupMemberBlacklistResponse>;
1524
+ /**
1525
+ * 群黑名单操作
1526
+ *
1527
+ * 只有目标用户不在群中时才能加入黑名单,需要先移除再拉黑;单次最多 20 个。
1528
+ * 返回的 `fail_openids` 在 `op=add` / `op=del` 下同义,都是操作失败的 openid。
1529
+ *
1530
+ * @param groupOpenid 群 openid
1531
+ * @param body 操作类型与目标成员列表
1532
+ */
1533
+ setGroupMemberBlacklist(groupOpenid: string, body: SetGroupMemberBlacklistBody): Promise<SetGroupMemberBlacklistResponse>;
1534
+ /**
1535
+ * 设置群成员禁言
1536
+ *
1537
+ * 机器人需拥有群管理员身份,平台限制最大禁言时长为 30 天;
1538
+ * 只能操作普通成员,不能操作群主、管理员与机器人。
1539
+ * 需要一次设置多个成员时用 {@link GroupsApi.setGroupMuteBatch}。
1540
+ *
1541
+ * @param groupOpenid 群 openid
1542
+ * @param memberOpenid 群成员 openid
1543
+ * @param op 操作: add 增加禁言,update 更新禁言到期时间,del 解除禁言
1544
+ * @param duration 禁言时间使用RFC3339 格式
1545
+ */
1546
+ setGroupMute(groupOpenid: string, memberOpenid: string, op: 'add' | 'update' | 'del', duration: string): Promise<{}>;
1547
+ /**
1548
+ * 批量设置群成员禁言
1549
+ *
1550
+ * 每项通过自身的 `op` 控制增 / 改 / 删,可以在一次请求里混用。
1551
+ * 平台限制单次最多 20 个成员(接口文档 v1.28.0 由 10 提升至 20),
1552
+ * 超出时平台会直接拒绝整个请求。
1553
+ *
1554
+ * @param groupOpenid 群 openid
1555
+ * @param members 成员禁言设置列表
1556
+ */
1557
+ setGroupMuteBatch(groupOpenid: string, members: SetMemberMuteState[]): Promise<{}>;
1558
+ /**
1559
+ * 设置群成员禁言
1560
+ * @deprecated 方法名拼写错误,请使用 {@link GroupsApi.setGroupMute}
1561
+ */
1562
+ setGroupMetu(groupOpenid: string, memberOpenid: string, op: 'add' | 'update' | 'del', duration: string): Promise<{}>;
1563
+ /**
1564
+ * 查询群禁言状态
1565
+ *
1566
+ * 返回全员禁言模式(含定时 / 周期规则)与当前禁言中的成员列表(不含已过期)。
1567
+ * 机器人需拥有群管理员身份。
1568
+ *
1569
+ * @param groupOpenid 群 openid
1570
+ */
1571
+ getGroupMuteSetting(groupOpenid: string): Promise<GetGroupMuteSettingResponse>;
1572
+ /**
1573
+ * 拉取入群申请列表
1574
+ *
1575
+ * 机器人需拥有群管理员身份。
1576
+ *
1577
+ * @param groupOpenid 群 openid
1578
+ * @param params 分页参数,`limit` 默认 20、最大 50(接口文档 v1.28.0 由 100 下调),
1579
+ * 传入更大的值会被收敛到 50,避免平台直接拒绝
1580
+ */
1581
+ getJoinRequestList(groupOpenid: string, params?: GetJoinRequestListParams): Promise<GetJoinRequestListResponse>;
1582
+ /**
1583
+ * 审批入群申请
1584
+ *
1585
+ * 机器人需拥有群管理员身份。
1586
+ *
1587
+ * @param groupOpenid 群 openid
1588
+ * @param memberOpenid 申请人 openid
1589
+ * @param body 审批动作,`op=decline` 时可附带拒绝理由与拉黑标记
1590
+ */
1591
+ approvalJoinRequest(groupOpenid: string, memberOpenid: string, body: ApprovalJoinRequestBody): Promise<{}>;
1592
+ }
1593
+ //#endregion
1594
+ //#region src/core/api/guilds.d.ts
1595
+ /**
1596
+ * 频道 / 子频道接口
1597
+ *
1598
+ * 子频道的创建、修改、删除均需要管理员权限且属于私域接口,
1599
+ * 操作成功后会触发 `CHANNEL_CREATE` / `CHANNEL_UPDATE` / `CHANNEL_DELETE` 事件。
1600
+ */
1601
+ declare class GuildsApi extends Http {
1602
+ /**
1603
+ * 获取机器人加入的频道列表
1604
+ *
1605
+ * 官方文档响应体标注为 `{ guilds: [] }`,但示例与实际返回均为裸数组;
1606
+ * 这里对两种形态都做兼容。
1607
+ *
1608
+ * @param params 分页参数,`limit` 默认 100、最大 100
1609
+ */
1610
+ getGuildList(params?: GetGuildListParams): Promise<GuildInfo[]>;
1611
+ /**
1612
+ * 获取频道详情
1613
+ * @param guildId 频道 ID
1614
+ */
1615
+ getGuild(guildId: string): Promise<GuildInfo>;
1616
+ /**
1617
+ * 获取子频道列表
1618
+ *
1619
+ * 官方文档响应体标注为 `{ channels: [] }`,但示例与实际返回均为裸数组;
1620
+ * 这里对两种形态都做兼容。
1621
+ *
1622
+ * @param guildId 频道 ID
1623
+ */
1624
+ getChannelList(guildId: string): Promise<ChannelInfo[]>;
1625
+ /**
1626
+ * 创建子频道(需要管理员权限,私域接口)
1627
+ * @param guildId 频道 ID
1628
+ * @param body 子频道配置
1629
+ */
1630
+ createChannel(guildId: string, body: CreateChannelRequest): Promise<ChannelInfo>;
1631
+ /**
1632
+ * 获取子频道详情
1633
+ * @param channelId 子频道 ID
1634
+ */
1635
+ getChannel(channelId: string): Promise<ChannelInfo>;
1636
+ /**
1637
+ * 修改子频道(需要管理员权限,私域接口)
1638
+ *
1639
+ * 只需传入要修改的字段。
1640
+ * @param channelId 子频道 ID
1641
+ * @param body 待修改的字段
1642
+ */
1643
+ updateChannel(channelId: string, body: UpdateChannelRequest): Promise<ChannelInfo>;
1644
+ /**
1645
+ * 删除子频道(需要管理员权限,私域接口)
1646
+ *
1647
+ * 子频道删除后无法恢复。
1648
+ * @param channelId 子频道 ID
1649
+ */
1650
+ deleteChannel(channelId: string): Promise<{}>;
1651
+ }
1652
+ //#endregion
1653
+ //#region src/core/api/menu.d.ts
1654
+ /**
1655
+ * 全局自定义菜单接口
1656
+ *
1657
+ * 自定义菜单展示在机器人单聊窗口底部,仅支持 C2C(单聊)场景,
1658
+ * 设置后对所有用户生效,不支持按用户维度区分。
1659
+ *
1660
+ * {@link https://bot.q.qq.com/wiki/develop/api-v2/server-inter/menu-panel/}
1661
+ */
1662
+ declare class MenuApi extends Http {
1663
+ /**
1664
+ * 查询全局自定义菜单
1665
+ *
1666
+ * 未设置过菜单时响应的 `menu` 字段为空。
1667
+ * @returns 当前生效的菜单配置与版本号
1668
+ */
1669
+ getMenu(): Promise<GetMenuResponse>;
1670
+ /**
1671
+ * 修改全局自定义菜单
1672
+ *
1673
+ * 传入后会覆盖原有的完整菜单配置;不传 `menu` 表示清空菜单。
1674
+ * @param menu 菜单配置,最多 10 个一级菜单项
1675
+ * @returns 本次修改后的菜单版本号
1676
+ */
1677
+ updateMenu(menu?: Menu): Promise<UpdateMenuResponse>;
1678
+ }
1679
+ //#endregion
1680
+ //#region src/core/api/panels.d.ts
1681
+ /**
1682
+ * 指令面板接口
1683
+ *
1684
+ * 指令面板以面板形式展示指令或链接,支持 c2c(单聊)、group(群聊)、
1685
+ * channel(文字子频道)、dm(频道私信)四种场景;其中 c2c / group 支持
1686
+ * 按指定用户或群生效(target_type=specific),channel / dm 仅支持全局配置。
1687
+ *
1688
+ * 一个机器人最多创建 20 个指令面板。
1689
+ *
1690
+ * {@link https://bot.q.qq.com/wiki/develop/api-v2/server-inter/menu-panel/}
1691
+ */
1692
+ declare class PanelsApi extends Http {
1693
+ /**
1694
+ * 查询指令面板列表
1695
+ *
1696
+ * 分页拉取指定场景下已生效的面板,按设置时间倒序排列。
1697
+ * @param params 查询参数,`scope` 必填
1698
+ * @returns 面板记录列表与分页游标
1699
+ */
1700
+ getPanelList(params: GetPanelListParams): Promise<GetPanelListResponse>;
1701
+ /**
1702
+ * 创建指令面板
1703
+ * @param body 面板场景、作用范围与配置内容
1704
+ * @returns 新创建的面板 ID
1705
+ */
1706
+ createPanel(body: CreatePanelRequest): Promise<CreatePanelResponse>;
1707
+ /**
1708
+ * 查询指令面板详情
1709
+ *
1710
+ * 返回面板完整配置,target_type=specific 时同时返回关联的用户 / 群 openid 列表。
1711
+ * @param panelId 面板 ID
1712
+ */
1713
+ getPanel(panelId: string): Promise<GetPanelResponse>;
1714
+ /**
1715
+ * 修改指令面板
1716
+ *
1717
+ * 传入后会覆盖原有的面板元素列表和备注,不影响已关联的用户 / 群列表。
1718
+ * @param panelId 面板 ID
1719
+ * @param panel 面板配置内容
1720
+ * @returns 本次修改后的面板版本号
1721
+ */
1722
+ updatePanel(panelId: string, panel: Panel): Promise<UpdatePanelResponse>;
1723
+ /**
1724
+ * 删除指令面板
1725
+ *
1726
+ * 删除后该面板不再对任何用户或群生效。
1727
+ * @param panelId 面板 ID
1728
+ */
1729
+ deletePanel(panelId: string): Promise<{}>;
1730
+ /**
1731
+ * 修改指令面板关联对象
1732
+ *
1733
+ * c2c 场景操作 `user_openids`,group 场景操作 `group_openids`,一次最多 20 个;
1734
+ * channel / dm 场景为全局配置,不支持此操作。
1735
+ * @param panelId 面板 ID
1736
+ * @param body 操作类型与关联对象列表
1737
+ */
1738
+ updatePanelTarget(panelId: string, body: UpdatePanelTargetRequest): Promise<{}>;
1739
+ }
1740
+ //#endregion
1741
+ //#region src/core/api/join-approval.d.ts
1742
+ /**
1743
+ * 入群自动审批策略接口
1744
+ *
1745
+ * 策略把「关联群 + 白名单 QQ 号码」绑在一起,命中白名单的入群申请会自动审批通过。
1746
+ * 规则仅在机器人拥有群管理员身份时才会实际运行;一个机器人最多 20 个策略。
1747
+ */
1748
+ declare class JoinApprovalApi extends Http {
1749
+ /**
1750
+ * 查询入群自动审批策略列表
1751
+ *
1752
+ * 按创建时间倒序,支持分页。
1753
+ * @param params 分页参数,`limit` 默认 20、最大 50(接口文档 v1.28.0 由 100 下调),
1754
+ * 传入更大的值会被收敛到 50,避免平台直接拒绝
1755
+ */
1756
+ getStrategyList(params?: GetJoinApprovalStrategyListParams): Promise<GetJoinApprovalStrategyListResponse>;
1757
+ /**
1758
+ * 创建入群自动审批策略
1759
+ *
1760
+ * `group_openids` 与 `group_ids` 二选一必填,同时传入或均未传入都会报错。
1761
+ * @param body 策略配置
1762
+ */
1763
+ createStrategy(body: CreateJoinApprovalStrategyRequest): Promise<CreateJoinApprovalStrategyResponse>;
1764
+ /**
1765
+ * 修改入群自动审批策略
1766
+ *
1767
+ * 可修改生效状态、失效时间、备注,或增删关联群;
1768
+ * 增删关联群时的群标识形式必须与创建时一致。
1769
+ * @param strategyId 策略 ID
1770
+ * @param body 待修改的字段
1771
+ */
1772
+ updateStrategy(strategyId: string, body: UpdateJoinApprovalStrategyRequest): Promise<UpdateJoinApprovalStrategyResponse>;
1773
+ /**
1774
+ * 删除入群自动审批策略
1775
+ * @param strategyId 策略 ID
1776
+ */
1777
+ deleteStrategy(strategyId: string): Promise<{}>;
1778
+ /**
1779
+ * 执行入群自动审批策略
1780
+ *
1781
+ * 对策略关联的全部群发起全量扫描,命中白名单号码的入群申请自动审批通过。
1782
+ * 异步执行,约 10 分钟完成。
1783
+ * @param strategyId 策略 ID
1784
+ */
1785
+ executeStrategy(strategyId: string): Promise<{}>;
1786
+ /**
1787
+ * 修改入群自动审批策略的白名单号码
1788
+ *
1789
+ * 单次最多 10000 个,策略号码上限 10W。
1790
+ * @param strategyId 策略 ID
1791
+ * @param body 操作类型与号码列表
1792
+ */
1793
+ updateWhitelistUsers(strategyId: string, body: UpdateWhitelistUsersRequest): Promise<UpdateWhitelistUsersResponse>;
1794
+ }
1795
+ //#endregion
1796
+ //#region src/core/api/index.d.ts
1797
+ /**
1798
+ * QQBot 官方 API 门面
1799
+ *
1800
+ * 子模块按职能拆分:
1801
+ * - messages:发送 / 撤回
1802
+ * - media:富媒体上传
1803
+ * - mediaImages:Markdown 素材图片管理
1804
+ * - interaction:按钮回调 ack
1805
+ * - meta:@me / dms / gateway / 分享链接
1806
+ * - groups:群基础信息 / 机器人群内状态 / 群成员列表与详情 / 禁言 / 批量移除 / 群黑名单 / 入群申请(白名单接口)
1807
+ * - guilds:频道与子频道的查询和增删改
1808
+ * - menu:全局自定义菜单(仅单聊)
1809
+ * - panels:指令面板
1810
+ * - joinApproval:入群自动审批策略
1811
+ * - request:裸请求入口,用于调用尚未封装的官方接口
1812
+ *
1813
+ * 请求体构造器 {@link buildQQMsg} / {@link buildGuildMsg} 独立导出,避免与 HTTP 调用耦合
1814
+ */
1815
+ declare class QQBotApi {
1816
+ readonly axios: AxiosInstance;
1817
+ /**
1818
+ * 裸请求入口,直接调用官方 OpenAPI。
1819
+ *
1820
+ * 官方新接口还没被适配器封装时可用它兜底,会自动带鉴权、解包 `data`、
1821
+ * 格式化错误码:
1822
+ *
1823
+ * ```ts
1824
+ * await bot.super.request.get('/v2/menu')
1825
+ * await bot.super.request.post('/v2/xxx', { foo: 1 })
1826
+ * ```
1827
+ *
1828
+ * @see {@link RequestApi}
1829
+ */
1830
+ readonly request: RequestApi;
1831
+ readonly messages: MessagesApi;
1832
+ readonly media: MediaApi;
1833
+ readonly mediaImages: MediaImagesApi;
1834
+ readonly interaction: InteractionApi;
1835
+ readonly meta: MetaApi;
1836
+ readonly groups: GroupsApi;
1837
+ readonly guilds: GuildsApi;
1838
+ readonly menu: MenuApi;
1839
+ readonly panels: PanelsApi;
1840
+ readonly joinApproval: JoinApprovalApi;
1841
+ /** 请求体构造器(静态便利) */
1842
+ readonly qq: {
1843
+ text(content: string): SendQQTextMessageRequest;
1844
+ markdown(markdown: Markdown, keyboard?: Keyboard): SendQQMarkdownMessageRequest;
1845
+ ark(ark: SendQQArkMessageRequest["ark"]): SendQQArkMessageRequest;
1846
+ media(fileInfo: string, keyboard?: Keyboard): SendQQMediaMessageRequest;
1847
+ };
1848
+ readonly guild: {
1849
+ text(content: string, image?: string): SendGuildTextMessageRequest;
1850
+ image(image: string): SendGuildImageMessageRequest;
1851
+ embed(embed: Embeds): SendGuildEmbedMessageRequest;
1852
+ ark(ark: Ark): SendGuildArkMessageRequest;
1853
+ markdown(markdown: Markdown, keyboard?: Keyboard): SendGuildMarkdownMessageRequest;
1854
+ };
1855
+ constructor(axios: AxiosInstance);
1856
+ }
1857
+ //#endregion
1858
+ //#region src/types/config.d.ts
1859
+ /**
1860
+ * 消息缓存存储分级。
1861
+ *
1862
+ * - minimal: 只存 ID 映射与引用关系(reply 段),撤回 / 引用解析可用,正文不落库;
1863
+ * - standard: 额外保存文本、表情与媒体本地路径,markdown 原文不落库;
1864
+ * - full: 全部可缓存消息段原样保存。
1865
+ */
1866
+ type MessageCacheLevel = 'minimal' | 'standard' | 'full';
1867
+ /**
1868
+ * 单个 QQBot 配置
1869
+ */
1870
+ interface QQBotConfig {
1871
+ /** 机器人 ID */
1872
+ appId: string;
1873
+ /** 机器人密钥 */
1874
+ secret: string;
1875
+ /** 开启 QQ 场景能力(单聊 / 群聊) */
1876
+ qqEnable: boolean;
1877
+ /** 开启频道场景能力 */
1878
+ guildEnable: boolean;
1879
+ /** 频道场景模式 0 公域 / 1 私域 */
1880
+ guildMode: 0 | 1;
1881
+ /** 收到消息后对文本进行表达式处理 */
1882
+ regex: {
1883
+ reg: string | RegExp;
1884
+ rep: string;
1885
+ }[];
1886
+ /** 消息缓存配置 */
1887
+ messageCache: {
1888
+ /** 是否启用数据库消息缓存,用于 bot.getMsg */
1889
+ enable: boolean;
1890
+ /** 是否缓存机器人自己发送的消息 */
1891
+ self: boolean;
1892
+ /** 存储分级,控制单条消息的落库体积 */
1893
+ level: MessageCacheLevel;
1894
+ /** 缓存保留小时数;多个 bot 同时开启时取最大值 */
1895
+ ttlHours: number;
1896
+ /** 消息缓存最大行数,超出后删除最旧;多个 bot 同时开启时取最大值 */
1897
+ maxRows: number;
1898
+ };
1899
+ /** 事件接收配置 */
1900
+ event: {
1901
+ /** 接收方式 0 关闭 / 1 webhook / 2 ws */
1902
+ type: 0 | 1 | 2;
1903
+ };
1904
+ }
1905
+ //#endregion
1906
+ //#region src/core/storage/message-store/types.d.ts
1907
+ interface CachedMessage {
1908
+ messageId: string;
1909
+ messageSeq: number;
1910
+ time: number;
1911
+ contact: Contact;
1912
+ sender: Sender;
1913
+ elements: ElementTypes[];
1914
+ }
1915
+ /** 保存消息时的附加标记。 */
1916
+ interface SaveOptions {
1917
+ /** QQ 客户端引用使用的 `msg_idx`(REFIDX),作为消息的第二查询索引。 */
1918
+ refIdx?: string;
1919
+ /** 是否是机器人自己发送的消息,用于单聊撤回判定。 */
1920
+ isSelf?: boolean;
1921
+ /** 存储分级;缺省按 standard 处理。 */
1922
+ level?: MessageCacheLevel;
1923
+ }
1924
+ //#endregion
1925
+ //#region src/core/storage/message-store/store.d.ts
1926
+ /**
1927
+ * QQBot 收到的消息缓存。
1928
+ *
1929
+ * SQLite 是唯一数据层,没有内存镜像:
1930
+ * - 写入热路径只入队,后台按批次事务落库,每条消息稳定 2~3 次语句
1931
+ * 往返(prepared statement 复用);
1932
+ * - 所有读取直接查 SQLite(WAL + 整数 hash 索引,点查亚毫秒级);
1933
+ * 读取前先排空待写队列,保证"读到自己刚写的数据"。
1934
+ */
1935
+ declare class MessageStore {
1936
+ private db?;
1937
+ private readonly ready;
1938
+ private shouldVacuum;
1939
+ private flushTimer?;
1940
+ private flushActive?;
1941
+ private mediaTimer?;
1942
+ private mediaActive;
1943
+ private pending;
1944
+ private pendingMedia;
1945
+ private readonly pendingMediaKeys;
1946
+ private readonly statements;
1947
+ private readonly contactRefCache;
1948
+ private readonly senderRefCache;
1949
+ /** 当前生效的缓存保留时长;由配置解析,多 bot 取最大值。 */
1950
+ private ttlMs;
1951
+ /** 当前生效的消息行数硬上限;由配置解析,多 bot 取最大值。 */
1952
+ private maxRows;
1953
+ constructor();
1954
+ /**
1955
+ * 立即执行一次过期消息和本地媒体缓存清理。
1956
+ *
1957
+ * 该方法交给 Karin `task` 调度调用;读写路径不再内嵌清理,避免尾延迟。
1958
+ *
1959
+ * @returns 清理完成 Promise。
1960
+ */
1961
+ cleanupExpired(): Promise<void>;
1962
+ /**
1963
+ * 保存实际消息。
1964
+ *
1965
+ * 只克隆快照并投递后台队列,不等待 SQLite,消息事件创建不会被
1966
+ * 数据库写锁或小事务阻塞。
1967
+ *
1968
+ * @param botId 当前 QQBot appId。
1969
+ * @param message 已转换为 Karin elements 的消息缓存。
1970
+ * @param options 引用索引与自己消息标记。
1971
+ */
1972
+ save(botId: string, message: CachedMessage, options?: SaveOptions): Promise<void>;
1973
+ /**
1974
+ * 保存 QQ 下发的引用上下文。
1975
+ *
1976
+ * 是否已有同 ID 缓存(原消息或引用索引)由后台 flush 在事务内判断并去重,
1977
+ * 避免阻塞事件热路径。
1978
+ *
1979
+ * @param botId 当前 QQBot appId。
1980
+ * @param message 以 `ref_msg_idx` 作为 messageId 的引用上下文。
1981
+ * @param level 存储分级;缺省按 standard 处理。
1982
+ */
1983
+ saveReferenceIfAbsent(botId: string, message: CachedMessage, level?: SaveOptions['level']): Promise<void>;
1984
+ /**
1985
+ * 读取缓存消息。
1986
+ *
1987
+ * OneBot v11 标准调用只传 messageId;contact 参数仅用于额外限定范围。
1988
+ *
1989
+ * @param botId 当前 QQBot appId。
1990
+ * @param messageId 真实消息 ID 或 QQ `REFIDX` 引用索引。
1991
+ * @param contact 可选会话范围,传入后只在该会话下查询。
1992
+ * @returns 命中的消息缓存;未命中或已过期时返回 null。
1993
+ */
1994
+ get(botId: string, messageId: string, contact?: Contact): Promise<MessageResponse | null>;
1995
+ /**
1996
+ * 按起始消息 ID 读取同一会话内的历史缓存消息。
1997
+ *
1998
+ * QQ 官方 Bot 没有 seq 历史查询能力;这里以本地缓存中命中的起始消息为锚点,
1999
+ * 按时间倒序返回最近的 `count` 条消息,包含起始消息本身。
2000
+ *
2001
+ * @param botId 当前 QQBot appId。
2002
+ * @param contact 查询限定的会话。
2003
+ * @param startMsgId 起始消息 ID 或 QQ `REFIDX` 引用索引。
2004
+ * @param count 获取消息数量。
2005
+ * @returns 命中的历史消息数组;未命中或已过期时返回空数组。
2006
+ */
2007
+ getHistory(botId: string, contact: Contact, startMsgId: string, count: number): Promise<MessageResponse[]>;
2008
+ /**
2009
+ * 将 QQ `REFIDX` 引用索引解析为 API 消息 ID。
2010
+ *
2011
+ * 撤回等平台接口的唯一映射来源;ID 映射行不受缓存开关影响,始终落库。
2012
+ *
2013
+ * @param botId 当前 QQBot appId。
2014
+ * @param contact 消息所在会话。
2015
+ * @param refIdx QQ 引用索引,通常为 REFIDX_...。
2016
+ * @returns 对应的 API 消息 ID;未命中时返回 null。
2017
+ */
2018
+ resolveApiMessageId(botId: string, contact: Contact, refIdx: string): Promise<string | null>;
2019
+ /**
2020
+ * 将 API 消息 ID 反向解析为 QQ `REFIDX` 引用索引。
2021
+ *
2022
+ * 发送侧显式引用回复的唯一映射来源。
2023
+ *
2024
+ * @param botId 当前 QQBot appId。
2025
+ * @param contact 消息所在会话。
2026
+ * @param messageId QQ API 消息 ID,通常为 ROBOT1.0_...。
2027
+ * @returns 对应的引用索引;未命中时返回 null。
2028
+ */
2029
+ resolveRefIdx(botId: string, contact: Contact, messageId: string): Promise<string | null>;
2030
+ /**
2031
+ * 读取持久化的 file_info 上传缓存。
2032
+ *
2033
+ * @param key 由 api 层构造的缓存键。
2034
+ * @returns 序列化的上传响应 JSON;未命中或已过期时返回 null。
2035
+ */
2036
+ getUploadCache(key: string): Promise<string | null>;
2037
+ /**
2038
+ * 写入持久化的 file_info 上传缓存。
2039
+ *
2040
+ * @param key 由 api 层构造的缓存键。
2041
+ * @param response 序列化的上传响应 JSON。
2042
+ * @param expiresAt 失效时间戳;0 表示长期有效。
2043
+ */
2044
+ setUploadCache(key: string, response: string, expiresAt: number): Promise<void>;
2045
+ /**
2046
+ * 判断消息是否由机器人自己发送。
2047
+ *
2048
+ * 单聊撤回判定的唯一来源,读取消息行的 `is_self` 标记。
2049
+ *
2050
+ * @param botId 当前 QQBot appId。
2051
+ * @param contact 消息所在会话。
2052
+ * @param messageId QQ API 消息 ID。
2053
+ * @returns true 表示是机器人自己发送的消息。
2054
+ */
2055
+ isSelfMessage(botId: string, contact: Contact, messageId: string): Promise<boolean>;
2056
+ /**
2057
+ * 初始化 SQLite 连接、表结构,并执行一次启动清理。
2058
+ *
2059
+ * 远程媒体补救不在这里执行,避免阻塞 `ready` 拖慢首批消息落库。
2060
+ *
2061
+ * @returns 初始化完成 Promise。
2062
+ */
2063
+ private initialize;
2064
+ /**
2065
+ * 从配置解析当前生效的 TTL 与行数上限。
2066
+ *
2067
+ * 数据库为全 bot 共享,多个 bot 同时开启缓存时取最大值;配置读取失败时
2068
+ * 保持当前值。每次清理前刷新,配置修改最迟 10 分钟内生效。
2069
+ */
2070
+ private refreshSettings;
2071
+ /**
2072
+ * 投递待落库消息。
2073
+ *
2074
+ * @param item 待写入 SQLite 的缓存任务。
2075
+ */
2076
+ private enqueue;
2077
+ /**
2078
+ * 安排一次后台批量落库。
2079
+ *
2080
+ * 已有 timer 或正在 flush 时不会重复安排。
2081
+ */
2082
+ private scheduleFlush;
2083
+ /**
2084
+ * 触发一次批量落库;已有进行中的 flush 时复用其 Promise。
2085
+ *
2086
+ * @returns 当前批次落库完成的 Promise。
2087
+ */
2088
+ private flushQueue;
2089
+ /**
2090
+ * 等待写入队列完全清空。
2091
+ *
2092
+ * 所有读取入口先经过它,保证"读到自己刚写的数据";队列为空时零开销。
2093
+ */
2094
+ private flushAll;
2095
+ /**
2096
+ * 批量落库队列中的消息。
2097
+ *
2098
+ * 单次最多处理 `FLUSH_BATCH_SIZE` 条,并在一个事务内完成写入。
2099
+ *
2100
+ * @returns flush 完成 Promise。
2101
+ */
2102
+ private doFlushBatch;
2103
+ /**
2104
+ * 写入一条待落库消息。
2105
+ *
2106
+ * 稳定状态下(contact/sender 已缓存)每条消息 2 次语句往返:
2107
+ * 定位既有行 + INSERT 或 UPDATE。
2108
+ *
2109
+ * @param item 待写入的消息任务。
2110
+ */
2111
+ private writeItem;
2112
+ /**
2113
+ * 清理待写队列中已经过期的消息。
2114
+ */
2115
+ private prunePending;
2116
+ /**
2117
+ * 投递媒体本地化任务。
2118
+ *
2119
+ * 原消息会先保留短期 URL 写入缓存;本地化成功后再覆盖同一条消息。队列会按
2120
+ * message scoped key 去重,避免高频更新同一条消息时重复下载。
2121
+ *
2122
+ * @param botId 当前 QQBot appId。
2123
+ * @param message 可能包含远程媒体 URL 的消息快照。
2124
+ * @param refIdx 该消息的引用索引,成功本地化后随消息一并回写。
2125
+ * @param isSelf 是否机器人自己发送。
2126
+ */
2127
+ private enqueueMediaLocalize;
2128
+ /**
2129
+ * 安排媒体本地化队列处理。
2130
+ *
2131
+ * @returns 已存在定时器或队列为空时直接返回。
2132
+ */
2133
+ private scheduleMediaLocalize;
2134
+ /**
2135
+ * 按固定并发处理媒体本地化任务。
2136
+ *
2137
+ * @returns 队列为空或达到并发上限时返回。
2138
+ */
2139
+ private drainMediaLocalizeQueue;
2140
+ /**
2141
+ * 本地化单条消息中的远程媒体字段,并在成功后覆盖内存与 SQLite。
2142
+ *
2143
+ * @param item 待处理的媒体本地化任务。
2144
+ * @returns 本地化与回写完成 Promise。
2145
+ */
2146
+ private localizeMediaItem;
2147
+ /**
2148
+ * 清理已经过期的媒体本地化待处理任务。
2149
+ */
2150
+ private prunePendingMedia;
2151
+ /**
2152
+ * 启动时扫描 SQLite 中尚未本地化的远程媒体消息,并重新投递队列补救。
2153
+ *
2154
+ * `has_remote_media` 是部分索引列,扫描不再需要 LIKE 全表匹配。
2155
+ *
2156
+ * @returns 扫描和投递完成 Promise。
2157
+ */
2158
+ private recoverRemoteMedia;
2159
+ /**
2160
+ * 按消息 ID 或引用索引查询消息行。
2161
+ *
2162
+ * @param botId 当前 QQBot appId。
2163
+ * @param messageId 真实消息 ID 或 `REFIDX` 引用索引。
2164
+ * @param contact 可选会话范围。
2165
+ * @returns 命中的消息行;未命中时返回 null。
2166
+ */
2167
+ private queryMessageRow;
2168
+ /**
2169
+ * 浅拷贝消息缓存,避免后续事件对象被插件侧修改后污染缓存。
2170
+ *
2171
+ * @param message 原始缓存消息。
2172
+ * @returns 可安全放入缓存的消息副本。
2173
+ */
2174
+ private cloneMessage;
2175
+ /**
2176
+ * 将数据库行还原为 Karin `MessageResponse`。
2177
+ *
2178
+ * @param row 消息主查询结果。
2179
+ * @returns Karin 标准消息查询结果。
2180
+ */
2181
+ private rowToResponse;
2182
+ /**
2183
+ * 从查询行还原 Karin Contact。
2184
+ *
2185
+ * @param row 消息主查询结果。
2186
+ * @returns Karin Contact。
2187
+ */
2188
+ private contactFromRow;
2189
+ /**
2190
+ * 获取或创建会话映射 ID。
2191
+ *
2192
+ * @param botId 当前 QQBot appId。
2193
+ * @param contact Karin 会话对象。
2194
+ * @returns `qqbot_contacts.id`。
2195
+ */
2196
+ private ensureContact;
2197
+ /**
2198
+ * 获取或创建发送者映射 ID。
2199
+ *
2200
+ * sender 按 (userId, nick, name, role) 去重;不再被引用的行由清理任务 GC,
2201
+ * 不会随昵称变化永久膨胀。
2202
+ *
2203
+ * @param botId 当前 QQBot appId。
2204
+ * @param sender Karin sender 对象。
2205
+ * @returns `qqbot_senders.id`。
2206
+ */
2207
+ private ensureSender;
2208
+ /**
2209
+ * 判断消息是否已经超过本地缓存 TTL。
2210
+ *
2211
+ * @param row 带 `time` 字段的消息对象。
2212
+ * @returns true 表示已经超过一天缓存窗口。
2213
+ */
2214
+ private isExpired;
2215
+ /**
2216
+ * 清理过期缓存消息,并执行体积治理。
2217
+ *
2218
+ * 依次执行:配置刷新、TTL 删除、硬上限删除、上传缓存清理、
2219
+ * sender GC(写空闲时)、增量 vacuum 归还空间、WAL checkpoint 截断、
2220
+ * 媒体文件清理。
2221
+ */
2222
+ private cleanup;
2223
+ /**
2224
+ * 执行数据库版本迁移。
2225
+ *
2226
+ * 使用 SQLite `PRAGMA user_version` 记录已应用的 schema 版本。
2227
+ *
2228
+ * @returns 迁移完成 Promise。
2229
+ */
2230
+ private migrate;
2231
+ /**
2232
+ * 判断 SQLite 表是否存在。
2233
+ *
2234
+ * @param name 表名。
2235
+ * @returns true 表示表存在。
2236
+ */
2237
+ private tableExists;
2238
+ /**
2239
+ * 读取 SQLite 表字段名。
2240
+ *
2241
+ * @param name 表名。
2242
+ * @returns 字段名数组;表不存在时返回空数组。
2243
+ */
2244
+ private tableColumns;
2245
+ /**
2246
+ * 读取 SQLite schema 版本。
2247
+ *
2248
+ * @returns 当前 `PRAGMA user_version`;新库默认为 0。
2249
+ */
2250
+ private getUserVersion;
2251
+ /**
2252
+ * 在 `BEGIN IMMEDIATE` 事务中执行写操作。
2253
+ *
2254
+ * @param fn 事务内执行的异步函数。
2255
+ */
2256
+ private transaction;
2257
+ /**
2258
+ * 获取当前数据库连接。
2259
+ *
2260
+ * @returns 已初始化的 sqlite3 Database。
2261
+ */
2262
+ private database;
2263
+ /**
2264
+ * 获取(并缓存)prepared statement。
2265
+ *
2266
+ * 热路径 SQL 只 parse 一次,重复执行只做参数绑定。
2267
+ *
2268
+ * @param sql SQL 字符串。
2269
+ * @returns 复用的 Statement。
2270
+ */
2271
+ private prepared;
2272
+ /**
2273
+ * 以 prepared statement 执行不返回行的 SQL。
2274
+ *
2275
+ * @param sql SQL 字符串。
2276
+ * @param params SQL 参数。
2277
+ */
2278
+ private runS;
2279
+ /**
2280
+ * 以 prepared statement 查询单行数据。
2281
+ *
2282
+ * @param sql SQL 字符串。
2283
+ * @param params SQL 参数。
2284
+ * @returns 查询结果;未命中时返回 undefined。
2285
+ */
2286
+ private getS;
2287
+ /**
2288
+ * 以 prepared statement 查询多行数据。
2289
+ *
2290
+ * @param sql SQL 字符串。
2291
+ * @param params SQL 参数。
2292
+ * @returns 查询结果数组。
2293
+ */
2294
+ private allS;
2295
+ /**
2296
+ * 执行一次性 SQL(DDL、PRAGMA、事务控制),不走 prepared statement 缓存。
2297
+ *
2298
+ * @param sql SQL 字符串。
2299
+ * @param params SQL 参数。
2300
+ */
2301
+ private exec;
2302
+ /**
2303
+ * 一次性查询单行(PRAGMA / 系统表)。
2304
+ *
2305
+ * @param sql SQL 字符串。
2306
+ * @param params SQL 参数。
2307
+ * @returns 查询结果;未命中时返回 undefined。
2308
+ */
2309
+ private rawGet;
2310
+ /**
2311
+ * 一次性查询多行(PRAGMA / 系统表)。
2312
+ *
2313
+ * @param sql SQL 字符串。
2314
+ * @param params SQL 参数。
2315
+ * @returns 查询结果数组。
2316
+ */
2317
+ private rawAll;
2318
+ }
2319
+ //#endregion
2320
+ //#region src/core/adapter/base.d.ts
2321
+ /**
2322
+ * QQ Official Bot 适配器
2323
+ *
2324
+ * 发送通道由平台能力决定,没有对应的用户配置项:QQ 单聊 / 群聊的自定义 Markdown
2325
+ * 已对所有机器人开放,固定走 msg_type=2;频道场景仍需内邀开通,先乐观尝试
2326
+ * Markdown,被拒后自动降级为普通消息(详见 pipeline-qq / pipeline-guild 与
2327
+ * guild-markdown)。视频 / 语音 / 文件由 pipeline 内部以 msg_type=7 紧随主消息补发。
2328
+ */
2329
+ declare class AdapterQQBot extends AdapterBase implements AdapterType {
2330
+ /** 与官方 API 交互 */
2331
+ super: QQBotApi;
2332
+ /** openId / member_openid -> 昵称 缓存 */
2333
+ nicknameCache: Map<string, string>;
2334
+ constructor(cfg: QQBotConfig, api: QQBotApi);
2335
+ /** 当前 bot 配置。真实配置存放在 WeakMap,避免被系统接口序列化整个适配器时带出。 */
2336
+ get cfg(): QQBotConfig;
2337
+ /** 接收消息的一天热缓存 + SQLite 缓存,用于实现 Karin 标准 `getMsg`。 */
2338
+ get messageStore(): MessageStore;
2339
+ logger(level: LogMethodNames, ...args: any[]): void;
2340
+ /**
2341
+ * 主消息回复入口(karin 调用)
2342
+ */
2343
+ srcReply(e: Message, elements: ElementTypes[]): Promise<SendMsgResults>;
2344
+ /**
2345
+ * 发送消息
2346
+ */
2347
+ sendMsg(contact: Contact, elements: Array<ElementTypes>, _retryCount?: number): Promise<SendMsgResults>;
2348
+ /**
2349
+ * 撤回消息
2350
+ *
2351
+ * 群聊中机器人被群主设为管理员后,也可撤回成员消息;平台仍限制消息发送后两分钟内。
2352
+ * REFIDX 与 API 消息 ID 的映射、单聊"是否自己发送"的判定都直接查询
2353
+ * SQLite 消息缓存(ID 映射行不受缓存开关影响,始终落库)。
2354
+ */
2355
+ recallMsg(contact: Contact, messageId: string): Promise<void>;
2356
+ /**
2357
+ * 构造空发送结果,pipeline 内填充 rawData
2358
+ */
2359
+ initSendMsgResults(): SendMsgResults;
2360
+ /**
2361
+ * 将 rawData[0].id / timestamp 同步到顶层字段
2362
+ */
2363
+ handleResponse(data: SendMsgResults): SendMsgResults;
2364
+ /**
2365
+ * 发送长消息
2366
+ */
2367
+ sendLongMsg(_contact: Contact, _resId: string): Promise<SendMsgResults>;
2368
+ /**
2369
+ * 发送合并转发消息
2370
+ *
2371
+ * QQ 官方没有合并转发能力,这里把各节点摊平成一段 Markdown 正文,节点之间用
2372
+ * 强制换行隔开,不添加任何前缀提示文本。
2373
+ *
2374
+ * 图片以 markdown 图片语法写入,**保留原始来源**(本地路径 / base64 / URL):
2375
+ * 究竟走内置图床、第三方 fileToUrl,还是降级成 msg_type=7 富媒体,由发送
2376
+ * pipeline 统一决定。这里不自己上传,也不自己判断通道——否则频道场景在没有
2377
+ * Markdown 权限时会绕过降级逻辑,直接被平台拒掉。
2378
+ *
2379
+ * 视频 / 语音 / 文件进不了 markdown,作为普通消息段跟随主消息一起交给 pipeline,
2380
+ * 由它在同一次发送里以 msg_type=7 补发。
2381
+ */
2382
+ sendForwardMsg(contact: Contact, elements: Array<NodeElement>, _options?: ForwardOptions): Promise<{
2383
+ messageId: string;
2384
+ forwardId: string;
2385
+ }>;
2386
+ /**
2387
+ * 获取头像 url
2388
+ *
2389
+ * 第三方头像 CDN 的模式是 `qqapp/{appId}/{openid}/{size}`,只有拼用户 openid 才有效;
2390
+ * 机器人自身没有可用的 openid(selfId 就是 appId,拼出 appId/appid 只会得到默认头像),
2391
+ * 因此目标是自己时改走官方 `GET /users/@me` 返回的 avatar 字段,取值与缓存见 self-avatar。
2392
+ */
2393
+ getAvatarUrl(_userId: string, _size?: 0 | 40 | 100 | 140): Promise<string>;
2394
+ /**
2395
+ * 获取群头像 url
2396
+ */
2397
+ getGroupAvatarUrl(_groupId: string, _size?: 0 | 40 | 100 | 140, _history?: number): Promise<string>;
2398
+ /**
2399
+ * 按消息 ID 获取已接收的消息。
2400
+ *
2401
+ * QQ 官方 Bot API 没有历史消息查询接口,因此仅从本地缓存读取。
2402
+ * 消息在接收时已转换为 Karin elements,最长保留一天;引用消息的 `REFIDX`
2403
+ * 索引同样可作为 `messageId` 查询。
2404
+ *
2405
+ * @param input OneBot v11 标准单参 messageId,或用于限定查询范围的 Contact。
2406
+ * @param messageId 当 input 是 Contact 时传入的目标消息 ID。
2407
+ * @returns 命中的消息;未命中时返回空消息结构。
2408
+ */
2409
+ getMsg(input: Contact | string, messageId?: string): Promise<MessageResponse>;
2410
+ /**
2411
+ * 获取本地缓存历史消息(仅支持 message_id)
2412
+ */
2413
+ getHistoryMsg(contact: Contact, startMsgId: string, count: number): Promise<Array<MessageResponse>>;
2414
+ /**
2415
+ * 获取本地缓存历史消息(message_seq 暂不支持)
2416
+ */
2417
+ getHistoryMsg(contact: Contact, startMsgSeq: number, count: number): Promise<Array<MessageResponse>>;
2418
+ /**
2419
+ * 获取合并转发消息
2420
+ */
2421
+ getForwardMsg(_resId: string): Promise<Array<MessageResponse>>;
2422
+ /**
2423
+ * 获取精华消息
2424
+ */
2425
+ getGroupHighlights(_groupId: string, _page: number, _pageSize: number): Promise<Array<GetGroupHighlightsResponse>>;
2426
+ /**
2427
+ * 构造资源 ID
2428
+ */
2429
+ createResId(_contact: Contact, _elements: Array<NodeElement>): Promise<string>;
2430
+ /**
2431
+ * 设置、取消群精华消息
2432
+ */
2433
+ setGroupHighlights(_groupId: string, _messageId: string, _create: boolean): Promise<void>;
2434
+ /**
2435
+ * 发送好友赞
2436
+ */
2437
+ sendLike(_targetId: string, _count: number): Promise<void>;
2438
+ /**
2439
+ * 群踢人
2440
+ *
2441
+ * 走官方 `POST /v2/groups/{group_openid}/batch_remove_members`,机器人需拥有群
2442
+ * 管理员身份。Karin 的 `rejectAddRequest` 映射为官方的 `add_to_member_blacklist`:
2443
+ * 移除的同时拉入群黑名单,该用户之后无法再次入群。官方接口没有踢人理由字段,
2444
+ * `kickReason` 只会被记录到日志。
2445
+ *
2446
+ * 需要一次移除多人时用 `bot.super.groups.batchRemoveGroupMembers()`,单次最多 20 个。
2447
+ *
2448
+ * @param _groupId 群 openid
2449
+ * @param _targetId 群成员 openid
2450
+ * @param _rejectAddRequest 是否同时拉入群黑名单,默认 false
2451
+ * @param _kickReason 官方不支持,仅在传入时输出提示
2452
+ */
2453
+ groupKickMember(_groupId: string, _targetId: string, _rejectAddRequest?: boolean, _kickReason?: string): Promise<void>;
2454
+ /**
2455
+ * 禁言群成员
2456
+ *
2457
+ * 机器人需拥有群管理员身份;平台限制最大禁言时长为 30 天,
2458
+ * 超出部分会被截断到 30 天而不是直接失败。
2459
+ *
2460
+ * @param _groupId 群 openid
2461
+ * @param _targetId 群成员 openid
2462
+ * @param duration 禁言时长(秒),传 0 或负数表示解除禁言
2463
+ */
2464
+ setGroupMute(_groupId: string, _targetId: string, duration: number): Promise<void>;
2465
+ /**
2466
+ * 群全员禁言
2467
+ */
2468
+ setGroupAllMute(_groupId: string, _isBan: boolean): Promise<void>;
2469
+ /**
2470
+ * 设置群管理员
2471
+ */
2472
+ setGroupAdmin(_groupId: string, _targetId: string, _isAdmin: boolean): Promise<void>;
2473
+ /**
2474
+ * 设置群名片
2475
+ */
2476
+ setGroupMemberCard(_groupId: string, _targetId: string, _card: string): Promise<void>;
2477
+ /**
2478
+ * 设置群名
2479
+ */
2480
+ setGroupName(_groupId: string, _groupName: string): Promise<void>;
2481
+ /**
2482
+ * 退出群组
2483
+ */
2484
+ setGroupQuit(_groupId: string, _isDismiss: boolean): Promise<void>;
2485
+ /**
2486
+ * 设置群专属头衔
2487
+ */
2488
+ setGroupMemberTitle(_groupId: string, _targetId: string, _title: string): Promise<void>;
2489
+ /**
2490
+ * 获取陌生人信息
2491
+ */
2492
+ getStrangerInfo(_targetId: string): Promise<UserInfo>;
2493
+ /**
2494
+ * 获取好友列表
2495
+ */
2496
+ getFriendList(_refresh?: boolean): Promise<Array<UserInfo>>;
2497
+ /**
2498
+ * 获取群信息
2499
+ *
2500
+ * QQ 群走官方 `GET /v2/groups/{group_openid}/info`(白名单接口);传入的是频道
2501
+ * ID 时退回 `GET /guilds/{guild_id}`,这样频道场景下的插件调用也能拿到名称和
2502
+ * 人数。两者都不可用(如白名单未开通返回 11253)时降级为空结构并告警。
2503
+ *
2504
+ * @param _groupId 群 openid 或频道 ID。
2505
+ */
2506
+ getGroupInfo(_groupId: string, _noCache?: boolean): Promise<GroupInfo>;
2507
+ /**
2508
+ * 获取群列表
2509
+ *
2510
+ * 官方没有 QQ 群列表接口。频道列表可用 `bot.super.guilds.getGuildList()` 获取,
2511
+ * 但频道在 Karin 里属于 guild 场景,与 QQ 群不是同一类会话,因此不在此处混用。
2512
+ */
2513
+ getGroupList(_refresh?: boolean): Promise<Array<GroupInfo>>;
2514
+ /**
2515
+ * 获取群成员信息
2516
+ *
2517
+ * - 查询机器人自身(targetId 为 selfId)走官方 `GET /v2/groups/{group_openid}/bot_state`。
2518
+ * - 查询其他成员走 `GET /v2/groups/{group_openid}/members/{member_openid}`,该接口在
2519
+ * 接口文档 v1.28.0(2026-09-03)转为公开文档,昵称字段为 `username`,`nick` 是
2520
+ * 转公开之前的字段名,仅作兼容回退。
2521
+ *
2522
+ * 两者都是白名单接口,未开通权限(11253)或查询失败时降级为占位结构并告警。
2523
+ */
2524
+ getGroupMemberInfo(_groupId: string, _targetId: string, _refresh?: boolean): Promise<GroupMemberInfo>;
2525
+ /**
2526
+ * 获取群成员列表
2527
+ *
2528
+ * 走官方 `GET /v2/groups/{group_openid}/members`(白名单接口),每页最多 30 条,
2529
+ * 这里按 `next_cursor` 自动翻完所有页;顺便把昵称写入
2530
+ * {@link AdapterQQBot.nicknameCache},让后续消息事件能直接取到昵称。
2531
+ *
2532
+ * 为防止平台返回的游标不收敛,翻页数有安全上限(约 6000 人),触顶会告警并返回已取到的部分。
2533
+ * 未开通权限(11253)或查询失败时返回已取到的部分并告警。
2534
+ *
2535
+ * @param _groupId 群 openid
2536
+ */
2537
+ getGroupMemberList(_groupId: string, _refresh?: boolean): Promise<Array<GroupMemberInfo>>;
2538
+ /**
2539
+ * 获取群荣誉信息
2540
+ */
2541
+ getGroupHonor(_groupId: string): Promise<Array<QQGroupHonorInfo>>;
2542
+ /**
2543
+ * 设置好友请求结果
2544
+ */
2545
+ setFriendApplyResult(_requestId: string, _isApprove: boolean, _remark?: string): Promise<void>;
2546
+ /**
2547
+ * 审批入群申请。
2548
+ *
2549
+ * 走官方 `POST /v2/groups/{group_openid}/approval_join_request/{member_openid}`,
2550
+ * 机器人需拥有群管理员身份。Karin 只透传 flag(`join_request_id`),群与申请人
2551
+ * openid 由 `join-request-cache` 在收到申请事件时记录,因此仅支持审批本次运行
2552
+ * 期间收到过的申请;历史申请请改用
2553
+ * `bot.super.groups.getJoinRequestList()` + `bot.super.groups.approvalJoinRequest()`。
2554
+ *
2555
+ * @param requestId 申请 ID(Karin 请求事件的 flag)。
2556
+ * @param isApprove 是否通过。
2557
+ * @param denyReason 拒绝理由,仅拒绝时生效。
2558
+ */
2559
+ setGroupApplyResult(requestId: string, isApprove: boolean, denyReason?: string): Promise<void>;
2560
+ /**
2561
+ * 设置邀请加入群请求结果。
2562
+ *
2563
+ * 机器人被邀请入群与用户主动申请入群在官方侧是同一条 `GROUP_JOIN_REQUEST`
2564
+ * 事件,审批走同一个接口,因此直接复用 {@link AdapterQQBot.setGroupApplyResult}。
2565
+ *
2566
+ * @param requestId 申请 ID(Karin 请求事件的 flag)。
2567
+ * @param isApprove 是否通过。
2568
+ */
2569
+ setInvitedJoinGroupResult(requestId: string, isApprove: boolean): Promise<void>;
2570
+ /**
2571
+ * 设置消息表情回应
2572
+ */
2573
+ setMsgReaction(_contact: Contact, _messageId: string, _faceId: number | string, _isSet: boolean): Promise<void>;
2574
+ /**
2575
+ * 上传群文件、私聊文件
2576
+ *
2577
+ * QQ 官方 Bot API 没有群文件系统,上传走 `POST /v2/{users|groups}/{openid}/files`
2578
+ * (file_type=4 + srv_send_msg=true),由服务端直接发送文件消息。
2579
+ * 频道 / 频道私信场景官方无文件接口,暂不支持。
2580
+ */
2581
+ uploadFile(_contact: Contact, _file: string, _name: string, _folder?: string): Promise<void>;
2582
+ /**
2583
+ * 下载文件到协议端本地
2584
+ */
2585
+ downloadFile(_options?: DownloadFileOptions): Promise<DownloadFileResponse>;
2586
+ /**
2587
+ * 创建群文件夹
2588
+ */
2589
+ createGroupFolder(_groupId: string, _name: string): Promise<CreateGroupFolderResponse>;
2590
+ /**
2591
+ * 重命名群文件夹
2592
+ */
2593
+ renameGroupFolder(_groupId: string, _folderId: string, _name: string): Promise<boolean>;
2594
+ /**
2595
+ * 删除群文件夹
2596
+ */
2597
+ delGroupFolder(_groupId: string, _folderId: string): Promise<boolean>;
2598
+ /**
2599
+ * 上传群文件
2600
+ *
2601
+ * 实现同 {@link uploadFile}:官方无群文件系统,走 files 接口由服务端直发文件消息。
2602
+ */
2603
+ uploadGroupFile(_groupId: string, _file: string, _name?: string): Promise<boolean>;
2604
+ /**
2605
+ * 获取文件 url
2606
+ */
2607
+ getFileUrl(_contact: Contact, _fileId: string): Promise<string>;
2608
+ /**
2609
+ * 删除群文件
2610
+ */
2611
+ delGroupFile(_groupId: string, _fileId: string, _busId: number): Promise<boolean>;
2612
+ /**
2613
+ * 获取群文件系统信息
2614
+ */
2615
+ getGroupFileSystemInfo(_groupId: string): Promise<GetGroupFileSystemInfoResponse>;
2616
+ /**
2617
+ * 获取群文件夹下文件列表
2618
+ */
2619
+ getGroupFileList(_groupId: string, _folderId?: string): Promise<GetGroupFileListResponse>;
2620
+ /**
2621
+ * 设置群备注
2622
+ */
2623
+ setGroupRemark(_groupId: string, _remark: string): Promise<boolean>;
2624
+ /**
2625
+ * 获取陌生群信息
2626
+ */
2627
+ getNotJoinedGroupInfo(_groupId: string): Promise<GroupInfo>;
2628
+ /**
2629
+ * 获取艾特全体成员剩余次数
2630
+ */
2631
+ getAtAllCount(_groupId: string): Promise<GetAtAllCountResponse>;
2632
+ /**
2633
+ * 获取群被禁言用户列表
2634
+ *
2635
+ * 走官方 `GET /v2/groups/{group_openid}/restrict_chat_setting`,只返回仍在
2636
+ * 禁言中的成员(不含已过期)。机器人需拥有群管理员身份,无权限或查询失败时
2637
+ * 降级为空数组并告警。
2638
+ *
2639
+ * `muteTime` 为禁言到期时间的 Unix 秒,而非剩余时长;全员禁言规则不在该返回
2640
+ * 结构内,需要时请用 `bot.super.groups.getGroupMuteSetting()` 读取 `global_rule`。
2641
+ *
2642
+ * @param _groupId 群 openid
2643
+ */
2644
+ getGroupMuteList(_groupId: string): Promise<Array<GetGroupMuteListResponse>>;
2645
+ /**
2646
+ * 戳一戳用户
2647
+ */
2648
+ pokeUser(_contact: Contact, _targetId: string, _count?: number): Promise<boolean>;
2649
+ /**
2650
+ * 获取 Cookies
2651
+ */
2652
+ getCookies(_domain: string): Promise<{
2653
+ cookie: string;
2654
+ }>;
2655
+ /**
2656
+ * 获取 QQ 相关接口凭证
2657
+ */
2658
+ getCredentials(_domain: string): Promise<{
2659
+ cookies: string;
2660
+ csrf_token: number;
2661
+ }>;
2662
+ /**
2663
+ * 获取 CSRF Token
2664
+ */
2665
+ getCSRFToken(): Promise<{
2666
+ token: number;
2667
+ }>;
2668
+ /**
2669
+ * 设置头像
2670
+ */
2671
+ setAvatar(_file: string): Promise<void>;
2672
+ /**
2673
+ * 获取 rkey
2674
+ */
2675
+ getRkey(): Promise<Array<GetRkeyResponse>>;
2676
+ /**
2677
+ * 获取群 Ai 语音可用声色列表
2678
+ */
2679
+ getAiCharacters(): Promise<Array<GetAiCharactersResponse>>;
2680
+ /**
2681
+ * 设置群 Ai 语音声色
2682
+ */
2683
+ sendAiCharacter(_groupId: string, _characterId: string, _text: string): Promise<{
2684
+ messageId: string;
2685
+ }>;
2686
+ }
2687
+ //#endregion
2688
+ export { Scene as i, QQBotApi as n, MediaType as r, AdapterQQBot as t };