@alemonjs/qq-bot 2.1.36 → 2.1.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -1979
- package/lib/config.d.ts +5 -0
- package/lib/framework-actions.d.ts +75 -0
- package/lib/framework-actions.js +620 -0
- package/lib/framework-events.d.ts +10 -0
- package/lib/framework-events.js +182 -0
- package/lib/hook.d.ts +16 -12
- package/lib/hook.js +5 -9
- package/lib/index.d.ts +6 -1
- package/lib/index.js +2 -1
- package/lib/index.websoket.js +6 -2
- package/lib/message/AUDIO_EVENT.d.ts +20 -0
- package/lib/message/AUDIO_EVENT.js +1 -0
- package/lib/message/FORUM_EVENT.d.ts +33 -0
- package/lib/message/FORUM_EVENT.js +1 -0
- package/lib/message/GUILD_AUDIT.d.ts +14 -0
- package/lib/message/GUILD_AUDIT.js +1 -0
- package/lib/message/INTERACTION_CREATE.d.ts +13 -20
- package/lib/message/MESSAGE_CREATE.d.ts +3 -9
- package/lib/message/MESSAGE_DELETE.d.ts +15 -1
- package/lib/message/group/C2C_MESSAGE_CREATE.d.ts +3 -13
- package/lib/message/group/C2C_MSG_RECEIVE.d.ts +1 -1
- package/lib/message/group/C2C_MSG_REJECT.d.ts +1 -1
- package/lib/message/group/FRIEND_ADD.d.ts +7 -1
- package/lib/message/group/FRIEND_DEL.d.ts +4 -1
- package/lib/message/group/GROUP_AT_MESSAGE_CREATE.d.ts +6 -27
- package/lib/message/group/GROUP_MEMBER_ADD.d.ts +4 -2
- package/lib/message/group/GROUP_MEMBER_REMOVE.d.ts +4 -2
- package/lib/message/group/GROUP_MESSAGE_CREATE.d.ts +6 -27
- package/lib/message/group/GROUP_MSG_RECEIVE.d.ts +1 -1
- package/lib/message/group/GROUP_MSG_REJECT.d.ts +1 -1
- package/lib/message/group/MESSAGE_AUDIT_PASS.d.ts +2 -0
- package/lib/message/group/MESSAGE_AUDIT_REJECT.d.ts +2 -0
- package/lib/message/group/SUBSCRIBE_MESSAGE_STATUS.d.ts +17 -0
- package/lib/message/group/SUBSCRIBE_MESSAGE_STATUS.js +1 -0
- package/lib/register.d.ts +1 -0
- package/lib/register.js +287 -115
- package/lib/sdk/api.d.ts +93 -14
- package/lib/sdk/api.js +241 -45
- package/lib/sdk/client.webhook.js +39 -19
- package/lib/sdk/client.websoket.js +2 -1
- package/lib/sdk/instance.d.ts +1 -6
- package/lib/sdk/instance.js +20 -66
- package/lib/sdk/intents.d.ts +1 -0
- package/lib/sdk/intents.js +1 -0
- package/lib/sdk/message.d.ts +1 -1
- package/lib/sdk/message.group.d.ts +4 -2
- package/lib/sdk/message.guild.d.ts +19 -0
- package/lib/sdk/non-channel-types.d.ts +138 -0
- package/lib/sdk/non-channel-types.js +1 -0
- package/lib/sdk/registry.js +2 -2
- package/lib/sdk/typing.d.ts +13 -1
- package/lib/sdk/webhook.secret.d.ts +1 -1
- package/lib/sdk/webhook.secret.js +10 -5
- package/lib/sends.d.ts +3 -3
- package/lib/sends.js +46 -10
- package/lib/text-sanitizer.d.ts +13 -0
- package/lib/text-sanitizer.js +26 -0
- package/lib/upload.js +13 -37
- package/package.json +8 -6
|
@@ -9,6 +9,7 @@ import { v4 } from "uuid";
|
|
|
9
9
|
//#region src/sdk/client.webhook.ts
|
|
10
10
|
const normalizeGatewayMessage = (message) => {
|
|
11
11
|
if (!message?.id || !message?.d || typeof message.d !== "object" || Array.isArray(message.d)) return message;
|
|
12
|
+
if (message.t === "INTERACTION_CREATE") message.d.event_id = message.id;
|
|
12
13
|
if (message.d.id === void 0 || message.d.id === null || message.d.id === "") message.d.id = message.id;
|
|
13
14
|
return message;
|
|
14
15
|
};
|
|
@@ -23,7 +24,7 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
23
24
|
* @param opstion
|
|
24
25
|
*/
|
|
25
26
|
constructor(opstion) {
|
|
26
|
-
super(opstion);
|
|
27
|
+
super({ ...opstion });
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* 注册事件处理程序
|
|
@@ -67,7 +68,13 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
67
68
|
if (!ws) {
|
|
68
69
|
this.#setTimeoutBotConfig();
|
|
69
70
|
this.#app = new Koa();
|
|
70
|
-
this.#app.use(bodyParser(
|
|
71
|
+
this.#app.use(bodyParser({
|
|
72
|
+
enableTypes: ["json"],
|
|
73
|
+
onerror: (_error, ctx) => {
|
|
74
|
+
ctx.status = 400;
|
|
75
|
+
ctx.body = { msg: "invalid json" };
|
|
76
|
+
}
|
|
77
|
+
}));
|
|
71
78
|
const router = new Router();
|
|
72
79
|
const port = this.config.get("port");
|
|
73
80
|
const secret = this.config.get("secret");
|
|
@@ -77,31 +84,39 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
77
84
|
port: port ? Number(port) : 17157
|
|
78
85
|
};
|
|
79
86
|
const ntqqWebhook = new WebhookAPI({ secret: cfg.secret });
|
|
80
|
-
this.#app.use(async (ctx, next) => {
|
|
81
|
-
let rawData = "";
|
|
82
|
-
ctx.req.on("data", (chunk) => rawData += chunk);
|
|
83
|
-
ctx.req.on("end", () => ctx.request.rawBody = rawData);
|
|
84
|
-
await next();
|
|
85
|
-
});
|
|
86
87
|
router.post(route, (ctx) => {
|
|
87
|
-
const
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
const request = ctx.request;
|
|
89
|
+
const body = request.body;
|
|
90
|
+
if (!body || typeof body !== "object" || Array.isArray(body) || !Number.isInteger(body.op)) {
|
|
91
|
+
ctx.status = 400;
|
|
92
|
+
ctx.body = { msg: "invalid payload" };
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (body.op !== 13 && !ntqqWebhook.validSign(ctx.get("x-signature-timestamp"), request.rawBody, ctx.get("x-signature-ed25519"))) {
|
|
91
96
|
ctx.status = 400;
|
|
92
97
|
ctx.body = { msg: "invalid signature" };
|
|
93
98
|
return;
|
|
94
99
|
}
|
|
95
|
-
|
|
96
|
-
|
|
100
|
+
if (body.op === 13) {
|
|
101
|
+
if (typeof body.d?.plain_token !== "string" || !body.d.plain_token || typeof body.d?.event_ts !== "string" || !body.d.event_ts) {
|
|
102
|
+
ctx.status = 400;
|
|
103
|
+
ctx.body = { msg: "invalid validation" };
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
97
106
|
ctx.status = 200;
|
|
98
107
|
ctx.body = {
|
|
99
108
|
plain_token: body.d.plain_token,
|
|
100
109
|
signature: ntqqWebhook.getSign(body.d.event_ts, body.d.plain_token)
|
|
101
110
|
};
|
|
102
|
-
} else if (
|
|
111
|
+
} else if (body.op === 0) {
|
|
112
|
+
if (typeof body.t !== "string" || !body.t || !body.d || typeof body.d !== "object" || Array.isArray(body.d)) {
|
|
113
|
+
ctx.status = 400;
|
|
114
|
+
ctx.body = { msg: "invalid dispatch" };
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
normalizeGatewayMessage(body);
|
|
103
118
|
ctx.status = 204;
|
|
104
|
-
|
|
119
|
+
this.#dispatch(body);
|
|
105
120
|
const accessToken = this.config.get("access_token");
|
|
106
121
|
for (const client of this.#client) try {
|
|
107
122
|
if (accessToken) body["access_token"] = accessToken;
|
|
@@ -130,7 +145,7 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
130
145
|
ws.on("message", (message) => {
|
|
131
146
|
try {
|
|
132
147
|
const body = normalizeGatewayMessage(JSON.parse(message.toString()));
|
|
133
|
-
|
|
148
|
+
this.#dispatch(body);
|
|
134
149
|
} catch (e) {
|
|
135
150
|
this.#error(e);
|
|
136
151
|
}
|
|
@@ -153,7 +168,7 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
153
168
|
const body = normalizeGatewayMessage(JSON.parse(data.toString()));
|
|
154
169
|
const accessToken = body["access_token"];
|
|
155
170
|
if (accessToken) this.config.set("access_token", accessToken);
|
|
156
|
-
|
|
171
|
+
this.#dispatch(body);
|
|
157
172
|
} catch (e) {
|
|
158
173
|
this.#error(e);
|
|
159
174
|
}
|
|
@@ -176,12 +191,17 @@ var QQBotClient = class extends QQBotAPI {
|
|
|
176
191
|
this.#error(e);
|
|
177
192
|
}
|
|
178
193
|
}
|
|
194
|
+
/** Acknowledge receipt without waiting for application work. Each listener
|
|
195
|
+
* owns its failure path so a rejection cannot escape the transport. */
|
|
196
|
+
#dispatch(body) {
|
|
197
|
+
for (const event of this.#events[body.t] || []) Promise.resolve().then(() => event(body.d)).catch((error) => this.#error(error));
|
|
198
|
+
}
|
|
179
199
|
/**
|
|
180
200
|
*
|
|
181
201
|
* @param error
|
|
182
202
|
*/
|
|
183
203
|
#error(error) {
|
|
184
|
-
|
|
204
|
+
for (const event of this.#events["ERROR"] || []) Promise.resolve().then(() => event(error)).catch((failure) => console.error("[qq-bot] ERROR listener failed", failure instanceof Error ? failure.name : "UnknownError"));
|
|
185
205
|
}
|
|
186
206
|
};
|
|
187
207
|
|
|
@@ -6,6 +6,7 @@ import WebSocket$1 from "ws";
|
|
|
6
6
|
//#region src/sdk/client.websoket.ts
|
|
7
7
|
const normalizeGatewayMessage = (message) => {
|
|
8
8
|
if (!message?.id || !message?.d || typeof message.d !== "object" || Array.isArray(message.d)) return message;
|
|
9
|
+
if (message.t === "INTERACTION_CREATE") message.d.event_id = message.id;
|
|
9
10
|
if (message.d.id === void 0 || message.d.id === null || message.d.id === "") message.d.id = message.id;
|
|
10
11
|
return message;
|
|
11
12
|
};
|
|
@@ -37,7 +38,7 @@ var QQBotClients = class extends QQBotAPI {
|
|
|
37
38
|
* @param option
|
|
38
39
|
*/
|
|
39
40
|
constructor(option) {
|
|
40
|
-
super(option);
|
|
41
|
+
super({ ...option });
|
|
41
42
|
this.#sessionStore = option.sessionStore || new FileSessionStore();
|
|
42
43
|
}
|
|
43
44
|
async #loadSession() {
|
package/lib/sdk/instance.d.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import { AxiosInstance, AxiosRequestConfig } from "axios";
|
|
2
2
|
//#region src/sdk/instance.d.ts
|
|
3
|
-
/**
|
|
4
|
-
* 基础请求
|
|
5
|
-
* @param service
|
|
6
|
-
* @param options
|
|
7
|
-
* @returns
|
|
8
|
-
*/
|
|
3
|
+
/** Preserve native platform failure payloads for existing SDK and Action callers. */
|
|
9
4
|
declare const createAxiosInstance: (service: AxiosInstance, options: AxiosRequestConfig) => Promise<any>;
|
|
10
5
|
//#endregion
|
|
11
6
|
export { createAxiosInstance };
|
package/lib/sdk/instance.js
CHANGED
|
@@ -1,75 +1,29 @@
|
|
|
1
1
|
import { logger } from "alemonjs";
|
|
2
2
|
|
|
3
3
|
//#region src/sdk/instance.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const filtered = {};
|
|
7
|
-
const sensitiveKeys = [
|
|
8
|
-
/^authorization$/i,
|
|
9
|
-
/^cookie$/i,
|
|
10
|
-
/^set-cookie$/i,
|
|
11
|
-
/token/i,
|
|
12
|
-
/key/i,
|
|
13
|
-
/jwt/i,
|
|
14
|
-
/^session[-_]id$/i,
|
|
15
|
-
/^uid$/i,
|
|
16
|
-
/^user[-_]id$/i
|
|
17
|
-
];
|
|
18
|
-
for (const key in headers) {
|
|
19
|
-
if (/^_/.test(key)) continue;
|
|
20
|
-
if (typeof key === "symbol") continue;
|
|
21
|
-
if (typeof headers[key] === "function") continue;
|
|
22
|
-
if (sensitiveKeys.some((re) => re.test(key))) filtered[key] = "******";
|
|
23
|
-
else filtered[key] = headers[key];
|
|
24
|
-
}
|
|
25
|
-
return filtered;
|
|
26
|
-
};
|
|
27
|
-
const filterConfig = (config = {}) => {
|
|
28
|
-
if (!config) return config;
|
|
29
|
-
const filtered = {};
|
|
30
|
-
for (const key in config) {
|
|
31
|
-
if (/^_/.test(key)) continue;
|
|
32
|
-
if (typeof key === "symbol") continue;
|
|
33
|
-
if (typeof config[key] === "function") continue;
|
|
34
|
-
filtered[key] = config[key];
|
|
35
|
-
}
|
|
36
|
-
return filtered;
|
|
37
|
-
};
|
|
38
|
-
const filterRequest = (request = {}) => {
|
|
39
|
-
if (!request) return request;
|
|
40
|
-
const filtered = {};
|
|
41
|
-
for (const key in request) {
|
|
42
|
-
if (/^_/.test(key)) continue;
|
|
43
|
-
if (typeof key === "symbol") continue;
|
|
44
|
-
if (typeof request[key] === "function") continue;
|
|
45
|
-
filtered[key] = request[key];
|
|
46
|
-
}
|
|
47
|
-
return filtered;
|
|
48
|
-
};
|
|
4
|
+
/** Log an allowlist of diagnostics. Axios config/request objects may contain
|
|
5
|
+
* credentials, signed URLs, message bodies, buffers and circular references. */
|
|
49
6
|
const loggerError = (err) => {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
7
|
+
const config = err?.config;
|
|
8
|
+
let path;
|
|
9
|
+
try {
|
|
10
|
+
path = new URL(config?.url ?? "", config?.baseURL || "http://localhost").pathname;
|
|
11
|
+
} catch {
|
|
12
|
+
path = void 0;
|
|
13
|
+
}
|
|
14
|
+
const headers = err?.response?.headers;
|
|
15
|
+
const data = err?.response?.data;
|
|
16
|
+
const scalarCode = (value) => typeof value === "number" || typeof value === "string" && /^[\w-]{1,64}$/.test(value) ? value : void 0;
|
|
17
|
+
logger.error("[qq-bot] HTTP request failed", {
|
|
18
|
+
method: typeof config?.method === "string" ? config.method.toUpperCase() : void 0,
|
|
19
|
+
path,
|
|
20
|
+
status: err?.response?.status,
|
|
21
|
+
code: scalarCode(data?.code ?? data?.err_code),
|
|
22
|
+
transportCode: scalarCode(err?.code),
|
|
23
|
+
traceId: headers?.["x-tps-trace-id"] ?? headers?.["x-trace-id"]
|
|
65
24
|
});
|
|
66
25
|
};
|
|
67
|
-
/**
|
|
68
|
-
* 基础请求
|
|
69
|
-
* @param service
|
|
70
|
-
* @param options
|
|
71
|
-
* @returns
|
|
72
|
-
*/
|
|
26
|
+
/** Preserve native platform failure payloads for existing SDK and Action callers. */
|
|
73
27
|
const createAxiosInstance = async (service, options) => {
|
|
74
28
|
try {
|
|
75
29
|
return (await service(options))?.data ?? {};
|
package/lib/sdk/intents.d.ts
CHANGED
package/lib/sdk/intents.js
CHANGED
package/lib/sdk/message.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { QQBotGroupEventMap } from "./message.group.js";
|
|
2
|
-
import { QQBotGuildEventMap } from "./message.guild.js";
|
|
3
2
|
import { QQBotPublicEventMap } from "./message.public.js";
|
|
3
|
+
import { QQBotGuildEventMap } from "./message.guild.js";
|
|
4
4
|
//#region src/sdk/message.d.ts
|
|
5
5
|
type QQBotEventMap = QQBotGroupEventMap & QQBotGuildEventMap & QQBotPublicEventMap;
|
|
6
6
|
//#endregion
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { SUBSCRIBE_MESSAGE_STATUS_TYPE } from "../message/group/SUBSCRIBE_MESSAGE_STATUS.js";
|
|
2
|
+
import { GROUP_MEMBER_ADD } from "../message/group/GROUP_MEMBER_ADD.js";
|
|
3
|
+
import { GROUP_MEMBER_REMOVE } from "../message/group/GROUP_MEMBER_REMOVE.js";
|
|
1
4
|
import { GROUP_AT_MESSAGE_CREATE_TYPE } from "../message/group/GROUP_AT_MESSAGE_CREATE.js";
|
|
2
5
|
import { GROUP_MESSAGE_CREATE_TYPE } from "../message/group/GROUP_MESSAGE_CREATE.js";
|
|
3
6
|
import { C2C_MESSAGE_CREATE_TYPE } from "../message/group/C2C_MESSAGE_CREATE.js";
|
|
@@ -13,10 +16,9 @@ import { MESSAGE_AUDIT_PASS_TYPE } from "../message/group/MESSAGE_AUDIT_PASS.js"
|
|
|
13
16
|
import { MESSAGE_AUDIT_REJECT_TYPE } from "../message/group/MESSAGE_AUDIT_REJECT.js";
|
|
14
17
|
import { GROUP_JOIN_REQUEST_TYPE } from "../message/group/GROUP_JOIN_REQUEST.js";
|
|
15
18
|
import { ERROR_TYPE } from "../message/ERROR.js";
|
|
16
|
-
import { GROUP_MEMBER_REMOVE } from "../message/group/GROUP_MEMBER_REMOVE.js";
|
|
17
|
-
import { GROUP_MEMBER_ADD } from "../message/group/GROUP_MEMBER_ADD.js";
|
|
18
19
|
//#region src/sdk/message.group.d.ts
|
|
19
20
|
type QQBotGroupEventMap = {
|
|
21
|
+
SUBSCRIBE_MESSAGE_STATUS: SUBSCRIBE_MESSAGE_STATUS_TYPE;
|
|
20
22
|
C2C_MESSAGE_CREATE: C2C_MESSAGE_CREATE_TYPE;
|
|
21
23
|
C2C_MSG_REJECT: C2C_MSG_REJECT_TYPE;
|
|
22
24
|
C2C_MSG_RECEIVE: C2C_MSG_RECEIVE_TYPE;
|
|
@@ -15,6 +15,9 @@ import { GUILD_UPDATE_TYPE } from "../message/GUILD_UPDATE.js";
|
|
|
15
15
|
import { GUILD_MEMBER_ADD_TYPE } from "../message/GUILD_MEMBER_ADD.js";
|
|
16
16
|
import { GUILD_MEMBER_REMOVE_TYPE } from "../message/GUILD_MEMBER_REMOVE.js";
|
|
17
17
|
import { GUILD_MEMBER_UPDATE_TYPE } from "../message/GUILD_MEMBER_UPDATE.js";
|
|
18
|
+
import { GUILD_AUDIT_TYPE } from "../message/GUILD_AUDIT.js";
|
|
19
|
+
import { FORUM_EVENT_TYPE } from "../message/FORUM_EVENT.js";
|
|
20
|
+
import { AUDIO_EVENT_TYPE, AUDIO_OR_LIVE_CHANNEL_MEMBER_EVENT_TYPE } from "../message/AUDIO_EVENT.js";
|
|
18
21
|
import { READY_TYPE } from "../message/READY.js";
|
|
19
22
|
//#region src/sdk/message.guild.d.ts
|
|
20
23
|
type QQBotGuildEventMap = {
|
|
@@ -35,6 +38,22 @@ type QQBotGuildEventMap = {
|
|
|
35
38
|
MESSAGE_REACTION_REMOVE: MESSAGE_REACTION_REMOVE_TYPE;
|
|
36
39
|
AT_MESSAGE_CREATE: AT_MESSAGE_CREATE_TYPE;
|
|
37
40
|
PUBLIC_MESSAGE_DELETE: PUBLIC_MESSAGE_DELETE_TYPE;
|
|
41
|
+
MESSAGE_AUDIT_PASS: GUILD_AUDIT_TYPE;
|
|
42
|
+
MESSAGE_AUDIT_REJECT: GUILD_AUDIT_TYPE;
|
|
43
|
+
FORUM_THREAD_CREATE: FORUM_EVENT_TYPE;
|
|
44
|
+
FORUM_THREAD_UPDATE: FORUM_EVENT_TYPE;
|
|
45
|
+
FORUM_THREAD_DELETE: FORUM_EVENT_TYPE;
|
|
46
|
+
FORUM_POST_CREATE: FORUM_EVENT_TYPE;
|
|
47
|
+
FORUM_POST_DELETE: FORUM_EVENT_TYPE;
|
|
48
|
+
FORUM_REPLY_CREATE: FORUM_EVENT_TYPE;
|
|
49
|
+
FORUM_REPLY_DELETE: FORUM_EVENT_TYPE;
|
|
50
|
+
FORUM_PUBLISH_AUDIT_RESULT: FORUM_EVENT_TYPE;
|
|
51
|
+
AUDIO_START: AUDIO_EVENT_TYPE;
|
|
52
|
+
AUDIO_FINISH: AUDIO_EVENT_TYPE;
|
|
53
|
+
AUDIO_ON_MIC: AUDIO_EVENT_TYPE;
|
|
54
|
+
AUDIO_OFF_MIC: AUDIO_EVENT_TYPE;
|
|
55
|
+
AUDIO_OR_LIVE_CHANNEL_MEMBER_ENTER: AUDIO_OR_LIVE_CHANNEL_MEMBER_EVENT_TYPE;
|
|
56
|
+
AUDIO_OR_LIVE_CHANNEL_MEMBER_EXIT: AUDIO_OR_LIVE_CHANNEL_MEMBER_EVENT_TYPE;
|
|
38
57
|
READY: READY_TYPE;
|
|
39
58
|
};
|
|
40
59
|
//#endregion
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
//#region src/sdk/non-channel-types.d.ts
|
|
2
|
+
/** 群聊、单聊服务端接口模型,依据 docs/official/non-channel 快照。 */
|
|
3
|
+
type QQBotPage = {
|
|
4
|
+
cursor?: string;
|
|
5
|
+
limit?: number;
|
|
6
|
+
};
|
|
7
|
+
type QQBotMenuItem = {
|
|
8
|
+
name?: string;
|
|
9
|
+
type?: 'switch' | 'send_message' | 'link' | 'menu';
|
|
10
|
+
send_message?: string;
|
|
11
|
+
link?: string;
|
|
12
|
+
switch?: {
|
|
13
|
+
switch_id?: string;
|
|
14
|
+
default?: boolean;
|
|
15
|
+
};
|
|
16
|
+
sub_menu_items?: {
|
|
17
|
+
name?: string;
|
|
18
|
+
type?: 'send_message' | 'link';
|
|
19
|
+
send_message?: string;
|
|
20
|
+
link?: string;
|
|
21
|
+
}[];
|
|
22
|
+
};
|
|
23
|
+
type QQBotMenu = {
|
|
24
|
+
items?: QQBotMenuItem[];
|
|
25
|
+
};
|
|
26
|
+
type QQBotPanel = {
|
|
27
|
+
items?: {
|
|
28
|
+
name?: string;
|
|
29
|
+
desc?: string;
|
|
30
|
+
type?: 'command' | 'link';
|
|
31
|
+
only_admin?: boolean;
|
|
32
|
+
link?: string;
|
|
33
|
+
}[];
|
|
34
|
+
remark?: string;
|
|
35
|
+
version?: number;
|
|
36
|
+
};
|
|
37
|
+
/** 本次仅开放非频道场景。 */
|
|
38
|
+
type QQBotPanelScope = 'c2c' | 'group';
|
|
39
|
+
type QQBotPanelCreate = {
|
|
40
|
+
scope: QQBotPanelScope;
|
|
41
|
+
target_type?: 'all' | 'specific';
|
|
42
|
+
user_openids?: string[];
|
|
43
|
+
group_openids?: string[];
|
|
44
|
+
panel: QQBotPanel;
|
|
45
|
+
};
|
|
46
|
+
type QQBotPanelRecord = QQBotPanelCreate & {
|
|
47
|
+
panel_id: string;
|
|
48
|
+
created_at?: string;
|
|
49
|
+
updated_at?: string;
|
|
50
|
+
version?: number;
|
|
51
|
+
};
|
|
52
|
+
type QQBotGroupMember = {
|
|
53
|
+
member_openid: string;
|
|
54
|
+
username: string;
|
|
55
|
+
member_role: 'member' | 'owner' | 'admin';
|
|
56
|
+
bot: boolean;
|
|
57
|
+
joined_at: string;
|
|
58
|
+
union_openid?: string;
|
|
59
|
+
};
|
|
60
|
+
type QQBotBlacklistUser = {
|
|
61
|
+
member_openid: string;
|
|
62
|
+
username: string;
|
|
63
|
+
banned_at: string;
|
|
64
|
+
bot: boolean;
|
|
65
|
+
union_openid?: string;
|
|
66
|
+
};
|
|
67
|
+
type QQBotMessageResult = {
|
|
68
|
+
id: string;
|
|
69
|
+
timestamp: string;
|
|
70
|
+
ext_info?: {
|
|
71
|
+
ref_idx?: string;
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
type QQBotMessageUser = {
|
|
75
|
+
id: string;
|
|
76
|
+
username?: string;
|
|
77
|
+
bot?: boolean;
|
|
78
|
+
union_openid?: string;
|
|
79
|
+
union_user_account?: string;
|
|
80
|
+
user_openid?: string;
|
|
81
|
+
member_openid?: string;
|
|
82
|
+
member_role?: 'member' | 'admin' | 'owner';
|
|
83
|
+
};
|
|
84
|
+
type QQBotAttachment = {
|
|
85
|
+
id?: string;
|
|
86
|
+
url?: string;
|
|
87
|
+
filename?: string;
|
|
88
|
+
width?: number;
|
|
89
|
+
height?: number;
|
|
90
|
+
size?: number;
|
|
91
|
+
content_type?: string;
|
|
92
|
+
voice_wav_url?: string;
|
|
93
|
+
asr_refer_text?: string;
|
|
94
|
+
};
|
|
95
|
+
type QQBotArkData = {
|
|
96
|
+
prompt?: string;
|
|
97
|
+
ark_type?: string;
|
|
98
|
+
ark_name?: string;
|
|
99
|
+
fields?: Record<string, unknown>;
|
|
100
|
+
};
|
|
101
|
+
type QQBotMessageElement = {
|
|
102
|
+
msg_idx?: string;
|
|
103
|
+
author?: QQBotMessageUser;
|
|
104
|
+
message_type?: number;
|
|
105
|
+
content?: string;
|
|
106
|
+
attachments?: QQBotAttachment[];
|
|
107
|
+
ark_data?: QQBotArkData;
|
|
108
|
+
msg_elements?: QQBotMessageElement[];
|
|
109
|
+
};
|
|
110
|
+
type QQBotMessageContent = {
|
|
111
|
+
attachments?: QQBotAttachment[];
|
|
112
|
+
ark_data?: QQBotArkData;
|
|
113
|
+
msg_elements?: QQBotMessageElement[];
|
|
114
|
+
message_scene?: {
|
|
115
|
+
ext: string[];
|
|
116
|
+
source?: string;
|
|
117
|
+
};
|
|
118
|
+
message_type?: number;
|
|
119
|
+
};
|
|
120
|
+
type QQBotInteractionResolved = {
|
|
121
|
+
button_data?: string;
|
|
122
|
+
button_id?: string | number;
|
|
123
|
+
user_id?: string;
|
|
124
|
+
feature_id?: string;
|
|
125
|
+
message_id?: string;
|
|
126
|
+
feedback_opt?: 'LIKE' | 'UNLIKE';
|
|
127
|
+
checked?: number;
|
|
128
|
+
action?: string;
|
|
129
|
+
message_scene?: {
|
|
130
|
+
ext?: string[];
|
|
131
|
+
};
|
|
132
|
+
authorize_data?: {
|
|
133
|
+
opt_scene?: string;
|
|
134
|
+
scope?: string;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
//#endregion
|
|
138
|
+
export { QQBotArkData, QQBotAttachment, QQBotBlacklistUser, QQBotGroupMember, QQBotInteractionResolved, QQBotMenu, QQBotMenuItem, QQBotMessageContent, QQBotMessageElement, QQBotMessageResult, QQBotMessageUser, QQBotPage, QQBotPanel, QQBotPanelCreate, QQBotPanelRecord, QQBotPanelScope };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/lib/sdk/registry.js
CHANGED
|
@@ -80,7 +80,7 @@ var QQBotRegistry = class {
|
|
|
80
80
|
}
|
|
81
81
|
#requestedBotId(data) {
|
|
82
82
|
const payload = data?.payload || {};
|
|
83
|
-
return payload.target?.BotId
|
|
83
|
+
return payload.params?.target?.BotId ?? payload.target?.BotId ?? payload.BotId ?? payload.event?.BotId ?? payload.event?.Platform?.BotId;
|
|
84
84
|
}
|
|
85
85
|
#select(data) {
|
|
86
86
|
const requested = this.#requestedBotId(data);
|
|
@@ -94,7 +94,7 @@ var QQBotRegistry = class {
|
|
|
94
94
|
}
|
|
95
95
|
async #onAction(data, consume) {
|
|
96
96
|
if (data?.action === "connection.status") {
|
|
97
|
-
const botId = data
|
|
97
|
+
const botId = this.#requestedBotId(data);
|
|
98
98
|
const status = this.getConnectionStatus(botId);
|
|
99
99
|
if (botId && !status.bots.length) consume([createResult(ResultCode.FailParams, `BotId ${botId} is not configured`, null)]);
|
|
100
100
|
else consume([createResult(ResultCode.Ok, data.action, status)]);
|
package/lib/sdk/typing.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { SessionStore } from "./session.js";
|
|
|
4
4
|
type MessageType = 0 | 1 | 2 | 3 | 4 | 6 | 7;
|
|
5
5
|
type FileType = 1 | 2 | 3 | 4;
|
|
6
6
|
interface ButtonType {
|
|
7
|
+
group_id?: string;
|
|
7
8
|
id: string;
|
|
8
9
|
render_data: {
|
|
9
10
|
label: string;
|
|
@@ -14,6 +15,15 @@ interface ButtonType {
|
|
|
14
15
|
type: number;
|
|
15
16
|
permission: {
|
|
16
17
|
type: number;
|
|
18
|
+
specify_user_ids?: string[];
|
|
19
|
+
specify_role_ids?: string[];
|
|
20
|
+
};
|
|
21
|
+
anchor?: number;
|
|
22
|
+
click_limit?: number;
|
|
23
|
+
modal?: {
|
|
24
|
+
content?: string;
|
|
25
|
+
confirm_text?: string;
|
|
26
|
+
cancel_text?: string;
|
|
17
27
|
};
|
|
18
28
|
reply?: boolean;
|
|
19
29
|
enter?: boolean;
|
|
@@ -35,6 +45,8 @@ interface KeyboardType {
|
|
|
35
45
|
};
|
|
36
46
|
}
|
|
37
47
|
interface MarkdownType {
|
|
48
|
+
template_id?: number;
|
|
49
|
+
force_verify_image_resource?: boolean;
|
|
38
50
|
/** markdown 模版id,申请模版后获得 */
|
|
39
51
|
custom_template_id?: string;
|
|
40
52
|
/** 原生 markdown 文本内容(内邀使用) */
|
|
@@ -60,7 +72,7 @@ interface ApiRequestData {
|
|
|
60
72
|
msg_id?: string;
|
|
61
73
|
msg_seq?: number;
|
|
62
74
|
/**
|
|
63
|
-
*
|
|
75
|
+
* 互动召回消息,与 msg_id/event_id 互斥
|
|
64
76
|
*/
|
|
65
77
|
is_wakeup?: boolean;
|
|
66
78
|
/**
|
|
@@ -14,11 +14,16 @@ var WebhookAPI = class {
|
|
|
14
14
|
* @returns
|
|
15
15
|
*/
|
|
16
16
|
validSign(ts, body, sign) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
if (typeof ts !== "string" || !ts || typeof body !== "string" && !Buffer.isBuffer(body)) return false;
|
|
18
|
+
if (!Buffer.isBuffer(sign) && (typeof sign !== "string" || !/^[a-f\d]{128}$/i.test(sign))) return false;
|
|
19
|
+
try {
|
|
20
|
+
const { publicKey } = this.getKey();
|
|
21
|
+
const sig = Buffer.isBuffer(sign) ? sign : Buffer.from(sign, "hex");
|
|
22
|
+
const msg = Buffer.concat([Buffer.from(ts), Buffer.isBuffer(body) ? body : Buffer.from(body)]);
|
|
23
|
+
return ed25519.verify(sig, msg, publicKey);
|
|
24
|
+
} catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
22
27
|
}
|
|
23
28
|
/**
|
|
24
29
|
* 生成签名
|
package/lib/sends.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { QQBotAPI } from "./sdk/api.js";
|
|
2
|
-
import { ClientAPIMessageResult, DataEnums } from "alemonjs";
|
|
2
|
+
import { ClientAPIMessageResult, DataEnums, MessageDelivery } from "alemonjs";
|
|
3
3
|
//#region src/sends.d.ts
|
|
4
4
|
type Client = typeof QQBotAPI.prototype;
|
|
5
5
|
/**
|
|
@@ -9,7 +9,7 @@ declare const GROUP_AT_MESSAGE_CREATE: (client: Client, event: {
|
|
|
9
9
|
ChannelId: string;
|
|
10
10
|
MessageId?: string;
|
|
11
11
|
_tag?: string;
|
|
12
|
-
}, val: DataEnums[], options?: {
|
|
12
|
+
}, val: DataEnums[], options?: MessageDelivery & {
|
|
13
13
|
forceVerifyImageResource?: boolean;
|
|
14
14
|
}) => Promise<ClientAPIMessageResult[]>;
|
|
15
15
|
/**
|
|
@@ -19,7 +19,7 @@ declare const C2C_MESSAGE_CREATE: (client: Client, event: {
|
|
|
19
19
|
UserId: string;
|
|
20
20
|
MessageId?: string;
|
|
21
21
|
_tag?: string;
|
|
22
|
-
}, val: DataEnums[], options?: {
|
|
22
|
+
}, val: DataEnums[], options?: MessageDelivery & {
|
|
23
23
|
forceVerifyImageResource?: boolean;
|
|
24
24
|
}) => Promise<ClientAPIMessageResult[]>;
|
|
25
25
|
/**
|