@karinjs/adapter-qqbot 2.0.0 → 2.2.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/README.md +112 -255
- package/dist/apps/cleanup.d.ts +5 -0
- package/dist/apps/cleanup.js +22 -0
- package/dist/apps/login.d.ts +1 -3
- package/dist/apps/login.js +65 -16
- package/dist/common-by1GpV0b.js +49 -0
- package/dist/config-B_Gc9JKZ.js +253 -0
- package/dist/index.d.ts +511 -25
- package/dist/index.js +2327 -242
- package/dist/message-Dt4QkDYn.js +1739 -0
- package/dist/{onboard-BX8g8Wik.js → onboard-BXQ1cG8h.js} +10 -7
- package/dist/utils-DIq0lGMt.js +4 -0
- package/dist/web.config.d.ts +21 -19
- package/dist/web.config.js +232 -88
- package/package.json +6 -11
- package/dist/config-H7LrvlNU.js +0 -197
- package/dist/utils-DO4gEkVN.js +0 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as getDefaultConfig, m as log, n as config, o as writeConfig } from "./config-B_Gc9JKZ.js";
|
|
2
|
+
import { a as sleep } from "./common-by1GpV0b.js";
|
|
2
3
|
import qrcode from "qrcode";
|
|
3
4
|
import axios from "node-karin/axios";
|
|
4
5
|
import crypto from "node:crypto";
|
|
@@ -128,7 +129,7 @@ const renderQr = async (url) => {
|
|
|
128
129
|
* 3. 解密返回 secret
|
|
129
130
|
*/
|
|
130
131
|
const qrRegister = async (opts = {}) => {
|
|
131
|
-
const { timeoutSeconds = DEFAULT_TIMEOUT_S, onQr } = opts;
|
|
132
|
+
const { timeoutSeconds = DEFAULT_TIMEOUT_S, printTerminal = false, onQr } = opts;
|
|
132
133
|
const deadline = Date.now() + timeoutSeconds * 1e3;
|
|
133
134
|
for (let refresh = 0; refresh <= MAX_REFRESHES; refresh++) {
|
|
134
135
|
let task;
|
|
@@ -141,11 +142,13 @@ const qrRegister = async (opts = {}) => {
|
|
|
141
142
|
const url = buildConnectUrl(task.taskId);
|
|
142
143
|
const { ascii, base64 } = await renderQr(url);
|
|
143
144
|
const qrDeadline = Date.now() + QR_TTL_MS;
|
|
144
|
-
if (
|
|
145
|
-
|
|
146
|
-
|
|
145
|
+
if (printTerminal) {
|
|
146
|
+
if (ascii) {
|
|
147
|
+
console.log();
|
|
148
|
+
console.log(ascii);
|
|
149
|
+
}
|
|
150
|
+
console.log(` 请使用 QQ 扫码(60s 内有效),或在手机 QQ 打开:\n ${url}\n`);
|
|
147
151
|
}
|
|
148
|
-
console.log(` 请使用 QQ 扫码(60s 内有效),或在手机 QQ 打开:\n ${url}\n`);
|
|
149
152
|
if (onQr) try {
|
|
150
153
|
await onQr({
|
|
151
154
|
url,
|
|
@@ -196,7 +199,7 @@ const qrRegister = async (opts = {}) => {
|
|
|
196
199
|
}
|
|
197
200
|
if (expired) {
|
|
198
201
|
if (refresh >= MAX_REFRESHES) {
|
|
199
|
-
log("error", `[扫码登录] 二维码已过期
|
|
202
|
+
log("error", `[扫码登录] 二维码已过期 4 次,终止流程`);
|
|
200
203
|
return null;
|
|
201
204
|
}
|
|
202
205
|
log("info", `[扫码登录] 二维码 60s 内未完成扫码,正在刷新 (${refresh + 1}/${MAX_REFRESHES})`);
|
package/dist/web.config.d.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import * as _$node_karin0 from "node-karin";
|
|
2
|
-
|
|
3
1
|
//#region src/web.config.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
2
|
+
type WebQQBotInput = {
|
|
3
|
+
name: unknown;
|
|
4
|
+
appId: unknown;
|
|
5
|
+
secret: unknown;
|
|
6
|
+
'proxy:api': unknown;
|
|
7
|
+
'proxy:ws': unknown;
|
|
8
|
+
sandbox: unknown;
|
|
9
|
+
qqEnable: unknown;
|
|
10
|
+
guildEnable: unknown;
|
|
11
|
+
guildMode: unknown;
|
|
12
|
+
regex: unknown;
|
|
13
|
+
'keyboard:enable': unknown;
|
|
14
|
+
'markdown:enable': unknown;
|
|
15
|
+
'messageCache:enable': unknown;
|
|
16
|
+
'messageCache:self': unknown;
|
|
17
|
+
'event:type': unknown;
|
|
18
|
+
};
|
|
19
|
+
type WebConfigInput = {
|
|
20
|
+
qqbot: WebQQBotInput[];
|
|
21
|
+
};
|
|
22
|
+
declare const _default: import("node-karin").DefineComponentConfig<WebConfigInput>;
|
|
21
23
|
//#endregion
|
|
22
24
|
export { _default as default };
|
package/dist/web.config.js
CHANGED
|
@@ -1,8 +1,92 @@
|
|
|
1
|
-
import { a as pkg, n as config, o as writeConfig } from "./config-
|
|
2
|
-
import "./utils-
|
|
1
|
+
import { a as readConfigFile, f as pkg, i as getDefaultConfig, n as config, o as writeConfig, s as buildFallbackWsUrlFromApi, u as normalizeProxyConfig } from "./config-B_Gc9JKZ.js";
|
|
2
|
+
import "./utils-DIq0lGMt.js";
|
|
3
3
|
import { components, defineConfig } from "node-karin";
|
|
4
4
|
|
|
5
5
|
//#region src/web.config.ts
|
|
6
|
+
const defaultProxy = () => getDefaultConfig()[0].proxy;
|
|
7
|
+
const unwrapValue = (value) => {
|
|
8
|
+
if (value && typeof value === "object" && "value" in value) return value.value;
|
|
9
|
+
return value;
|
|
10
|
+
};
|
|
11
|
+
const toBool = (value, fallback) => {
|
|
12
|
+
const raw = unwrapValue(value);
|
|
13
|
+
if (typeof raw === "boolean") return raw;
|
|
14
|
+
if (typeof raw === "number") return raw !== 0;
|
|
15
|
+
if (typeof raw === "string") {
|
|
16
|
+
const normalized = raw.trim().toLowerCase();
|
|
17
|
+
if ([
|
|
18
|
+
"false",
|
|
19
|
+
"0",
|
|
20
|
+
"off",
|
|
21
|
+
"no",
|
|
22
|
+
""
|
|
23
|
+
].includes(normalized)) return false;
|
|
24
|
+
if ([
|
|
25
|
+
"true",
|
|
26
|
+
"1",
|
|
27
|
+
"on",
|
|
28
|
+
"yes"
|
|
29
|
+
].includes(normalized)) return true;
|
|
30
|
+
}
|
|
31
|
+
if (raw === null || raw === void 0) return fallback;
|
|
32
|
+
return fallback;
|
|
33
|
+
};
|
|
34
|
+
const toStringValue = (value, fallback = "") => {
|
|
35
|
+
const raw = unwrapValue(value);
|
|
36
|
+
if (typeof raw === "string") return raw;
|
|
37
|
+
if (raw === null || raw === void 0) return fallback;
|
|
38
|
+
return String(raw);
|
|
39
|
+
};
|
|
40
|
+
const toStringList = (value) => {
|
|
41
|
+
const raw = unwrapValue(value);
|
|
42
|
+
if (!Array.isArray(raw)) return [];
|
|
43
|
+
return raw.map((item) => toStringValue(item)).filter(Boolean);
|
|
44
|
+
};
|
|
45
|
+
const proxyKeys = (sandbox) => sandbox ? {
|
|
46
|
+
api: "sandboxApi",
|
|
47
|
+
ws: "sandboxWs"
|
|
48
|
+
} : {
|
|
49
|
+
api: "prodApi",
|
|
50
|
+
ws: "prodWs"
|
|
51
|
+
};
|
|
52
|
+
const getBotProxyInput = (item) => {
|
|
53
|
+
const keys = proxyKeys(!!item.sandbox);
|
|
54
|
+
const proxy = item.proxy || defaultProxy();
|
|
55
|
+
return {
|
|
56
|
+
"proxy:api": proxy[keys.api] || defaultProxy()[keys.api],
|
|
57
|
+
"proxy:ws": proxy[keys.ws] || defaultProxy()[keys.ws]
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
const proxyFromInput = (item, previous) => {
|
|
61
|
+
const def = defaultProxy();
|
|
62
|
+
const sandbox = toBool(item.sandbox, previous?.sandbox ?? false);
|
|
63
|
+
const previousSandbox = previous?.sandbox ?? sandbox;
|
|
64
|
+
const keys = proxyKeys(sandbox);
|
|
65
|
+
const previousVisibleKeys = proxyKeys(previousSandbox);
|
|
66
|
+
const previousProxy = previous?.proxy;
|
|
67
|
+
const base = {
|
|
68
|
+
...def,
|
|
69
|
+
...previousProxy
|
|
70
|
+
};
|
|
71
|
+
const envChanged = !!previous && previousSandbox !== sandbox;
|
|
72
|
+
const rawApi = toStringValue(item["proxy:api"]).trim();
|
|
73
|
+
const rawWs = toStringValue(item["proxy:ws"]).trim();
|
|
74
|
+
const previousVisibleApi = previousProxy?.[previousVisibleKeys.api] || def[previousVisibleKeys.api];
|
|
75
|
+
const previousVisibleWs = previousProxy?.[previousVisibleKeys.ws] || def[previousVisibleKeys.ws];
|
|
76
|
+
const api = envChanged && rawApi === previousVisibleApi ? base[keys.api] || def[keys.api] : rawApi || base[keys.api] || def[keys.api];
|
|
77
|
+
const previousApi = previousProxy?.[keys.api] || def[keys.api];
|
|
78
|
+
const previousWs = previousProxy?.[keys.ws] || def[keys.ws];
|
|
79
|
+
const wsInput = envChanged && rawWs === previousVisibleWs ? base[keys.ws] || def[keys.ws] : rawWs;
|
|
80
|
+
let ws = wsInput || previousWs || def[keys.ws];
|
|
81
|
+
const previousAutoWs = buildFallbackWsUrlFromApi(previousApi);
|
|
82
|
+
if (!wsInput || wsInput === previousWs && previousWs === previousAutoWs && api !== previousApi) ws = buildFallbackWsUrlFromApi(api);
|
|
83
|
+
return normalizeProxyConfig({
|
|
84
|
+
...base,
|
|
85
|
+
[keys.api]: api,
|
|
86
|
+
tokenApi: base.tokenApi || def.tokenApi,
|
|
87
|
+
[keys.ws]: ws
|
|
88
|
+
});
|
|
89
|
+
};
|
|
6
90
|
var web_config_default = defineConfig({
|
|
7
91
|
info: {
|
|
8
92
|
id: pkg().name,
|
|
@@ -23,108 +107,140 @@ var web_config_default = defineConfig({
|
|
|
23
107
|
name: item.name,
|
|
24
108
|
appId: item.appId,
|
|
25
109
|
secret: item.secret,
|
|
26
|
-
|
|
27
|
-
sandboxApi: item.sandboxApi,
|
|
28
|
-
tokenApi: item.tokenApi,
|
|
110
|
+
"event:type": String(item.event?.type ?? 2),
|
|
29
111
|
sandbox: item.sandbox,
|
|
30
112
|
qqEnable: item.qqEnable,
|
|
31
113
|
guildEnable: item.guildEnable,
|
|
32
114
|
guildMode: item.guildMode === 1,
|
|
33
115
|
regex: item.regex.map((r) => `${r.reg} ${r.rep}`),
|
|
34
116
|
"keyboard:enable": item.keyboard?.enable !== false,
|
|
35
|
-
"
|
|
117
|
+
"markdown:enable": item.markdown?.enable !== false,
|
|
118
|
+
"messageCache:enable": item.messageCache?.enable === true,
|
|
119
|
+
"messageCache:self": item.messageCache?.self === true,
|
|
120
|
+
...getBotProxyInput(item)
|
|
36
121
|
});
|
|
37
122
|
});
|
|
38
|
-
return [components.
|
|
39
|
-
|
|
40
|
-
|
|
123
|
+
return [components.divider.horizontal("bot-section", {
|
|
124
|
+
description: "机器人账号",
|
|
125
|
+
descPosition: 5
|
|
126
|
+
}), components.accordionPro.create("qqbot", data, {
|
|
127
|
+
label: "QQ 官方机器人列表",
|
|
128
|
+
description: "每一项对应一个 QQ 官方机器人账号。新增机器人时先填 AppID 和 Secret,再按需调整接收方式、场景能力和发送能力。",
|
|
41
129
|
children: {
|
|
42
130
|
key: "qqbotConfig",
|
|
43
131
|
children: [
|
|
132
|
+
components.radio.group("event:type", {
|
|
133
|
+
label: "事件接收方式",
|
|
134
|
+
description: "QQ 官方机器人只有 Webhook 推送和 WebSocket 主动连接两种接收方式。不确定时选择 WebSocket;如果 QQ 后台已启用 Webhook,可在下方高级设置填写第三方 Webhook 转 WebSocket 服务地址。",
|
|
135
|
+
defaultValue: "2",
|
|
136
|
+
radio: [
|
|
137
|
+
components.radio.create("0", {
|
|
138
|
+
label: "关闭接收",
|
|
139
|
+
value: "0",
|
|
140
|
+
description: "停用这个机器人,不连接 WebSocket,也不接收 Webhook 事件。"
|
|
141
|
+
}),
|
|
142
|
+
components.radio.create("1", {
|
|
143
|
+
label: "Webhook 推送",
|
|
144
|
+
value: "1",
|
|
145
|
+
description: "由 QQ 官方把事件推送到 Karin 的 /qqbot/webhook 路由。通常需要公网地址,并在 QQ 后台配置回调地址。"
|
|
146
|
+
}),
|
|
147
|
+
components.radio.create("2", {
|
|
148
|
+
label: "WebSocket 主动连接",
|
|
149
|
+
value: "2",
|
|
150
|
+
description: "适配器主动连接 WebSocket 地址接收事件。默认连接 QQ 官方网关;如果 QQ 后台已开 Webhook,可改为第三方 Webhook 转 WebSocket 服务地址。"
|
|
151
|
+
})
|
|
152
|
+
]
|
|
153
|
+
}),
|
|
154
|
+
components.divider.horizontal("bot-basic-section", {
|
|
155
|
+
description: "基础信息",
|
|
156
|
+
descPosition: 5
|
|
157
|
+
}),
|
|
44
158
|
components.input.create("name", {
|
|
45
|
-
label: "
|
|
46
|
-
description: "
|
|
159
|
+
label: "机器人显示名称",
|
|
160
|
+
description: "只用于 Karin 配置页和日志里识别这个机器人,不影响 QQ 平台资料。扫码登录写入配置时通常会自动填充。"
|
|
47
161
|
}),
|
|
48
162
|
components.input.create("appId", {
|
|
49
|
-
label: "AppID",
|
|
50
|
-
description: "
|
|
163
|
+
label: "机器人 AppID",
|
|
164
|
+
description: "QQ 开放平台机器人应用的 AppID,是识别机器人账号的唯一编号。填错会导致鉴权和收发消息失败。",
|
|
51
165
|
isRequired: true
|
|
52
166
|
}),
|
|
53
167
|
components.input.create("secret", {
|
|
54
|
-
label: "Secret",
|
|
55
|
-
description: "
|
|
168
|
+
label: "机器人 Secret",
|
|
169
|
+
description: "QQ 开放平台机器人应用的 Secret,用于获取 access token。请不要泄露;扫码授权会刷新 Secret,旧 Secret 会立即失效。",
|
|
56
170
|
isRequired: true
|
|
57
171
|
}),
|
|
58
|
-
components.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
isRequired: true
|
|
62
|
-
}),
|
|
63
|
-
components.input.create("sandboxApi", {
|
|
64
|
-
label: "沙盒环境 API",
|
|
65
|
-
defaultValue: "https://sandbox.api.sgroup.qq.com",
|
|
66
|
-
isRequired: true
|
|
67
|
-
}),
|
|
68
|
-
components.input.create("tokenApi", {
|
|
69
|
-
label: "AccessToken 接口",
|
|
70
|
-
defaultValue: "https://bots.qq.com/app/getAppAccessToken",
|
|
71
|
-
isRequired: true
|
|
172
|
+
components.divider.horizontal("bot-scene-section", {
|
|
173
|
+
description: "场景能力",
|
|
174
|
+
descPosition: 5
|
|
72
175
|
}),
|
|
73
176
|
components.switch.create("sandbox", {
|
|
74
|
-
label: "
|
|
75
|
-
description: "
|
|
177
|
+
label: "使用沙盒环境",
|
|
178
|
+
description: "开启后这个机器人会使用沙盒环境的 OpenAPI 和 WebSocket 地址;关闭时使用正式环境地址。正式上线机器人请关闭。",
|
|
76
179
|
defaultSelected: false
|
|
77
180
|
}),
|
|
78
181
|
components.switch.create("qqEnable", {
|
|
79
|
-
label: "QQ
|
|
80
|
-
description: "
|
|
182
|
+
label: "启用 QQ 私聊 / 群聊",
|
|
183
|
+
description: "开启后会处理 QQ 单聊和群聊里的消息事件;如果这个机器人只用于频道,可以关闭。",
|
|
81
184
|
defaultSelected: true
|
|
82
185
|
}),
|
|
83
186
|
components.switch.create("guildEnable", {
|
|
84
|
-
label: "
|
|
85
|
-
description: "
|
|
187
|
+
label: "启用频道消息",
|
|
188
|
+
description: "开启后会处理 QQ 频道消息事件;如果这个机器人只用于私聊或群聊,可以关闭。",
|
|
86
189
|
defaultSelected: true
|
|
87
190
|
}),
|
|
88
191
|
components.switch.create("guildMode", {
|
|
89
|
-
label: "
|
|
90
|
-
description: "
|
|
192
|
+
label: "频道私域机器人模式",
|
|
193
|
+
description: "关闭时按公域机器人处理,通常只接收 @ 机器人相关消息;开启时按私域机器人处理,可接收更多频道消息,需确认机器人权限匹配。",
|
|
91
194
|
defaultSelected: false
|
|
92
195
|
}),
|
|
196
|
+
components.divider.horizontal("bot-message-section", {
|
|
197
|
+
description: "消息发送",
|
|
198
|
+
descPosition: 5
|
|
199
|
+
}),
|
|
93
200
|
components.input.group("regex", {
|
|
94
201
|
data: [],
|
|
95
202
|
label: "消息正则替换",
|
|
96
|
-
description: "
|
|
203
|
+
description: "收到文本消息后,先按这里的规则替换内容,再交给 Karin 插件处理。每行格式是“正则表达式 替换内容”,中间用空格分隔;例如“^/ #”会把“/菜单”改成“#菜单”。不懂正则可以保留默认或清空。",
|
|
97
204
|
template: components.input.create("regex", {
|
|
98
|
-
label: "
|
|
205
|
+
label: "一条替换规则",
|
|
99
206
|
placeholder: "^/ #"
|
|
100
207
|
})
|
|
101
208
|
}),
|
|
102
209
|
components.switch.create("keyboard:enable", {
|
|
103
|
-
label: "
|
|
104
|
-
description: "
|
|
210
|
+
label: "把链接自动转成按钮",
|
|
211
|
+
description: "开启后,发送文本里出现的 http(s) 链接会尽量转成 QQ keyboard 按钮,用户可以直接点按钮打开链接。该能力依赖 Markdown 通道。",
|
|
105
212
|
defaultSelected: true
|
|
106
213
|
}),
|
|
107
|
-
components.
|
|
108
|
-
label: "
|
|
109
|
-
description: "
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
214
|
+
components.switch.create("markdown:enable", {
|
|
215
|
+
label: "启用 Markdown 发送通道",
|
|
216
|
+
description: "开启后普通文本和图片优先合并为 QQ Markdown 消息,Markdown 里的图片会以内嵌图片形式发送;关闭后普通图片会按官方富媒体单独上传发送。插件显式传入的 segment.markdown 不受此开关影响。",
|
|
217
|
+
defaultSelected: true
|
|
218
|
+
}),
|
|
219
|
+
components.divider.horizontal("bot-cache-section", {
|
|
220
|
+
description: "消息缓存",
|
|
221
|
+
descPosition: 5
|
|
222
|
+
}),
|
|
223
|
+
components.switch.create("messageCache:enable", {
|
|
224
|
+
label: "缓存收到的消息到数据库",
|
|
225
|
+
description: "开启后会把最近一天收到的消息写入本地数据库,供 bot.getMsg 等查询使用;收到的图片、语音、视频等富媒体也会保存到本地。消息量大时会明显占用磁盘空间。",
|
|
226
|
+
defaultSelected: false
|
|
227
|
+
}),
|
|
228
|
+
components.switch.create("messageCache:self", {
|
|
229
|
+
label: "同时缓存机器人自己发出的消息",
|
|
230
|
+
description: "只有开启“缓存收到的消息到数据库”后才生效。开启后,机器人发送成功的消息也会写入缓存,方便之后通过消息 ID 查询。",
|
|
231
|
+
defaultSelected: false
|
|
232
|
+
}),
|
|
233
|
+
components.divider.horizontal("bot-proxy-section", {
|
|
234
|
+
description: "连接代理(高级设置:通常只在使用 Webhook 转 WebSocket 服务时填写,除非你知道你在做什么,否则不建议更改)",
|
|
235
|
+
descPosition: 5
|
|
236
|
+
}),
|
|
237
|
+
components.input.create("proxy:ws", {
|
|
238
|
+
label: "WebSocket 接入地址",
|
|
239
|
+
description: "事件接收方式为 WebSocket 时连接的地址。常见用途是填写第三方 Webhook 转 WebSocket 服务地址,因为 QQ 后台开启 Webhook 后通常无法再直连官方 WebSocket。不填会使用当前环境的官方默认网关。"
|
|
240
|
+
}),
|
|
241
|
+
components.input.create("proxy:api", {
|
|
242
|
+
label: "OpenAPI 反代地址",
|
|
243
|
+
description: "用于发送消息、上传媒体、查询网关和获取机器人资料的 QQ OpenAPI 根地址。多数 Webhook 转 WebSocket 场景不用改这里;只有 OpenAPI 请求也需要走反代时才填写。"
|
|
128
244
|
})
|
|
129
245
|
]
|
|
130
246
|
}
|
|
@@ -135,37 +251,65 @@ var web_config_default = defineConfig({
|
|
|
135
251
|
success: false,
|
|
136
252
|
message: "保存失败:配置格式错误"
|
|
137
253
|
};
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
254
|
+
const prevConfig = readConfigFile();
|
|
255
|
+
let data;
|
|
256
|
+
try {
|
|
257
|
+
data = input.qqbot.map((item) => {
|
|
258
|
+
const previous = prevConfig.find((cfg) => cfg.appId === toStringValue(item.appId));
|
|
259
|
+
const sandbox = toBool(item.sandbox, previous?.sandbox ?? false);
|
|
260
|
+
const qqEnable = toBool(item.qqEnable, previous?.qqEnable ?? true);
|
|
261
|
+
const guildEnable = toBool(item.guildEnable, previous?.guildEnable ?? true);
|
|
262
|
+
const guildMode = toBool(item.guildMode, previous?.guildMode === 1) ? 1 : 0;
|
|
263
|
+
const eventType = Number(toStringValue(item["event:type"], String(previous?.event?.type ?? 0)));
|
|
264
|
+
const keyboardEnable = toBool(item["keyboard:enable"], previous?.keyboard?.enable ?? true);
|
|
265
|
+
const markdownEnable = toBool(item["markdown:enable"], previous?.markdown?.enable ?? true);
|
|
266
|
+
const messageCacheEnable = toBool(item["messageCache:enable"], previous?.messageCache?.enable ?? false);
|
|
267
|
+
const messageCacheSelf = toBool(item["messageCache:self"], previous?.messageCache?.self ?? false);
|
|
268
|
+
const regex = toStringList(item.regex).map((str) => {
|
|
269
|
+
const parts = str.split(" ");
|
|
270
|
+
return {
|
|
271
|
+
reg: parts[0]?.replace(/^<|>$/g, "") || "",
|
|
272
|
+
rep: parts[1]?.replace(/^<|>$/g, "") || ""
|
|
273
|
+
};
|
|
274
|
+
});
|
|
275
|
+
const proxy = proxyFromInput(item, previous);
|
|
143
276
|
return {
|
|
144
|
-
|
|
145
|
-
|
|
277
|
+
name: toStringValue(item.name),
|
|
278
|
+
appId: toStringValue(item.appId),
|
|
279
|
+
secret: toStringValue(item.secret),
|
|
280
|
+
proxy,
|
|
281
|
+
sandbox,
|
|
282
|
+
qqEnable,
|
|
283
|
+
guildEnable,
|
|
284
|
+
guildMode,
|
|
285
|
+
regex,
|
|
286
|
+
keyboard: { enable: keyboardEnable },
|
|
287
|
+
markdown: { enable: markdownEnable },
|
|
288
|
+
messageCache: {
|
|
289
|
+
enable: messageCacheEnable,
|
|
290
|
+
self: messageCacheSelf
|
|
291
|
+
},
|
|
292
|
+
event: { type: eventType }
|
|
146
293
|
};
|
|
147
294
|
});
|
|
295
|
+
} catch (err) {
|
|
148
296
|
return {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
secret: item.secret || "",
|
|
152
|
-
prodApi: item.prodApi || "https://api.sgroup.qq.com",
|
|
153
|
-
sandboxApi: item.sandboxApi || "https://sandbox.api.sgroup.qq.com",
|
|
154
|
-
tokenApi: item.tokenApi || "https://bots.qq.com/app/getAppAccessToken",
|
|
155
|
-
sandbox: !!item.sandbox,
|
|
156
|
-
qqEnable: !!item.qqEnable,
|
|
157
|
-
guildEnable: !!item.guildEnable,
|
|
158
|
-
guildMode,
|
|
159
|
-
regex,
|
|
160
|
-
keyboard: { enable: item["keyboard:enable"] !== false },
|
|
161
|
-
event: { type: eventType }
|
|
297
|
+
success: false,
|
|
298
|
+
message: `保存失败:代理地址格式错误:${err?.message || "unknown"}`
|
|
162
299
|
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
300
|
+
}
|
|
301
|
+
try {
|
|
302
|
+
writeConfig(data);
|
|
303
|
+
return {
|
|
304
|
+
success: true,
|
|
305
|
+
message: "保存成功"
|
|
306
|
+
};
|
|
307
|
+
} catch (err) {
|
|
308
|
+
return {
|
|
309
|
+
success: false,
|
|
310
|
+
message: `保存失败:${err?.message || "unknown"}`
|
|
311
|
+
};
|
|
312
|
+
}
|
|
169
313
|
}
|
|
170
314
|
});
|
|
171
315
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@karinjs/adapter-qqbot",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "karin adapter for QQ Official Bot (2.0)",
|
|
5
5
|
"homepage": "https://github.com/KarinJS/karin-plugin-adapter-qqbot",
|
|
6
6
|
"bugs": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@karinjs/geturls": "^1.0.2",
|
|
31
|
-
"form-data": "^4.0.
|
|
31
|
+
"form-data": "^4.0.6",
|
|
32
32
|
"image-size": "^2.0.2",
|
|
33
33
|
"qrcode": "^1.5.4",
|
|
34
34
|
"silk-wasm": "^3.7.1",
|
|
@@ -36,24 +36,19 @@
|
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/express": "5.0.6",
|
|
39
|
-
"@types/node": "^24.
|
|
39
|
+
"@types/node": "^24.13.2",
|
|
40
40
|
"@types/qrcode": "^1.5.6",
|
|
41
41
|
"eslint": "^9.39.4",
|
|
42
42
|
"neostandard": "^0.13.0",
|
|
43
|
-
"node-karin": "
|
|
44
|
-
"tsdown": "^0.22.
|
|
45
|
-
"tsx": "^4.
|
|
43
|
+
"node-karin": "1.16.3",
|
|
44
|
+
"tsdown": "^0.22.3",
|
|
45
|
+
"tsx": "^4.23.0",
|
|
46
46
|
"typescript": "^6.0.3"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public",
|
|
50
50
|
"registry": "https://registry.npmjs.org"
|
|
51
51
|
},
|
|
52
|
-
"pnpm": {
|
|
53
|
-
"overrides": {
|
|
54
|
-
"yaml@>=2.0.0 <2.8.3": "^2.8.3"
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
52
|
"karin": {
|
|
58
53
|
"main": "src/index.ts",
|
|
59
54
|
"apps": [
|