@karinjs/adapter-qqbot 3.0.0 → 3.0.1
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/dist/apps/cleanup.js +1 -1
- package/dist/apps/login.d.ts +2 -16
- package/dist/apps/login.js +138 -85
- package/dist/{config-BUuU6FnQ.js → config-D1_LqrcJ.js} +2 -99
- package/dist/index.d.ts +10 -29
- package/dist/index.js +102 -115
- package/dist/logger-sza6kuy3.js +27 -0
- package/dist/{message-BTGL3TSn.js → message-CVJVFAGR.js} +2 -1
- package/dist/utils-lb9ZdWay.js +32 -0
- package/dist/web.config.d.ts +0 -5
- package/dist/web.config.js +4 -87
- package/package.json +3 -2
- package/dist/common-by1GpV0b.js +0 -49
- package/dist/onboard-vIEoe9dB.js +0 -252
- package/dist/utils-N9PNiHjE.js +0 -4
package/dist/apps/cleanup.js
CHANGED
package/dist/apps/login.d.ts
CHANGED
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
//#region src/apps/login.d.ts
|
|
2
|
-
|
|
3
|
-
* #QQ登录 指令
|
|
4
|
-
*
|
|
5
|
-
* 仅主人可用。匹配 `#QQ登录` 或 `#qqlogin`(大小写均可)。
|
|
6
|
-
* 必须带 `#` 前缀。
|
|
7
|
-
*
|
|
8
|
-
* 流程:
|
|
9
|
-
* 1. 立即回复"开始扫码"
|
|
10
|
-
* 2. 触发扫码授权流程
|
|
11
|
-
* 3. 每次生成新二维码 → 把 PNG 图片回复给触发者
|
|
12
|
-
* 4. 授权成功 → 回复结果,watch 回调自动初始化 bot
|
|
13
|
-
*
|
|
14
|
-
* ⚠ 注意:扫码授权会刷新该 appId 的 secret,旧 secret 立即失效
|
|
15
|
-
*/
|
|
16
|
-
declare const qqLogin: import("node-karin").Command<keyof import("node-karin").MessageEventMap>;
|
|
2
|
+
declare const QQBotLogin: import("node-karin").Command<keyof import("node-karin").MessageEventMap>;
|
|
17
3
|
//#endregion
|
|
18
|
-
export {
|
|
4
|
+
export { QQBotLogin };
|
package/dist/apps/login.js
CHANGED
|
@@ -1,106 +1,159 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as runQrOnboard } from "../onboard-vIEoe9dB.js";
|
|
1
|
+
import { i as getDefaultConfig, n as config } from "../config-D1_LqrcJ.js";
|
|
3
2
|
import karin, { segment } from "node-karin";
|
|
3
|
+
import qrcode from "qrcode";
|
|
4
|
+
import axios from "node-karin/axios";
|
|
5
|
+
import crypto from "node:crypto";
|
|
4
6
|
|
|
5
|
-
//#region src/
|
|
7
|
+
//#region src/core/qrcode/session.ts
|
|
8
|
+
const BASEURL = "q.qq.com";
|
|
9
|
+
const headers = {
|
|
10
|
+
"Content-Type": "application/json",
|
|
11
|
+
Accept: "application/json"
|
|
12
|
+
};
|
|
13
|
+
/** 生成随机密钥 */
|
|
14
|
+
const RandomKey = () => {
|
|
15
|
+
return crypto.randomBytes(32).toString("base64");
|
|
16
|
+
};
|
|
6
17
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 流程:
|
|
13
|
-
* 1. 立即回复"开始扫码"
|
|
14
|
-
* 2. 触发扫码授权流程
|
|
15
|
-
* 3. 每次生成新二维码 → 把 PNG 图片回复给触发者
|
|
16
|
-
* 4. 授权成功 → 回复结果,watch 回调自动初始化 bot
|
|
17
|
-
*
|
|
18
|
-
* ⚠ 注意:扫码授权会刷新该 appId 的 secret,旧 secret 立即失效
|
|
18
|
+
* 解密密钥
|
|
19
|
+
* @param encryptedBase64
|
|
20
|
+
* @param keyBase64
|
|
21
|
+
* @returns
|
|
19
22
|
*/
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const decryptSecret = (encryptedBase64, keyBase64) => {
|
|
24
|
+
const key = Buffer.from(keyBase64, "base64");
|
|
25
|
+
const data = Buffer.from(encryptedBase64, "base64");
|
|
26
|
+
const IV = data.subarray(0, 12);
|
|
27
|
+
const authtag = data.subarray(data.length - 16);
|
|
28
|
+
const ciphertext = data.subarray(12, data.length - 16);
|
|
29
|
+
const decipher = crypto.createDecipheriv("aes-256-gcm", key, IV);
|
|
30
|
+
decipher.setAuthTag(authtag);
|
|
31
|
+
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
32
|
+
};
|
|
22
33
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
34
|
+
* 创建绑定任务
|
|
35
|
+
* @param timeout 超时时间
|
|
25
36
|
*/
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
37
|
+
const createBindTask = async (timeout = 1e4) => {
|
|
38
|
+
const url = `https://${BASEURL}/lite/create_bind_task`;
|
|
39
|
+
const key = RandomKey();
|
|
40
|
+
const { data } = await axios.post(url, { key }, {
|
|
41
|
+
headers,
|
|
42
|
+
timeout
|
|
43
|
+
});
|
|
44
|
+
if (data.retcode !== 0) throw new Error(data.msg ?? "创建绑定任务失败");
|
|
45
|
+
if (!data.data?.task_id) throw new Error("创建绑定任务失败: task_id 缺失");
|
|
46
|
+
return {
|
|
47
|
+
taskId: data.data.task_id,
|
|
48
|
+
aesKey: key
|
|
49
|
+
};
|
|
31
50
|
};
|
|
32
51
|
/**
|
|
33
|
-
*
|
|
34
|
-
* @param
|
|
35
|
-
* @param
|
|
52
|
+
* 查询绑定结果
|
|
53
|
+
* @param taskId 任务id
|
|
54
|
+
* @param timeout 超时时间
|
|
36
55
|
*/
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
|
|
56
|
+
const checkBindResult = async (taskId, timeout = 1e4) => {
|
|
57
|
+
const url = `https://${BASEURL}/lite/poll_bind_result`;
|
|
58
|
+
const { data } = await axios.post(url, { task_id: taskId }, {
|
|
59
|
+
headers,
|
|
60
|
+
timeout
|
|
61
|
+
});
|
|
62
|
+
if (data.retcode !== 0) throw new Error(data.msg ?? "查询绑定结果失败");
|
|
63
|
+
return {
|
|
64
|
+
status: data.data?.status ?? 0,
|
|
65
|
+
appId: String(data.data?.bot_appid ?? ""),
|
|
66
|
+
encryptedSecret: data.data?.bot_encrypt_secret ?? "",
|
|
67
|
+
userOpenid: data.data?.user_openid ?? void 0
|
|
68
|
+
};
|
|
40
69
|
};
|
|
70
|
+
/** 构建连接URL */
|
|
71
|
+
const buildConnectUrl = (taskId) => `https://${BASEURL}/qqbot/openclaw/connect.html?task_id=${encodeURIComponent(taskId)}&source=karin&_wv=2`;
|
|
72
|
+
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/core/qrcode/qr.ts
|
|
75
|
+
const WaitingMS = 2e3;
|
|
41
76
|
/**
|
|
42
|
-
*
|
|
43
|
-
* @param
|
|
44
|
-
* @param
|
|
45
|
-
* @
|
|
77
|
+
* 轮询绑定结果
|
|
78
|
+
* @param taskId 任务ID
|
|
79
|
+
* @param key 解密密钥
|
|
80
|
+
* @returns QQBot 的appid与secret
|
|
46
81
|
*/
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
82
|
+
const PollBindResult = async (taskId, key) => {
|
|
83
|
+
while (true) {
|
|
84
|
+
let data;
|
|
85
|
+
try {
|
|
86
|
+
data = await checkBindResult(taskId);
|
|
87
|
+
} catch {
|
|
88
|
+
await new Promise((resolve) => setTimeout(resolve, WaitingMS));
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (data.status === 2) {
|
|
92
|
+
const secret = decryptSecret(data.encryptedSecret, key);
|
|
93
|
+
return {
|
|
94
|
+
status: data.status,
|
|
95
|
+
appId: data.appId,
|
|
96
|
+
secret
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (data.status === 3) return { status: data.status };
|
|
100
|
+
await new Promise((resolve) => setTimeout(resolve, WaitingMS));
|
|
52
101
|
}
|
|
53
|
-
messageIds.length = 0;
|
|
54
102
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* @param elements 回复内容。
|
|
65
|
-
*/
|
|
66
|
-
const replyAndTrack = async (elements) => {
|
|
67
|
-
const result = await e.reply(elements);
|
|
68
|
-
trackReply(result, messageIds);
|
|
69
|
-
return result;
|
|
103
|
+
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/apps/login.ts
|
|
106
|
+
let busy = false;
|
|
107
|
+
const QQBotLogin = karin.command(/^#qqbot(登录|login)$/i, async (e) => {
|
|
108
|
+
const msgIds = [];
|
|
109
|
+
const reply = async (elements) => {
|
|
110
|
+
const res = await e.reply(elements, { at: true });
|
|
111
|
+
msgIds.push(res.messageId);
|
|
70
112
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
segment.image(base64),
|
|
82
|
-
segment.text(`或在手机 QQ 打开链接:\n${url}`)
|
|
83
|
-
]);
|
|
84
|
-
} catch (err) {
|
|
85
|
-
log("warn", "[扫码登录] 推送二维码失败:", err);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
113
|
+
if (busy) return await e.reply("已有扫码授权在进行中,请稍候再试", { reply: true });
|
|
114
|
+
busy = true;
|
|
115
|
+
await reply("注意: 确认登录后将刷新 QQBot 的 AppSecret,旧的 AppSecret 将失效");
|
|
116
|
+
const task = await createBindTask();
|
|
117
|
+
const url = buildConnectUrl(task.taskId);
|
|
118
|
+
const msg = [segment.text("请使用 QQ 扫码登录")];
|
|
119
|
+
if (e.bot.adapter.protocol === "console") {
|
|
120
|
+
const qrcode$1 = await qrcode.toString(url, {
|
|
121
|
+
type: "terminal",
|
|
122
|
+
small: true
|
|
88
123
|
});
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
124
|
+
msg.push(segment.text(`\n${qrcode$1}`));
|
|
125
|
+
} else {
|
|
126
|
+
const qrcode$2 = await qrcode.toDataURL(url);
|
|
127
|
+
msg.push(segment.image(qrcode$2));
|
|
128
|
+
}
|
|
129
|
+
msg.push(segment.text(`或使用手机 QQ 打开链接登录: ${url}`));
|
|
130
|
+
await reply(msg);
|
|
131
|
+
const ok = await PollBindResult(task.taskId, task.aesKey);
|
|
132
|
+
msgIds.forEach(async (id) => {
|
|
133
|
+
await e.bot.recallMsg(e.contact, id).catch(() => {});
|
|
134
|
+
});
|
|
135
|
+
if (ok.status === 2) {
|
|
136
|
+
const list = config();
|
|
137
|
+
const idx = list.findIndex((item) => item.appId === ok.appId);
|
|
138
|
+
if (idx >= 0) {
|
|
139
|
+
list[idx].secret = ok.secret;
|
|
140
|
+
e.reply(`Bot存在,已更新[${ok.appId}]配置`, { reply: true });
|
|
141
|
+
} else {
|
|
142
|
+
const defaults = getDefaultConfig()[0];
|
|
143
|
+
list.push({
|
|
144
|
+
...defaults,
|
|
145
|
+
appId: ok.appId,
|
|
146
|
+
secret: ok.secret
|
|
147
|
+
});
|
|
148
|
+
e.reply(`[${ok.appId}] 扫码登录成功`, { reply: true });
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
98
151
|
}
|
|
152
|
+
return await e.reply("二维码过期,请重新触发指令", { reply: true });
|
|
99
153
|
}, {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
authFailMsg: "#QQ登录 仅限主人使用"
|
|
154
|
+
perm: "master",
|
|
155
|
+
name: "QQBot 扫码登录"
|
|
103
156
|
});
|
|
104
157
|
|
|
105
158
|
//#endregion
|
|
106
|
-
export {
|
|
159
|
+
export { QQBotLogin };
|
|
@@ -11,30 +11,6 @@ const dirPath = path.resolve(filePath, "../..");
|
|
|
11
11
|
/** 插件包的名称 */
|
|
12
12
|
const basename = path.basename(dirPath);
|
|
13
13
|
|
|
14
|
-
//#endregion
|
|
15
|
-
//#region src/utils/logger.ts
|
|
16
|
-
const PREFIX = "[QQ Official Bot]";
|
|
17
|
-
const m = {
|
|
18
|
-
trace: (...a) => logger.trace(PREFIX, ...a),
|
|
19
|
-
debug: (...a) => logger.debug(PREFIX, ...a),
|
|
20
|
-
info: (...a) => logger.info(PREFIX, ...a),
|
|
21
|
-
warn: (...a) => logger.warn(PREFIX, ...a),
|
|
22
|
-
error: (...a) => logger.error(PREFIX, ...a),
|
|
23
|
-
fatal: (...a) => logger.fatal(PREFIX, ...a),
|
|
24
|
-
mark: (...a) => logger.mark(PREFIX, ...a)
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* QQBot 日志函数
|
|
28
|
-
* - log('info', '消息')
|
|
29
|
-
* - log.info('消息')
|
|
30
|
-
*
|
|
31
|
-
* 日志级别由 karin 框架的 log.level 控制
|
|
32
|
-
*/
|
|
33
|
-
function log(level, ...args) {
|
|
34
|
-
m[level](...args);
|
|
35
|
-
}
|
|
36
|
-
Object.assign(log, m);
|
|
37
|
-
|
|
38
14
|
//#endregion
|
|
39
15
|
//#region src/utils/plugin.ts
|
|
40
16
|
/**
|
|
@@ -48,56 +24,6 @@ const pluginName = pkg().name;
|
|
|
48
24
|
/** 文件系统目录名:把 npm 包名里的 `/` 规范化为 `-`,与 Karin 框架对齐。 */
|
|
49
25
|
const pluginDirName = pluginName.replace(/\//g, "-");
|
|
50
26
|
|
|
51
|
-
//#endregion
|
|
52
|
-
//#region src/utils/proxy-url.ts
|
|
53
|
-
/**
|
|
54
|
-
* HTTP / token 地址只清理首尾空白。完整接口地址是否带尾斜杠可能有路由含义,不能替用户改。
|
|
55
|
-
*/
|
|
56
|
-
const normalizeHttpUrl = (raw) => raw.trim();
|
|
57
|
-
/**
|
|
58
|
-
* 拼接 OpenAPI 路径时再处理斜杠,避免配置值本身被改写。
|
|
59
|
-
*/
|
|
60
|
-
const joinHttpPath = (base, path) => {
|
|
61
|
-
return `${normalizeHttpUrl(base).replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
|
62
|
-
};
|
|
63
|
-
/**
|
|
64
|
-
* WebSocket 网关地址:
|
|
65
|
-
* - ws:// / wss:// 原样保留协议
|
|
66
|
-
* - http:// / https:// 映射为 ws:// / wss://
|
|
67
|
-
* - 未写协议时按 wss:// 处理
|
|
68
|
-
*
|
|
69
|
-
* 这里只做最小处理,不改 path / query / hash。自定义网关的尾斜杠和查询参数都可能有路由含义。
|
|
70
|
-
*/
|
|
71
|
-
const normalizeWsGatewayUrl = (raw) => {
|
|
72
|
-
const value = raw.trim();
|
|
73
|
-
if (!value) return "";
|
|
74
|
-
let normalized = value;
|
|
75
|
-
const scheme = value.match(/^([a-z][a-z\d+.-]*):\/\//i)?.[1]?.toLowerCase();
|
|
76
|
-
if (scheme === "http" || scheme === "https") normalized = value.replace(/^http/i, "ws");
|
|
77
|
-
else if (scheme && scheme !== "ws" && scheme !== "wss") throw new Error(`unsupported websocket protocol: ${scheme}:`);
|
|
78
|
-
else if (!scheme) normalized = `wss://${value}`;
|
|
79
|
-
const parsed = new URL(normalized);
|
|
80
|
-
if (parsed.protocol !== "ws:" && parsed.protocol !== "wss:") throw new Error(`unsupported websocket protocol: ${parsed.protocol}`);
|
|
81
|
-
return normalized;
|
|
82
|
-
};
|
|
83
|
-
/**
|
|
84
|
-
* 只有从 OpenAPI 根地址推导官方 fallback 网关时,才主动拼 `/websocket/`。
|
|
85
|
-
*/
|
|
86
|
-
const buildFallbackWsUrlFromApi = (apiUrl) => {
|
|
87
|
-
const parsed = new URL(normalizeWsGatewayUrl(apiUrl));
|
|
88
|
-
parsed.pathname = `${parsed.pathname.replace(/\/+$/, "")}/websocket/`;
|
|
89
|
-
parsed.search = "";
|
|
90
|
-
parsed.hash = "";
|
|
91
|
-
return parsed.toString();
|
|
92
|
-
};
|
|
93
|
-
const normalizeProxyConfig = (proxy) => ({
|
|
94
|
-
prodApi: normalizeHttpUrl(proxy.prodApi),
|
|
95
|
-
sandboxApi: normalizeHttpUrl(proxy.sandboxApi),
|
|
96
|
-
tokenApi: normalizeHttpUrl(proxy.tokenApi),
|
|
97
|
-
prodWs: normalizeWsGatewayUrl(proxy.prodWs),
|
|
98
|
-
sandboxWs: normalizeWsGatewayUrl(proxy.sandboxWs)
|
|
99
|
-
});
|
|
100
|
-
|
|
101
27
|
//#endregion
|
|
102
28
|
//#region src/utils/config.ts
|
|
103
29
|
let cache;
|
|
@@ -159,23 +85,10 @@ const writeConfig = (data) => {
|
|
|
159
85
|
const formatConfig = (user) => {
|
|
160
86
|
const def = getDefaultConfig()[0];
|
|
161
87
|
return user.map((item) => {
|
|
162
|
-
const {
|
|
88
|
+
const { markdown, messageCache, event, ...rest } = item;
|
|
163
89
|
return {
|
|
164
90
|
...def,
|
|
165
91
|
...rest,
|
|
166
|
-
proxy: normalizeProxyConfig({
|
|
167
|
-
...def.proxy,
|
|
168
|
-
...proxy,
|
|
169
|
-
prodApi: proxy?.prodApi || prodApi || def.proxy.prodApi,
|
|
170
|
-
sandboxApi: proxy?.sandboxApi || sandboxApi || def.proxy.sandboxApi,
|
|
171
|
-
tokenApi: proxy?.tokenApi || tokenApi || def.proxy.tokenApi,
|
|
172
|
-
prodWs: proxy?.prodWs || proxy?.wsUrl || wsUrl || def.proxy.prodWs,
|
|
173
|
-
sandboxWs: proxy?.sandboxWs || proxy?.wsUrl || wsUrl || def.proxy.sandboxWs
|
|
174
|
-
}),
|
|
175
|
-
keyboard: {
|
|
176
|
-
...def.keyboard,
|
|
177
|
-
...keyboard
|
|
178
|
-
},
|
|
179
92
|
markdown: {
|
|
180
93
|
...def.markdown,
|
|
181
94
|
...markdown
|
|
@@ -231,17 +144,8 @@ const clampNumber = (value, min, max, fallback) => {
|
|
|
231
144
|
* 默认配置
|
|
232
145
|
*/
|
|
233
146
|
const getDefaultConfig = () => [{
|
|
234
|
-
name: "",
|
|
235
147
|
appId: "",
|
|
236
148
|
secret: "",
|
|
237
|
-
proxy: {
|
|
238
|
-
prodApi: "https://api.sgroup.qq.com",
|
|
239
|
-
sandboxApi: "https://sandbox.api.sgroup.qq.com",
|
|
240
|
-
tokenApi: "https://bots.qq.com/app/getAppAccessToken",
|
|
241
|
-
prodWs: "wss://api.sgroup.qq.com/websocket/",
|
|
242
|
-
sandboxWs: "wss://sandbox.api.sgroup.qq.com/websocket/"
|
|
243
|
-
},
|
|
244
|
-
sandbox: false,
|
|
245
149
|
qqEnable: true,
|
|
246
150
|
guildEnable: true,
|
|
247
151
|
guildMode: 0,
|
|
@@ -249,7 +153,6 @@ const getDefaultConfig = () => [{
|
|
|
249
153
|
reg: "^/",
|
|
250
154
|
rep: "#"
|
|
251
155
|
}],
|
|
252
|
-
keyboard: { enable: true },
|
|
253
156
|
markdown: { enable: true },
|
|
254
157
|
messageCache: {
|
|
255
158
|
enable: false,
|
|
@@ -290,4 +193,4 @@ setTimeout(() => {
|
|
|
290
193
|
}, 2e3);
|
|
291
194
|
|
|
292
195
|
//#endregion
|
|
293
|
-
export { readConfigFile as a,
|
|
196
|
+
export { readConfigFile as a, pluginDirName as c, getDefaultConfig as i, basename as l, config as n, writeConfig as o, getConfig as r, pkg as s, bindHandlers as t };
|
package/dist/index.d.ts
CHANGED
|
@@ -334,7 +334,7 @@ interface UploadMediaResponse {
|
|
|
334
334
|
/**
|
|
335
335
|
* 创建 axios 实例,自动从 tokens map 取最新 access_token
|
|
336
336
|
*/
|
|
337
|
-
declare const createAxiosInstance: (
|
|
337
|
+
declare const createAxiosInstance: (appId: string) => import("node-karin/axios").AxiosInstance;
|
|
338
338
|
//#endregion
|
|
339
339
|
//#region src/core/api/http.d.ts
|
|
340
340
|
type AxiosInstance = ReturnType<typeof createAxiosInstance>;
|
|
@@ -517,11 +517,18 @@ declare class GroupsApi extends Http {
|
|
|
517
517
|
/**
|
|
518
518
|
* 获取群成员详情
|
|
519
519
|
*
|
|
520
|
-
* 未公开文档,来自腾讯官方 openclaw 插件(v2.0.0)的接口速查。
|
|
521
520
|
* @param groupOpenid 群 openid
|
|
522
521
|
* @param memberOpenid 群成员 openid
|
|
523
522
|
*/
|
|
524
523
|
getGroupMember(groupOpenid: string, memberOpenid: string): Promise<QQGroupMemberResponse>;
|
|
524
|
+
/**
|
|
525
|
+
* 设置群成员禁言
|
|
526
|
+
* @param groupOpenid 群 openid
|
|
527
|
+
* @param memberOpenid 群成员 openid
|
|
528
|
+
* @param op 操作: add 增加禁言,update 更新禁言到期时间,del 解除禁言
|
|
529
|
+
* @param duration 禁言时间使用RFC3339 格式
|
|
530
|
+
*/
|
|
531
|
+
setGroupMetu(groupOpenid: string, memberOpenid: string, op: 'add' | 'update' | 'del', duration: string): Promise<{}>;
|
|
525
532
|
}
|
|
526
533
|
//#endregion
|
|
527
534
|
//#region src/core/api/index.d.ts
|
|
@@ -562,21 +569,6 @@ declare class QQBotApi {
|
|
|
562
569
|
}
|
|
563
570
|
//#endregion
|
|
564
571
|
//#region src/types/config.d.ts
|
|
565
|
-
/**
|
|
566
|
-
* 自定义连接代理配置
|
|
567
|
-
*/
|
|
568
|
-
interface QQBotProxyConfig {
|
|
569
|
-
/** 正式环境 API */
|
|
570
|
-
prodApi: string;
|
|
571
|
-
/** 测试环境 API */
|
|
572
|
-
sandboxApi: string;
|
|
573
|
-
/** 调用凭证 API */
|
|
574
|
-
tokenApi: string;
|
|
575
|
-
/** 正式环境 WebSocket 网关 */
|
|
576
|
-
prodWs: string;
|
|
577
|
-
/** 测试环境 WebSocket 网关 */
|
|
578
|
-
sandboxWs: string;
|
|
579
|
-
}
|
|
580
572
|
/**
|
|
581
573
|
* 消息缓存存储分级。
|
|
582
574
|
*
|
|
@@ -589,16 +581,10 @@ type MessageCacheLevel = 'minimal' | 'standard' | 'full';
|
|
|
589
581
|
* 单个 QQBot 配置
|
|
590
582
|
*/
|
|
591
583
|
interface QQBotConfig {
|
|
592
|
-
/** 机器人名称 */
|
|
593
|
-
name: string;
|
|
594
584
|
/** 机器人 ID */
|
|
595
585
|
appId: string;
|
|
596
586
|
/** 机器人密钥 */
|
|
597
587
|
secret: string;
|
|
598
|
-
/** 自定义连接代理 */
|
|
599
|
-
proxy: QQBotProxyConfig;
|
|
600
|
-
/** 开启沙盒环境 */
|
|
601
|
-
sandbox: boolean;
|
|
602
588
|
/** 开启 QQ 场景能力(单聊 / 群聊) */
|
|
603
589
|
qqEnable: boolean;
|
|
604
590
|
/** 开启频道场景能力 */
|
|
@@ -610,11 +596,6 @@ interface QQBotConfig {
|
|
|
610
596
|
reg: string | RegExp;
|
|
611
597
|
rep: string;
|
|
612
598
|
}[];
|
|
613
|
-
/** 按钮自动化 */
|
|
614
|
-
keyboard: {
|
|
615
|
-
/** 是否将文本中的 URL 自动转换为 keyboard 按钮 */
|
|
616
|
-
enable: boolean;
|
|
617
|
-
};
|
|
618
599
|
/** Markdown 通道 */
|
|
619
600
|
markdown: {
|
|
620
601
|
/** 是否启用 Markdown 通道发送消息 */
|
|
@@ -1165,7 +1146,7 @@ declare class AdapterQQBot extends AdapterBase implements AdapterType {
|
|
|
1165
1146
|
/**
|
|
1166
1147
|
* 禁言群成员
|
|
1167
1148
|
*/
|
|
1168
|
-
setGroupMute(_groupId: string, _targetId: string,
|
|
1149
|
+
setGroupMute(_groupId: string, _targetId: string, duration: number): Promise<void>;
|
|
1169
1150
|
/**
|
|
1170
1151
|
* 群全员禁言
|
|
1171
1152
|
*/
|