koishi-plugin-node-async-bot-all 2.30.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands.d.ts +26 -57
- package/lib/config.d.ts +38 -0
- package/lib/fun.d.ts +29 -15
- package/lib/index.d.ts +24 -39
- package/lib/index.js +754 -880
- package/package.json +27 -21
- package/res/steamNews.html +179 -0
- package/res/slNews.html +0 -71
- package/res/userCard.html +0 -242
- package/res/userMsg.html +0 -110
package/lib/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
34
34
|
// src/locales/zh-CN.yml
|
|
35
35
|
var require_zh_CN = __commonJS({
|
|
36
36
|
"src/locales/zh-CN.yml"(exports2, module2) {
|
|
37
|
-
module2.exports = { noApi: "未指定 API", noop: "无", unknownError: "未知错误。", failed: "{quote}{time}\n{error}", "failed-md": "**{time}**\n
|
|
37
|
+
module2.exports = { noApi: "未指定 API", noop: "无", unknownError: "未知错误。", failed: "{quote}{time}\n{error}", "failed-md": "**{time}**\n{error}", commands: { na: { description: "NodeAsync Bot" }, cxgame: { description: "查询服务器当前人数。", messages: { msg: "{time}{list}\n进服指南请在群公告中查看。", "msg-md": "*{time}*\n\n---\n{list}\n\n---\n\n进服指南请在群公告中查看。", list: "【{name} 服务器 {count}】\n➣ {version}:{players}\n➣ {ne}:{list}\n➣ 备注:{note}", "list-md": "## {name} 服务器 {count}\n\n- {version}:{players}\n- {ne}:{list}\n- 备注:{note}", listFailed: "【{name} 服务器 {count}】\n➣ 查询失败:{data}\n➣ 请稍后重试。\n➣ 备注:{note}", "listFailed-md": "## {name} 服务器 {count}\n\n- 查询失败:{data}\n- 请稍后重试。\n- 备注:{note}", timeout: "请求超时。", fewData: "服务端返回的数据过少。", close: "服务器已关闭。", host: "没有到主机的路由。", dns: "解析失败。", "ne-a2s": "机器人", "ne-mc": "玩家列表", forbidden: "此指令不允许在本群使用。", failed: "查询失败:" } }, status: { description: "查询机器人状态。", messages: { msg: "{time}\n--- 系统状态 ---\n系统名称:{name}\nCPU使用率:{cpu}\n内存使用率:{memory}\n--- 机器人状态 ---\n昨日收/发消息数量:{msgCount}\n机器人版本:{version}\n运行时间:{online}", "msg-md": "*{time}*\n\n---\n\n## 系统状态\n\n- 系统名称:{name}\n- CPU使用率:{cpu}\n- 内存使用率:{memory}\n\n## 机器人状态\n\n- 昨日收/发消息数量:{msgCount}\n- 机器人版本:{version}\n- 运行时间:{online}", error: "状态获取失败。" } }, random: { description: "随机数生成器。", usage: "缺少参数时默认生成 0-10000 的随机数。\n使用示例:", examples: "random 1 128 生成1到128范围的随机数", messages: { msg: "{time}\n生成了一个随机数:{data}", "msg-md": "*{time}*\n\n---\n\n生成了一个随机数:{data}" } }, info: { description: "查询机器人信息。", messages: { msg: "{time}\n--- NodeAsync {version} ---\n私有机器人,服务器专用。\n--- 开发者 ---\n德二吹风机(3112836258)\n--- 其他 ---\nNode.js 版本:{nodeVersion}\nKoishi 版本:{koishiVersion}\n开源地址:https://github.com/ccd2s/node-async-bot-all\n官网:https://www.tasaed.top", "msg-md": "*{time}*\n\n---\n\n## NodeAsync {version}\n\n私有机器人,服务器专用。\n\n## 开发者\n\n- 德二吹风机(3112836258)\n\n## 其他\n\n- Node.js 版本:{nodeVersion}\n- Koishi 版本:{koishiVersion}\n- 开源地址:https://github.com/ccd2s/node-async-bot-all\n- 官网:https://www.tasaed.top", error: "读取信息失败。" } }, rw: { description: "随机名言名句。", messages: null }, randomba: { description: "随机BA图。", messages: { msg: "{quote}{image}" } }, centerservertest: { description: "查看中心服务器状态。", messages: { msg: "{time}{list}", "msg-md": "*{time}*\n\n---\n{list}", list: "== {name} ==\n状态:{status}\n存活率:{uptime}\n检测时间:{time}", "list-md": "## {name}\n\n- 状态:{status}\n- 存活率:{uptime}\n- 检测时间:{time}", listFailed: "== {name} ==\n查看失败:{data}", "listFailed-md": "## {name}\n\n查看失败:{data}", statusLive: "✅ 正常", statusDie: "❌ 故障", dataFail: "未能获取到此服务器的状态信息。" } }, meme: { description: "群友的怪话!", usage: "不带参数时随机查看\n带参数时为查看指定 meme", examples: "meme\nmeme 1145", messages: { msg: "{quote}{time}\n{image}\n{title}", "msg-qq": "{quote}{image}\n{time}\n{title}" } }, randomcat: { description: "随机猫猫图。", messages: { msg: "{quote}{image}" } }, getqqinfo: { description: "获取 QQ 号的信息。", usage: "获取 QQ 号的信息。", examples: "getqqinfo 10001", messages: { msg: "{quote}{image}", failed: "{quote}{time}\n获取失败:{data}", command: "QQ 号不正确。" } }, msg2img: { description: "引用一个消息并使用此指令,即可将消息转图。", usage: "引用一条消息,/m。(不要带@)", messages: { msg: "{quote}{image}", failed: "{quote}{time}\n获取失败:{data}", null: "未引用任何消息。", matroska: "{quote}禁止套娃!" } }, steamnews: { description: "抓取 Steam 游戏的最新新闻。" }, use: { description: "使用 TA !", usage: "use @用户", examples: "use @用户", messages: { command: "请 @ 一个用户。", msg: "{at} {desc}了 {at2} !" } } } };
|
|
38
38
|
}
|
|
39
39
|
});
|
|
40
40
|
|
|
@@ -42,13 +42,14 @@ var require_zh_CN = __commonJS({
|
|
|
42
42
|
var src_exports = {};
|
|
43
43
|
__export(src_exports, {
|
|
44
44
|
Config: () => Config,
|
|
45
|
+
NodeAsyncBot: () => NodeAsyncBot,
|
|
45
46
|
apply: () => apply,
|
|
46
47
|
inject: () => inject,
|
|
47
48
|
name: () => name,
|
|
48
49
|
usage: () => usage
|
|
49
50
|
});
|
|
50
51
|
module.exports = __toCommonJS(src_exports);
|
|
51
|
-
var
|
|
52
|
+
var import_koishi4 = require("koishi");
|
|
52
53
|
|
|
53
54
|
// src/commands.ts
|
|
54
55
|
var import_koishi2 = require("koishi");
|
|
@@ -59,9 +60,7 @@ var import_fs = __toESM(require("fs"));
|
|
|
59
60
|
var import_path = __toESM(require("path"));
|
|
60
61
|
var import_koishi = require("koishi");
|
|
61
62
|
var import_steam_server_query = require("steam-server-query");
|
|
62
|
-
var
|
|
63
|
-
var import_preset_html5 = __toESM(require("@bbob/preset-html5"));
|
|
64
|
-
var import_bing_translate_api = require("bing-translate-api");
|
|
63
|
+
var import_feedsmith = require("feedsmith");
|
|
65
64
|
var import_minecraft_server_util = require("minecraft-server-util");
|
|
66
65
|
function getSystemName() {
|
|
67
66
|
return import_os.default.type() + " " + import_os.default.release();
|
|
@@ -101,15 +100,15 @@ __name(getCpuUsage, "getCpuUsage");
|
|
|
101
100
|
async function getSystemUsage() {
|
|
102
101
|
try {
|
|
103
102
|
return {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
name: getSystemName(),
|
|
104
|
+
cpu: await getCpuUsage(),
|
|
105
|
+
memory: getMemoryUsage(),
|
|
106
|
+
success: 0
|
|
108
107
|
};
|
|
109
108
|
} catch (error) {
|
|
110
109
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
data: error.message,
|
|
111
|
+
success: 1
|
|
113
112
|
};
|
|
114
113
|
}
|
|
115
114
|
}
|
|
@@ -158,7 +157,10 @@ function formatTimestampDiff(start, end) {
|
|
|
158
157
|
}
|
|
159
158
|
__name(formatTimestampDiff, "formatTimestampDiff");
|
|
160
159
|
async function getMsgCount(ctx) {
|
|
161
|
-
const array = await ctx.database.get("analytics.message", { date: import_koishi.Time.getDateNumber() - 1 }, [
|
|
160
|
+
const array = await ctx.database.get("analytics.message", { date: import_koishi.Time.getDateNumber() - 1 }, [
|
|
161
|
+
"type",
|
|
162
|
+
"count"
|
|
163
|
+
]);
|
|
162
164
|
let receive = 0;
|
|
163
165
|
let send = 0;
|
|
164
166
|
array.forEach((item) => {
|
|
@@ -168,7 +170,7 @@ async function getMsgCount(ctx) {
|
|
|
168
170
|
send = send + item.count;
|
|
169
171
|
}
|
|
170
172
|
});
|
|
171
|
-
return {
|
|
173
|
+
return { receive, send };
|
|
172
174
|
}
|
|
173
175
|
__name(getMsgCount, "getMsgCount");
|
|
174
176
|
function random(type = 0, data, data2) {
|
|
@@ -188,91 +190,55 @@ function random(type = 0, data, data2) {
|
|
|
188
190
|
}
|
|
189
191
|
}
|
|
190
192
|
__name(random, "random");
|
|
191
|
-
async function request(url, options = {
|
|
192
|
-
const
|
|
193
|
+
async function request(url, ctx, options = { method: "GET", timeout: 8e3 }, logger) {
|
|
194
|
+
const log = logger ?? ctx.logger("http");
|
|
193
195
|
try {
|
|
194
|
-
const response = await
|
|
196
|
+
const response = await ctx.http(url, options);
|
|
195
197
|
let responseData;
|
|
196
|
-
let
|
|
197
|
-
const text = await response.
|
|
198
|
+
let isObj;
|
|
199
|
+
const text = await response.data;
|
|
198
200
|
try {
|
|
199
201
|
responseData = JSON.parse(text);
|
|
200
|
-
|
|
202
|
+
isObj = true;
|
|
201
203
|
} catch {
|
|
202
204
|
responseData = text;
|
|
203
|
-
|
|
205
|
+
isObj = false;
|
|
204
206
|
}
|
|
205
|
-
if (
|
|
206
|
-
log
|
|
207
|
-
return {
|
|
207
|
+
if (response.status !== 200) {
|
|
208
|
+
log.error(`HTTP Error ${response.status}: ${url}`, responseData);
|
|
209
|
+
return isObj ? {
|
|
210
|
+
success: false,
|
|
211
|
+
code: response.status,
|
|
212
|
+
error: responseData,
|
|
213
|
+
isObj: true,
|
|
214
|
+
isError: false
|
|
215
|
+
} : {
|
|
208
216
|
success: false,
|
|
209
217
|
code: response.status,
|
|
210
|
-
error: responseData
|
|
211
|
-
|
|
218
|
+
error: responseData ?? `HTTP ${response.status}`,
|
|
219
|
+
isObj: false,
|
|
220
|
+
isError: false
|
|
212
221
|
};
|
|
213
222
|
}
|
|
214
|
-
log
|
|
223
|
+
log.info(`HTTP ${response.status}: ${url}`);
|
|
215
224
|
return {
|
|
216
225
|
success: true,
|
|
217
226
|
data: responseData
|
|
218
227
|
};
|
|
219
228
|
} catch (error) {
|
|
220
|
-
const
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
log
|
|
229
|
+
const { name: name2, message } = error instanceof Error ? error : { name: "UnknownError", message: "unknown message" };
|
|
230
|
+
const isTimeout = name2 === "TimeoutError" || name2 === "AbortError";
|
|
231
|
+
const errorMessage = isTimeout ? `请求超时。(${options?.timeout}ms)` : message;
|
|
232
|
+
log.error(url);
|
|
233
|
+
log.error(`Request Failed:`, error);
|
|
224
234
|
return {
|
|
225
235
|
success: false,
|
|
226
|
-
error: { name:
|
|
227
|
-
|
|
236
|
+
error: { name: name2, message: errorMessage },
|
|
237
|
+
isError: true
|
|
228
238
|
};
|
|
229
239
|
}
|
|
230
240
|
}
|
|
231
241
|
__name(request, "request");
|
|
232
|
-
async function readUserCardFile(userInfo) {
|
|
233
|
-
let card;
|
|
234
|
-
try {
|
|
235
|
-
const aPath = import_path.default.resolve(__dirname, "..") + import_path.default.sep + "res" + import_path.default.sep + "userCard.html";
|
|
236
|
-
card = await import_fs.default.promises.readFile(aPath, "utf8");
|
|
237
|
-
let sex_so;
|
|
238
|
-
let sex;
|
|
239
|
-
if (userInfo.sex == "male") {
|
|
240
|
-
sex = "♂";
|
|
241
|
-
sex_so = "sex-male";
|
|
242
|
-
} else if (userInfo.sex == "female") {
|
|
243
|
-
sex = "♀";
|
|
244
|
-
sex_so = "sex-female";
|
|
245
|
-
} else {
|
|
246
|
-
sex = "猫娘";
|
|
247
|
-
sex_so = "sex-unknown";
|
|
248
|
-
}
|
|
249
|
-
card = card.toString().replace("{avatarUrl}", userInfo.avatar_url).replace("{nickname}", userInfo.nickname).replace("{sex}", sex).replace("{sex-so}", sex_so).replace("{age}", String(userInfo.age)).replace("{longNick}", userInfo.long_nick == "" ? "<无>" : `“ ${userInfo.long_nick} ”`).replace("{qq}", userInfo.qq).replace("{qqLevel}", String(userInfo.qq_level)).replace("{qid}", userInfo.qid == "" ? "<无>" : userInfo.qid).replace("{location}", userInfo.location == "" ? "<无>" : userInfo.location).replace("{email}", userInfo.email == "" ? "<无>" : userInfo.email).replace("{regTime}", userInfo.reg_time).replace("{lastUpdated}", userInfo.last_updated);
|
|
250
|
-
} catch (error) {
|
|
251
|
-
card = error.message;
|
|
252
|
-
}
|
|
253
|
-
return card;
|
|
254
|
-
}
|
|
255
|
-
__name(readUserCardFile, "readUserCardFile");
|
|
256
|
-
async function readUserMsgFile(userName, userAvatar, msg, inversion, replyUserName, replyMsg) {
|
|
257
|
-
let html;
|
|
258
|
-
try {
|
|
259
|
-
const aPath = import_path.default.resolve(__dirname, "..") + import_path.default.sep + "res" + import_path.default.sep + "userMsg.html";
|
|
260
|
-
html = await import_fs.default.promises.readFile(aPath, "utf8");
|
|
261
|
-
html = html.toString().replace("{userData.avatarUrl}", userAvatar).replace("{userData.username}", userName).replace("{userData.message}", msg).replace("{replyData.username}", replyUserName).replace("{replyData.message}", replyMsg).replace(
|
|
262
|
-
/<at\s+(?:id=["']([^"']*)["']\s+name=["']([^"']*)["']|name=["']([^"']*)["']\s+id=["']([^"']*)["'])\s*\/?>/g,
|
|
263
|
-
(match, id1, name1, name2, id2) => {
|
|
264
|
-
const name3 = name1 || name2 || id1 || id2 || match;
|
|
265
|
-
return `@${name3}`;
|
|
266
|
-
}
|
|
267
|
-
).replace('<at type="all"/>', "@全体成员");
|
|
268
|
-
if (inversion) html = html.replace("//// ", "");
|
|
269
|
-
if (replyUserName != void 0) html = html.replace("/**/", "//// ");
|
|
270
|
-
} catch (error) {
|
|
271
|
-
html = error.message;
|
|
272
|
-
}
|
|
273
|
-
return html;
|
|
274
|
-
}
|
|
275
|
-
__name(readUserMsgFile, "readUserMsgFile");
|
|
276
242
|
async function queryA2S(host, log) {
|
|
277
243
|
try {
|
|
278
244
|
const playerResponse = await (0, import_steam_server_query.queryGameServerInfo)(host);
|
|
@@ -294,697 +260,570 @@ async function queryA2S(host, log) {
|
|
|
294
260
|
}
|
|
295
261
|
}
|
|
296
262
|
__name(queryA2S, "queryA2S");
|
|
297
|
-
async function
|
|
298
|
-
let html;
|
|
263
|
+
async function parseNewsRssToHtml(rss, log, count) {
|
|
299
264
|
try {
|
|
300
|
-
const aPath = import_path.default.resolve(__dirname, "..") + import_path.default.sep + "res" + import_path.default.sep + "
|
|
301
|
-
html = await import_fs.default.promises.readFile(aPath, "utf8");
|
|
302
|
-
const content =
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
const finalText = bilingualParagraphs.join("<br />").replace(/<br \/>{2,}/g, "<br />");
|
|
314
|
-
const contentHtml = (0, import_html.default)(finalText, (0, import_preset_html5.default)());
|
|
315
|
-
const date = Number(info.appnews.newsitems[0].date + "000");
|
|
316
|
-
html = html.toString().replace("{date}", new Date(date).toLocaleString()).replace("{title}", info.appnews.newsitems[0].title).replace("{content}", contentHtml);
|
|
265
|
+
const aPath = import_path.default.resolve(__dirname, "..") + import_path.default.sep + "res" + import_path.default.sep + "steamNews.html";
|
|
266
|
+
let html = await import_fs.default.promises.readFile(aPath, "utf8");
|
|
267
|
+
const content = (0, import_feedsmith.parseRssFeed)(rss);
|
|
268
|
+
if (!content?.items) return { error: new Error("响应不正确") };
|
|
269
|
+
const item = content.items[count ?? 0];
|
|
270
|
+
if (!item || !item.guid) return { error: new Error("文章不存在") };
|
|
271
|
+
if (item.enclosures && item.enclosures[0] && item.enclosures[0].url)
|
|
272
|
+
html = html.replace("<!--!", "").replace("!!-->", "").replace("{imgUrl}", item.enclosures[0].url);
|
|
273
|
+
return {
|
|
274
|
+
data: html.replace("{date}", new Date(item.pubDate ?? 0).toLocaleString()).replace("{title}", item.title ?? "无").replace("{content}", item.description ?? "无"),
|
|
275
|
+
guid: item.guid?.value
|
|
276
|
+
};
|
|
317
277
|
} catch (error) {
|
|
318
278
|
log.error(error);
|
|
319
279
|
log.error(error.message);
|
|
320
|
-
return
|
|
280
|
+
return { error };
|
|
321
281
|
}
|
|
322
|
-
return [html];
|
|
323
282
|
}
|
|
324
|
-
__name(
|
|
325
|
-
async function translateAPI(log, text) {
|
|
326
|
-
const ms = random(0, 0, 250);
|
|
327
|
-
await (0, import_koishi.sleep)(ms);
|
|
328
|
-
await (0, import_bing_translate_api.translate)(text, "en", "zh-Hans").then((result) => {
|
|
329
|
-
text = result?.translation;
|
|
330
|
-
}).catch((err) => {
|
|
331
|
-
log.error(err);
|
|
332
|
-
});
|
|
333
|
-
return text;
|
|
334
|
-
}
|
|
335
|
-
__name(translateAPI, "translateAPI");
|
|
283
|
+
__name(parseNewsRssToHtml, "parseNewsRssToHtml");
|
|
336
284
|
async function slpInfo(log, host, port, timeout) {
|
|
337
285
|
try {
|
|
338
286
|
const info = await (0, import_minecraft_server_util.status)(host, port, { timeout });
|
|
339
287
|
log.info(info);
|
|
340
288
|
return {
|
|
341
|
-
|
|
342
|
-
|
|
289
|
+
success: true,
|
|
290
|
+
data: info
|
|
343
291
|
};
|
|
344
292
|
} catch (error) {
|
|
345
293
|
log.error(error);
|
|
346
294
|
return {
|
|
347
|
-
|
|
348
|
-
|
|
295
|
+
success: false,
|
|
296
|
+
data: error.message
|
|
349
297
|
};
|
|
350
298
|
}
|
|
351
299
|
}
|
|
352
300
|
__name(slpInfo, "slpInfo");
|
|
353
301
|
|
|
354
302
|
// src/commands.ts
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
} else {
|
|
417
|
-
const host = api.split(":");
|
|
418
|
-
const serverInfo = await slpInfo(log, host[0], Number(host[1]), ctx.config.timeout);
|
|
419
|
-
if (serverInfo.success) {
|
|
420
|
-
log.debug(serverInfo);
|
|
421
|
-
if (serverInfo.data.players.sample == null) {
|
|
303
|
+
var CommandHandler = class {
|
|
304
|
+
static {
|
|
305
|
+
__name(this, "CommandHandler");
|
|
306
|
+
}
|
|
307
|
+
ctx;
|
|
308
|
+
session;
|
|
309
|
+
log;
|
|
310
|
+
time;
|
|
311
|
+
isQQ;
|
|
312
|
+
constructor(ctx, session, loggerName) {
|
|
313
|
+
this.ctx = ctx;
|
|
314
|
+
this.session = session;
|
|
315
|
+
this.log = ctx.logger(loggerName);
|
|
316
|
+
this.time = getHongKongTime();
|
|
317
|
+
this.isQQ = session?.bot.adapterName == "qq";
|
|
318
|
+
this.log.debug(
|
|
319
|
+
`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
// 发送普通消息(自动判断 QQ markdown)
|
|
323
|
+
async sendMsg(msgKey, data) {
|
|
324
|
+
await this.session?.send(
|
|
325
|
+
this.isQQ ? (0, import_koishi2.h)("qq:markdown", { content: this.session?.text(msgKey, data) }) : this.session?.text(msgKey, data)
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
// 发送失败消息
|
|
329
|
+
async sendFailed(data) {
|
|
330
|
+
await this.sendMsg(this.isQQ ? "failed-md" : "failed", data);
|
|
331
|
+
}
|
|
332
|
+
// 指令 cx
|
|
333
|
+
async server() {
|
|
334
|
+
const { ctx, session, log, time, isQQ } = this;
|
|
335
|
+
let msg;
|
|
336
|
+
const index = ctx.config.cxV3.findIndex(
|
|
337
|
+
(item) => item.id === session.event.guild?.id
|
|
338
|
+
);
|
|
339
|
+
if (index !== -1) {
|
|
340
|
+
const server = ctx.config.cxV3[index].server;
|
|
341
|
+
if (server == void 0) {
|
|
342
|
+
msg = {
|
|
343
|
+
time,
|
|
344
|
+
error: session.text(".failed") + session.text("noApi"),
|
|
345
|
+
success: 2
|
|
346
|
+
};
|
|
347
|
+
log.warn("Sent:");
|
|
348
|
+
log.warn(msg);
|
|
349
|
+
await this.sendFailed(msg);
|
|
350
|
+
return 1;
|
|
351
|
+
}
|
|
352
|
+
let count = 0;
|
|
353
|
+
let list = "";
|
|
354
|
+
for (const item of server) {
|
|
355
|
+
const note = item.note;
|
|
356
|
+
const type = item.type;
|
|
357
|
+
const api = item.api;
|
|
358
|
+
count++;
|
|
359
|
+
if (type == "a2s") {
|
|
360
|
+
const info = await queryA2S(api, log);
|
|
361
|
+
if (info.success) {
|
|
362
|
+
log.debug(info);
|
|
422
363
|
const temp = {
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
364
|
+
count,
|
|
365
|
+
players: info.players,
|
|
366
|
+
version: info.version,
|
|
367
|
+
list: info.bots,
|
|
368
|
+
note: note ?? session.text("noop"),
|
|
369
|
+
name: "A2S",
|
|
370
|
+
ne: session.text(".ne-a2s")
|
|
430
371
|
};
|
|
431
372
|
log.info(`Server ${count}:`);
|
|
432
373
|
log.info(temp);
|
|
433
|
-
list = list + "\n" + session.text(
|
|
374
|
+
list = list + "\n" + session.text(isQQ ? ".list-md" : ".list", temp);
|
|
434
375
|
} else {
|
|
376
|
+
let err;
|
|
377
|
+
if (info.error.toString().includes(
|
|
378
|
+
"Timeout reached. Possible reasons: You are being rate limited; Timeout too short; Wrong server host configured"
|
|
379
|
+
)) {
|
|
380
|
+
err = session.text(".timeout");
|
|
381
|
+
} else {
|
|
382
|
+
err = session.text("unknown");
|
|
383
|
+
}
|
|
435
384
|
const temp = {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
"note": note ?? session.text("noop"),
|
|
441
|
-
"ne": "玩家列表",
|
|
442
|
-
"name": "MC"
|
|
385
|
+
count,
|
|
386
|
+
data: err,
|
|
387
|
+
note,
|
|
388
|
+
name: "A2S"
|
|
443
389
|
};
|
|
444
|
-
log.
|
|
445
|
-
log.
|
|
446
|
-
list = list + "\n" + session.text(
|
|
390
|
+
log.error(`Server ${count}:`);
|
|
391
|
+
log.error(temp);
|
|
392
|
+
list = list + "\n" + session.text(isQQ ? ".listFailed-md" : ".listFailed", temp);
|
|
447
393
|
}
|
|
448
394
|
} else {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
395
|
+
const host = api.split(":");
|
|
396
|
+
const serverInfo = await slpInfo(log, host[0], Number(host[1]), ctx.config.timeout);
|
|
397
|
+
if (serverInfo.success) {
|
|
398
|
+
log.debug(serverInfo);
|
|
399
|
+
if (serverInfo.data.players.sample == null) {
|
|
400
|
+
const temp = {
|
|
401
|
+
count,
|
|
402
|
+
players: serverInfo.data.players.online + "/" + serverInfo.data.players.max,
|
|
403
|
+
version: serverInfo.data.version.name,
|
|
404
|
+
note: note ?? session.text("noop"),
|
|
405
|
+
ne: session.text(".ne-mc"),
|
|
406
|
+
list: "[]",
|
|
407
|
+
name: "MC"
|
|
408
|
+
};
|
|
409
|
+
log.info(`Server ${count}:`);
|
|
410
|
+
log.info(temp);
|
|
411
|
+
list = list + "\n" + session.text(isQQ ? ".list-md" : ".list", temp);
|
|
412
|
+
} else {
|
|
413
|
+
const temp = {
|
|
414
|
+
count,
|
|
415
|
+
players: serverInfo.data.players.online + "/" + serverInfo.data.players.max,
|
|
416
|
+
version: serverInfo.data.version.name,
|
|
417
|
+
list: serverInfo.data.players.sample.map((item2) => item2.name).join(", "),
|
|
418
|
+
note: note ?? session.text("noop"),
|
|
419
|
+
ne: session.text(".ne-mc"),
|
|
420
|
+
name: "MC"
|
|
421
|
+
};
|
|
422
|
+
log.info(`Server ${count}:`);
|
|
423
|
+
log.info(temp);
|
|
424
|
+
list = list + "\n" + session.text(isQQ ? ".list-md" : ".list", temp);
|
|
425
|
+
}
|
|
426
|
+
} else {
|
|
427
|
+
let err = serverInfo.data;
|
|
428
|
+
if (err.includes("connect ECONNREFUSED") || err.includes("Server is offline or unreachable")) {
|
|
429
|
+
err = session.text(".close");
|
|
430
|
+
} else if (err.includes("connect EHOSTUNREACH")) {
|
|
431
|
+
err = session.text(".host");
|
|
432
|
+
} else if (err.includes("connect ETIMEDOUT")) {
|
|
433
|
+
err = session.text(".timeout");
|
|
434
|
+
} else if (err.includes("Ping payload did not match received payload")) {
|
|
435
|
+
err = session.text(".fewData");
|
|
436
|
+
} else if (err.includes("Expected server to send packet type")) {
|
|
437
|
+
err = session.text(".fewData");
|
|
438
|
+
} else if (err.includes("getaddrinfo")) {
|
|
439
|
+
err = session.text(".dns");
|
|
440
|
+
}
|
|
441
|
+
const temp = {
|
|
442
|
+
count,
|
|
443
|
+
data: err,
|
|
444
|
+
note,
|
|
445
|
+
name: "MC"
|
|
446
|
+
};
|
|
447
|
+
log.error(`Server ${count}:`);
|
|
448
|
+
log.error(temp);
|
|
449
|
+
list = list + "\n" + session.text(isQQ ? ".listFailed-md" : ".listFailed", temp);
|
|
462
450
|
}
|
|
463
|
-
const temp = {
|
|
464
|
-
"count": count,
|
|
465
|
-
"data": err,
|
|
466
|
-
"note": note,
|
|
467
|
-
"name": "MC"
|
|
468
|
-
};
|
|
469
|
-
log.error(`Server ${count}:`);
|
|
470
|
-
log.error(temp);
|
|
471
|
-
list = list + "\n" + session.text(session?.bot.adapterName == "qq" ? ".listFailed-md" : ".listFailed", temp);
|
|
472
451
|
}
|
|
473
452
|
}
|
|
453
|
+
msg = {
|
|
454
|
+
time,
|
|
455
|
+
list,
|
|
456
|
+
success: 0
|
|
457
|
+
};
|
|
458
|
+
await this.sendMsg(isQQ ? ".msg-md" : ".msg", msg);
|
|
459
|
+
return 0;
|
|
460
|
+
} else {
|
|
461
|
+
msg = {
|
|
462
|
+
time,
|
|
463
|
+
error: session.text(".forbidden"),
|
|
464
|
+
success: 1
|
|
465
|
+
};
|
|
466
|
+
log.info("Sent:");
|
|
467
|
+
log.info(msg);
|
|
468
|
+
await this.sendFailed(msg);
|
|
469
|
+
return 1;
|
|
474
470
|
}
|
|
475
|
-
msg = {
|
|
476
|
-
"time": time,
|
|
477
|
-
"list": list,
|
|
478
|
-
"success": 0
|
|
479
|
-
};
|
|
480
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
481
|
-
content: session?.text(".msg-md", msg)
|
|
482
|
-
}) : session?.text(".msg", msg));
|
|
483
|
-
return 0;
|
|
484
|
-
} else {
|
|
485
|
-
msg = {
|
|
486
|
-
"time": time,
|
|
487
|
-
"error": "此指令不允许在本群使用。",
|
|
488
|
-
"success": 1
|
|
489
|
-
};
|
|
490
|
-
log.info("Sent:");
|
|
491
|
-
log.info(msg);
|
|
492
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
493
|
-
content: session?.text("failed-md", msg)
|
|
494
|
-
}) : session?.text("failed", msg));
|
|
495
|
-
return 1;
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
__name(getServer, "getServer");
|
|
499
|
-
async function getStatus(ctx, session) {
|
|
500
|
-
const log = ctx.logger("status");
|
|
501
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
502
|
-
const time = getHongKongTime();
|
|
503
|
-
let msg;
|
|
504
|
-
const vMsg = await getSystemUsage();
|
|
505
|
-
if (vMsg["success"] == 1) {
|
|
506
|
-
log.error(vMsg);
|
|
507
|
-
msg = {
|
|
508
|
-
"time": time,
|
|
509
|
-
"data": vMsg["data"],
|
|
510
|
-
"error": "状态获取失败。",
|
|
511
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
512
|
-
"success": 1
|
|
513
|
-
};
|
|
514
|
-
} else {
|
|
515
|
-
const msgCount = await getMsgCount(ctx);
|
|
516
|
-
msg = {
|
|
517
|
-
"time": time,
|
|
518
|
-
"name": vMsg["name"],
|
|
519
|
-
"cpu": vMsg["cpu"],
|
|
520
|
-
"memory": vMsg["memory"],
|
|
521
|
-
"online": formatTimestampDiff(
|
|
522
|
-
Number((await ctx.database.get("botData", "uptime"))[0].data),
|
|
523
|
-
Number(session.event.timestamp.toString().substring(0, 10))
|
|
524
|
-
),
|
|
525
|
-
"msgCount": `${msgCount["receive"]}/${msgCount["send"]}`,
|
|
526
|
-
"version": (await ctx.database.get("botData", "version"))[0].data,
|
|
527
|
-
"success": 0
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
log.debug("Sent:");
|
|
531
|
-
log.debug(msg);
|
|
532
|
-
return msg;
|
|
533
|
-
}
|
|
534
|
-
__name(getStatus, "getStatus");
|
|
535
|
-
async function getRandom(ctx, session, min, max) {
|
|
536
|
-
const log = ctx.logger("random");
|
|
537
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
538
|
-
const time = getHongKongTime();
|
|
539
|
-
let msg;
|
|
540
|
-
let data;
|
|
541
|
-
if (min == void 0 || max == void 0) {
|
|
542
|
-
min = 0;
|
|
543
|
-
max = 1e4;
|
|
544
|
-
}
|
|
545
|
-
min = Math.ceil(min);
|
|
546
|
-
max = Math.floor(max);
|
|
547
|
-
data = Math.floor(Math.random() * (max - min + 1)) + min + `(${min},${max})`;
|
|
548
|
-
msg = {
|
|
549
|
-
"time": time,
|
|
550
|
-
"data": data,
|
|
551
|
-
"success": 0
|
|
552
|
-
};
|
|
553
|
-
log.debug("Sent:");
|
|
554
|
-
log.debug(msg);
|
|
555
|
-
return msg;
|
|
556
|
-
}
|
|
557
|
-
__name(getRandom, "getRandom");
|
|
558
|
-
async function getInfo(ctx, session) {
|
|
559
|
-
const log = ctx.logger("info");
|
|
560
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
561
|
-
const time = getHongKongTime();
|
|
562
|
-
let msg;
|
|
563
|
-
let data = await readInfo(ctx);
|
|
564
|
-
if (typeof data == "string") {
|
|
565
|
-
log.error("Error:", data);
|
|
566
|
-
msg = {
|
|
567
|
-
"time": time,
|
|
568
|
-
"data": data,
|
|
569
|
-
"error": "读取信息失败。",
|
|
570
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
571
|
-
"success": 1
|
|
572
|
-
};
|
|
573
|
-
} else {
|
|
574
|
-
msg = {
|
|
575
|
-
"time": time,
|
|
576
|
-
...data,
|
|
577
|
-
"success": 0
|
|
578
|
-
};
|
|
579
|
-
}
|
|
580
|
-
log.debug("Sent:");
|
|
581
|
-
log.debug(msg);
|
|
582
|
-
return msg;
|
|
583
|
-
}
|
|
584
|
-
__name(getInfo, "getInfo");
|
|
585
|
-
async function getRandomWord(ctx, session) {
|
|
586
|
-
const log = ctx.logger("rw");
|
|
587
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
588
|
-
let msg;
|
|
589
|
-
const time = getHongKongTime();
|
|
590
|
-
if (ctx.config.rwAPI == void 0) {
|
|
591
|
-
msg = {
|
|
592
|
-
"time": time,
|
|
593
|
-
"error": session.text("noApi"),
|
|
594
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
595
|
-
"success": 2
|
|
596
|
-
};
|
|
597
|
-
log.warn("Sent:");
|
|
598
|
-
log.warn(msg);
|
|
599
|
-
return msg;
|
|
600
471
|
}
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
log
|
|
604
|
-
msg
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
err = response.isJson ? response.error["data"] : response.error;
|
|
472
|
+
// 指令 Status
|
|
473
|
+
async status() {
|
|
474
|
+
const { ctx, session, log, time } = this;
|
|
475
|
+
let msg;
|
|
476
|
+
const vMsg = await getSystemUsage();
|
|
477
|
+
if (vMsg["success"] == 1) {
|
|
478
|
+
log.error(vMsg);
|
|
479
|
+
msg = {
|
|
480
|
+
time,
|
|
481
|
+
data: vMsg["data"],
|
|
482
|
+
error: session.text(".error"),
|
|
483
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
484
|
+
success: 1
|
|
485
|
+
};
|
|
616
486
|
} else {
|
|
617
|
-
|
|
487
|
+
const msgCount = await getMsgCount(ctx);
|
|
488
|
+
msg = {
|
|
489
|
+
time,
|
|
490
|
+
name: vMsg["name"],
|
|
491
|
+
cpu: vMsg["cpu"],
|
|
492
|
+
memory: vMsg["memory"],
|
|
493
|
+
online: formatTimestampDiff(
|
|
494
|
+
Number((await ctx.database.get("botData", "uptime"))[0].data),
|
|
495
|
+
Number(session.event.timestamp.toString().substring(0, 10))
|
|
496
|
+
),
|
|
497
|
+
msgCount: `${msgCount["receive"]}/${msgCount["send"]}`,
|
|
498
|
+
version: (await ctx.database.get("botData", "version"))[0].data,
|
|
499
|
+
success: 0
|
|
500
|
+
};
|
|
618
501
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
623
|
-
"success": 1
|
|
624
|
-
};
|
|
625
|
-
log.warn("Sent:");
|
|
626
|
-
log.warn(msg);
|
|
627
|
-
}
|
|
628
|
-
return msg;
|
|
629
|
-
}
|
|
630
|
-
__name(getRandomWord, "getRandomWord");
|
|
631
|
-
async function getBlueArchive(ctx, session) {
|
|
632
|
-
const log = ctx.logger("ba");
|
|
633
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
634
|
-
if (ctx.config.baAPI == void 0) {
|
|
635
|
-
await session.send(session.text(".msg", { "quote": import_koishi2.h.quote(session.messageId), "image": session.text("noApi") }));
|
|
636
|
-
return 1;
|
|
502
|
+
log.debug("Sent:");
|
|
503
|
+
log.debug(msg);
|
|
504
|
+
return msg;
|
|
637
505
|
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
__name(getBlueArchive, "getBlueArchive");
|
|
647
|
-
async function centerServerTest(ctx, session) {
|
|
648
|
-
const log = ctx.logger("centerServerTest");
|
|
649
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
650
|
-
const time = getHongKongTime();
|
|
651
|
-
let msg;
|
|
652
|
-
let list = "";
|
|
653
|
-
const timeFormatter = new Intl.DateTimeFormat("zh-CN", {
|
|
654
|
-
timeZone: "Asia/Shanghai",
|
|
655
|
-
year: "numeric",
|
|
656
|
-
month: "2-digit",
|
|
657
|
-
day: "2-digit",
|
|
658
|
-
hour: "2-digit",
|
|
659
|
-
minute: "2-digit",
|
|
660
|
-
second: "2-digit",
|
|
661
|
-
hour12: false
|
|
662
|
-
});
|
|
663
|
-
const response = await request("https://status.scpslgame.com/api/status-page/heartbeat/nw", {}, ctx.config.timeout, log);
|
|
664
|
-
if (response.success) {
|
|
665
|
-
log.debug(response.data);
|
|
666
|
-
for (const server of ctx.config.slTest) {
|
|
667
|
-
const lastTime = response.data.heartbeatList[server.id].at(-1);
|
|
668
|
-
if (lastTime) {
|
|
669
|
-
const uptime24 = (response.data.uptimeList[server.id + "_24"] * 100).toFixed(2) + "%";
|
|
670
|
-
const status2 = lastTime?.status == 1 ? session.text(".statusLive") : session.text(".statusDie");
|
|
671
|
-
const testTime = timeFormatter.format(/* @__PURE__ */ new Date(lastTime?.time.replace(" ", "T") + "Z"));
|
|
672
|
-
list = list + "\n" + session.text(session?.bot.adapterName == "qq" ? ".list-md" : ".list", {
|
|
673
|
-
"name": server.name,
|
|
674
|
-
"status": status2,
|
|
675
|
-
"uptime": uptime24,
|
|
676
|
-
"time": testTime
|
|
677
|
-
});
|
|
678
|
-
} else {
|
|
679
|
-
list = list + "\n" + session.text(session?.bot.adapterName == "qq" ? ".listFailed-md" : ".listFailed", {
|
|
680
|
-
"name": server.name,
|
|
681
|
-
"data": session.text(".dataFail")
|
|
682
|
-
});
|
|
683
|
-
}
|
|
506
|
+
// 指令 Random
|
|
507
|
+
async random(min, max) {
|
|
508
|
+
const { log, time } = this;
|
|
509
|
+
let msg;
|
|
510
|
+
let data;
|
|
511
|
+
if (min == void 0 || max == void 0) {
|
|
512
|
+
min = 0;
|
|
513
|
+
max = 1e4;
|
|
684
514
|
}
|
|
515
|
+
min = Math.ceil(min);
|
|
516
|
+
max = Math.floor(max);
|
|
517
|
+
data = Math.floor(Math.random() * (max - min + 1)) + min + `(${min},${max})`;
|
|
685
518
|
msg = {
|
|
686
|
-
|
|
687
|
-
|
|
519
|
+
time,
|
|
520
|
+
data,
|
|
521
|
+
success: 0
|
|
688
522
|
};
|
|
689
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
690
|
-
content: session?.text(".msg-md", msg.data)
|
|
691
|
-
}) : session?.text(".msg", msg.data));
|
|
692
523
|
log.debug("Sent:");
|
|
693
524
|
log.debug(msg);
|
|
694
|
-
return
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
525
|
+
return msg;
|
|
526
|
+
}
|
|
527
|
+
// 指令 Info
|
|
528
|
+
async info() {
|
|
529
|
+
const { ctx, session, log, time } = this;
|
|
530
|
+
let msg;
|
|
531
|
+
let data = await readInfo(ctx);
|
|
532
|
+
if (typeof data == "string") {
|
|
533
|
+
log.error("Error:", data);
|
|
534
|
+
msg = {
|
|
535
|
+
time,
|
|
536
|
+
data,
|
|
537
|
+
error: session.text(".error"),
|
|
538
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
539
|
+
success: 1
|
|
540
|
+
};
|
|
699
541
|
} else {
|
|
700
|
-
|
|
542
|
+
msg = {
|
|
543
|
+
time,
|
|
544
|
+
...data,
|
|
545
|
+
success: 0
|
|
546
|
+
};
|
|
701
547
|
}
|
|
702
|
-
msg = {
|
|
703
|
-
"data": { "error": "查看失败:" + err, "time": time },
|
|
704
|
-
"success": ".failed"
|
|
705
|
-
};
|
|
706
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
707
|
-
content: session?.text("failed-md", msg.data)
|
|
708
|
-
}) : session?.text("failed", msg.data));
|
|
709
|
-
log.warn("Sent:");
|
|
710
|
-
log.warn(msg);
|
|
711
|
-
return 1;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
__name(centerServerTest, "centerServerTest");
|
|
715
|
-
async function getMeme(ctx, session, count) {
|
|
716
|
-
const log = ctx.logger("getMeme");
|
|
717
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
718
|
-
let msg;
|
|
719
|
-
const time = getHongKongTime();
|
|
720
|
-
if (ctx.config.memesAPI[`${session.event.guild?.id}`] == void 0) {
|
|
721
|
-
msg = {
|
|
722
|
-
"time": time,
|
|
723
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
724
|
-
"error": "此指令不允许在本群使用。"
|
|
725
|
-
};
|
|
726
|
-
log.warn("Sent:");
|
|
727
|
-
log.warn(msg);
|
|
728
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
729
|
-
content: session?.text("failed-md", msg)
|
|
730
|
-
}) : session?.text("failed", msg));
|
|
731
|
-
return 0;
|
|
732
|
-
}
|
|
733
|
-
const api = count ? ctx.config.memesAPI[`${session.event.guild?.id}`] + `&type=1&count=${count}` : ctx.config.memesAPI[`${session.event.guild?.id}`];
|
|
734
|
-
const response = await request(api, {}, ctx.config.timeout, log);
|
|
735
|
-
if (response.success) {
|
|
736
|
-
msg = {
|
|
737
|
-
"time": time,
|
|
738
|
-
"title": response.data.data.title,
|
|
739
|
-
"image": import_koishi2.h.image(response.data.data.image),
|
|
740
|
-
"quote": import_koishi2.h.quote(session.messageId)
|
|
741
|
-
};
|
|
742
548
|
log.debug("Sent:");
|
|
743
549
|
log.debug(msg);
|
|
744
|
-
|
|
745
|
-
return 0;
|
|
746
|
-
} else {
|
|
747
|
-
let err;
|
|
748
|
-
if (response.code) {
|
|
749
|
-
err = response.isJson ? response.error["data"] : response.error;
|
|
750
|
-
} else {
|
|
751
|
-
err = response.error.message;
|
|
752
|
-
}
|
|
753
|
-
msg = {
|
|
754
|
-
"time": time,
|
|
755
|
-
"error": "获取失败:" + err,
|
|
756
|
-
"quote": import_koishi2.h.quote(session.messageId)
|
|
757
|
-
};
|
|
758
|
-
log.warn("Sent:");
|
|
759
|
-
log.warn(msg);
|
|
760
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
761
|
-
content: session?.text("failed-md", msg)
|
|
762
|
-
}) : session?.text("failed", msg));
|
|
763
|
-
return 0;
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
__name(getMeme, "getMeme");
|
|
767
|
-
async function getCat(ctx, session) {
|
|
768
|
-
const log = ctx.logger("cat");
|
|
769
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
770
|
-
const time = getHongKongTime();
|
|
771
|
-
if (ctx.config.catAPI == void 0) {
|
|
772
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "data": "未指定 API", "time": time }));
|
|
773
|
-
log.warn("未指定 API");
|
|
774
|
-
return 1;
|
|
550
|
+
return msg;
|
|
775
551
|
}
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
log
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
"quote": import_koishi2.h.quote(session.messageId),
|
|
787
|
-
"data": response.isJson ? "获取失败:" + response.error["error"] : "获取失败:" + response.error,
|
|
788
|
-
"time": time
|
|
552
|
+
// 指令 RW
|
|
553
|
+
async randomWord() {
|
|
554
|
+
const { ctx, session, log, time } = this;
|
|
555
|
+
let msg;
|
|
556
|
+
if (ctx.config.rwAPI == void 0) {
|
|
557
|
+
msg = {
|
|
558
|
+
time,
|
|
559
|
+
error: session.text("noApi"),
|
|
560
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
561
|
+
success: 2
|
|
789
562
|
};
|
|
790
|
-
await session?.send(session?.bot.adapterName == "qq" ? (0, import_koishi2.h)("qq:markdown", {
|
|
791
|
-
content: session?.text("failed-md", msg)
|
|
792
|
-
}) : session?.text("failed", msg));
|
|
793
563
|
log.warn("Sent:");
|
|
794
|
-
log.warn(
|
|
564
|
+
log.warn(msg);
|
|
565
|
+
return msg;
|
|
566
|
+
}
|
|
567
|
+
const response = await request(
|
|
568
|
+
ctx.config.rwAPI + "?format=json",
|
|
569
|
+
ctx,
|
|
570
|
+
{ method: "GET", timeout: ctx.config.timeout },
|
|
571
|
+
log
|
|
572
|
+
);
|
|
573
|
+
if (response.success) {
|
|
574
|
+
log.debug(response.data);
|
|
575
|
+
msg = {
|
|
576
|
+
time,
|
|
577
|
+
error: response.data.data,
|
|
578
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
579
|
+
success: 0
|
|
580
|
+
};
|
|
581
|
+
log.debug("Sent:");
|
|
582
|
+
log.debug(msg);
|
|
795
583
|
} else {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
}
|
|
584
|
+
let err;
|
|
585
|
+
if (!response.isError && response.isObj) {
|
|
586
|
+
err = response.error["data"];
|
|
587
|
+
} else if (response.isError) {
|
|
588
|
+
err = response.error.message;
|
|
589
|
+
} else {
|
|
590
|
+
err = response.error;
|
|
591
|
+
}
|
|
592
|
+
msg = {
|
|
593
|
+
time,
|
|
594
|
+
error: err,
|
|
595
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
596
|
+
success: 1
|
|
597
|
+
};
|
|
800
598
|
log.warn("Sent:");
|
|
801
|
-
log.warn(
|
|
599
|
+
log.warn(msg);
|
|
802
600
|
}
|
|
601
|
+
return msg;
|
|
803
602
|
}
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
if (ctx.config.qqAPI == void 0) {
|
|
812
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "data": "未指定 API", "time": time }));
|
|
813
|
-
log.warn("未指定 API");
|
|
814
|
-
return 1;
|
|
815
|
-
}
|
|
816
|
-
const response = await request(ctx.config.qqAPI + `?qq=${qq}`, {}, ctx.config.timeout, log);
|
|
817
|
-
if (response.success) {
|
|
818
|
-
const fullHtml = await readUserCardFile(response.data);
|
|
819
|
-
log.debug(fullHtml);
|
|
820
|
-
const page = await ctx.puppeteer.page();
|
|
821
|
-
try {
|
|
822
|
-
await page.setViewport({
|
|
823
|
-
width: 450,
|
|
824
|
-
height: 650,
|
|
825
|
-
deviceScaleFactor: 2
|
|
826
|
-
});
|
|
827
|
-
await page.setContent(fullHtml, { timeout: ctx.config.htmlTimeout, waitUntil: "networkidle0" });
|
|
828
|
-
const { width, height } = await page.evaluate(() => ({
|
|
829
|
-
width: document.body.scrollWidth,
|
|
830
|
-
height: document.body.scrollHeight
|
|
831
|
-
}));
|
|
832
|
-
await page.setViewport({ width, height, deviceScaleFactor: 2 });
|
|
833
|
-
const image = await page.screenshot({ type: "png", omitBackground: true });
|
|
834
|
-
await session.send(session.text(".msg", { "quote": import_koishi2.h.quote(session.messageId), "image": import_koishi2.h.image(image, "image/png") }));
|
|
835
|
-
} catch (err) {
|
|
836
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "time": time, "data": "图片渲染失败" }));
|
|
837
|
-
log.error("图片渲染失败:", err);
|
|
603
|
+
// 指令 BA
|
|
604
|
+
async blueArchive() {
|
|
605
|
+
const { ctx, session, log } = this;
|
|
606
|
+
if (ctx.config.baAPI == void 0) {
|
|
607
|
+
await session.send(
|
|
608
|
+
session.text(".msg", { quote: import_koishi2.h.quote(session.messageId), image: session.text("noApi") })
|
|
609
|
+
);
|
|
838
610
|
return 1;
|
|
839
|
-
} finally {
|
|
840
|
-
if (page && !page.isClosed()) await page.close();
|
|
841
|
-
}
|
|
842
|
-
log.debug("Sent: Image");
|
|
843
|
-
} else {
|
|
844
|
-
if (response.code) {
|
|
845
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "data": response.isJson ? response.error["error"] : response.error, "time": time }));
|
|
846
|
-
log.warn("Sent:");
|
|
847
|
-
log.warn(response.error);
|
|
848
|
-
} else {
|
|
849
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "data": response.error.message, "time": time }));
|
|
850
|
-
log.warn("Sent:");
|
|
851
|
-
log.warn(response.error);
|
|
852
611
|
}
|
|
612
|
+
const ms = random(0, 0, 1500);
|
|
613
|
+
const link = random(2, ctx.config.baAPI) + `?cacheBuster=${random(1, 1, 2147483647)}`;
|
|
614
|
+
log.debug(`Link: ${link}`);
|
|
615
|
+
await (0, import_koishi2.sleep)(ms);
|
|
616
|
+
const status2 = await session.send(
|
|
617
|
+
session.text(".msg", { quote: import_koishi2.h.quote(session.messageId), image: import_koishi2.h.image(link) })
|
|
618
|
+
);
|
|
619
|
+
if (!status2)
|
|
620
|
+
await session.send(
|
|
621
|
+
session.text(".msg", { quote: import_koishi2.h.quote(session.messageId), image: import_koishi2.h.image(link) })
|
|
622
|
+
);
|
|
623
|
+
return 0;
|
|
853
624
|
}
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
await session.send(session.text(".matroska", { "quote": import_koishi2.h.quote(session.messageId) }));
|
|
869
|
-
log.debug("套娃");
|
|
870
|
-
return 1;
|
|
871
|
-
}
|
|
872
|
-
const user = await session.bot.getUser(session.quote.user.id, session.channelId);
|
|
873
|
-
const msg = session.quote.content;
|
|
874
|
-
const quoteMsg = session.quote.quote?.content;
|
|
875
|
-
const quoteUser = session.quote.quote?.user?.name;
|
|
876
|
-
log.debug(msg);
|
|
877
|
-
if (!user.name || !user.avatar) {
|
|
878
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "time": time, "data": "获取用户信息失败。" }));
|
|
879
|
-
log.error("获取用户信息失败");
|
|
880
|
-
return 1;
|
|
881
|
-
}
|
|
882
|
-
const page = await ctx.puppeteer.page();
|
|
883
|
-
const html = await readUserMsgFile(user.name, user.avatar, msg, inversion, quoteUser, quoteMsg);
|
|
884
|
-
log.debug(html);
|
|
885
|
-
try {
|
|
886
|
-
await page.setViewport({
|
|
887
|
-
width: 450,
|
|
888
|
-
height: 1,
|
|
889
|
-
deviceScaleFactor: 2
|
|
625
|
+
// 指令 centerServerTest
|
|
626
|
+
async centerServerTest() {
|
|
627
|
+
const { ctx, session, log, time } = this;
|
|
628
|
+
let msg;
|
|
629
|
+
let list = "";
|
|
630
|
+
const timeFormatter = new Intl.DateTimeFormat("zh-CN", {
|
|
631
|
+
timeZone: "Asia/Shanghai",
|
|
632
|
+
year: "numeric",
|
|
633
|
+
month: "2-digit",
|
|
634
|
+
day: "2-digit",
|
|
635
|
+
hour: "2-digit",
|
|
636
|
+
minute: "2-digit",
|
|
637
|
+
second: "2-digit",
|
|
638
|
+
hour12: false
|
|
890
639
|
});
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
640
|
+
const response = await request(
|
|
641
|
+
"https://status.scpslgame.com/api/status-page/heartbeat/nw",
|
|
642
|
+
ctx,
|
|
643
|
+
{ method: "GET", timeout: ctx.config.timeout },
|
|
644
|
+
log
|
|
645
|
+
);
|
|
646
|
+
if (response.success) {
|
|
647
|
+
log.debug(response.data);
|
|
648
|
+
for (const server of ctx.config.slTest) {
|
|
649
|
+
const lastTime = response.data.heartbeatList[server.id].at(-1);
|
|
650
|
+
if (lastTime) {
|
|
651
|
+
const uptime24 = (response.data.uptimeList[server.id + "_24"] * 100).toFixed(2) + "%";
|
|
652
|
+
const status2 = lastTime?.status == 1 ? session.text(".statusLive") : session.text(".statusDie");
|
|
653
|
+
const testTime = timeFormatter.format(/* @__PURE__ */ new Date(lastTime?.time.replace(" ", "T") + "Z"));
|
|
654
|
+
list = list + "\n" + session.text(this.isQQ ? ".list-md" : ".list", {
|
|
655
|
+
name: server.name,
|
|
656
|
+
status: status2,
|
|
657
|
+
uptime: uptime24,
|
|
658
|
+
time: testTime
|
|
659
|
+
});
|
|
660
|
+
} else {
|
|
661
|
+
list = list + "\n" + session.text(this.isQQ ? ".listFailed-md" : ".listFailed", {
|
|
662
|
+
name: server.name,
|
|
663
|
+
data: session.text(".dataFail")
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
msg = {
|
|
668
|
+
data: { list, time },
|
|
669
|
+
success: ".msg"
|
|
670
|
+
};
|
|
671
|
+
await this.sendMsg(".msg", msg.data);
|
|
672
|
+
log.debug("Sent:");
|
|
673
|
+
log.debug(msg);
|
|
674
|
+
return 0;
|
|
906
675
|
} else {
|
|
907
|
-
|
|
908
|
-
|
|
676
|
+
let err;
|
|
677
|
+
if (!response.isError && response.isObj) {
|
|
678
|
+
err = response.error["data"];
|
|
679
|
+
} else if (response.isError) {
|
|
680
|
+
err = response.error.message;
|
|
681
|
+
} else {
|
|
682
|
+
err = response.error;
|
|
683
|
+
}
|
|
684
|
+
msg = {
|
|
685
|
+
data: { error: "查看失败:" + err, time },
|
|
686
|
+
success: ".failed"
|
|
687
|
+
};
|
|
688
|
+
await this.sendFailed(msg.data);
|
|
689
|
+
log.warn("Sent:");
|
|
690
|
+
log.warn(msg);
|
|
909
691
|
return 1;
|
|
910
692
|
}
|
|
911
|
-
} catch (err) {
|
|
912
|
-
await session.send(session.text(".failed", { "quote": import_koishi2.h.quote(session.messageId), "time": time, "data": "图片渲染失败" }));
|
|
913
|
-
log.error("图片渲染失败:", err);
|
|
914
|
-
return 1;
|
|
915
|
-
} finally {
|
|
916
|
-
if (page && !page.isClosed()) await page.close();
|
|
917
693
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
694
|
+
// 指令 Cat
|
|
695
|
+
async cat() {
|
|
696
|
+
const { ctx, session, log, time } = this;
|
|
697
|
+
if (ctx.config.catAPI == void 0) {
|
|
698
|
+
await session.send(
|
|
699
|
+
session.text(".failed", {
|
|
700
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
701
|
+
data: session.text("noApi"),
|
|
702
|
+
time
|
|
703
|
+
})
|
|
704
|
+
);
|
|
705
|
+
log.warn("未指定 API");
|
|
706
|
+
return 1;
|
|
928
707
|
}
|
|
929
|
-
const
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
708
|
+
const response = await request(
|
|
709
|
+
ctx.config.catAPI,
|
|
710
|
+
ctx,
|
|
711
|
+
{ method: "GET", timeout: ctx.config.timeout },
|
|
712
|
+
log
|
|
713
|
+
);
|
|
714
|
+
if (response.success) {
|
|
715
|
+
log.debug(response.data);
|
|
716
|
+
const msg = { quote: import_koishi2.h.quote(session.messageId), image: import_koishi2.h.image(response.data[0].url) };
|
|
717
|
+
await session.send(session.text(".msg", msg));
|
|
718
|
+
log.debug("Sent:");
|
|
719
|
+
log.debug(response.data[0].url);
|
|
933
720
|
} else {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
721
|
+
if (!response.isError) {
|
|
722
|
+
const msg = {
|
|
723
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
724
|
+
data: response.isObj ? "获取失败:" + response.error["error"] : "获取失败:" + response.error,
|
|
725
|
+
time
|
|
726
|
+
};
|
|
727
|
+
await this.sendFailed(msg);
|
|
728
|
+
log.warn("Sent:");
|
|
729
|
+
log.warn(response.error);
|
|
730
|
+
} else {
|
|
731
|
+
const msg = {
|
|
732
|
+
quote: import_koishi2.h.quote(session.messageId),
|
|
733
|
+
data: "获取失败:" + response.error?.message,
|
|
734
|
+
time
|
|
735
|
+
};
|
|
736
|
+
await this.sendFailed(msg);
|
|
737
|
+
log.warn("Sent:");
|
|
738
|
+
log.warn(response.error);
|
|
739
|
+
}
|
|
939
740
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
const
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
741
|
+
return 0;
|
|
742
|
+
}
|
|
743
|
+
// 定时任务 SL News(静态方法,无 session)
|
|
744
|
+
static async getNewsMsg(ctx, type) {
|
|
745
|
+
const log = ctx.logger("getNewsMsg");
|
|
746
|
+
const results = [];
|
|
747
|
+
const latestIds = [];
|
|
748
|
+
const storedIds = (await ctx.database.get("botData", "newsId"))[0]?.data?.split(",") ?? [];
|
|
749
|
+
for (const item of ctx.config.newsAPI) {
|
|
750
|
+
const rssUrl = `https://store.steampowered.com/feeds/news/app/${item.appUrl}`;
|
|
751
|
+
log.info(`获取新闻: ${item.name} -> ${rssUrl}`);
|
|
752
|
+
const response = await request(
|
|
753
|
+
rssUrl,
|
|
754
|
+
ctx,
|
|
755
|
+
{ method: "GET", timeout: ctx.config.timeout },
|
|
756
|
+
log
|
|
757
|
+
);
|
|
758
|
+
if (!response.success) {
|
|
759
|
+
log.error(`请求失败: ${item.name}`);
|
|
760
|
+
results.push({ success: false, msg: `请求 ${item.name} 新闻失败` });
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
const parsed = await parseNewsRssToHtml(response.data, log);
|
|
764
|
+
if (parsed.error || !parsed.guid) {
|
|
765
|
+
log.error(`解析失败: ${item.name}`, parsed.error);
|
|
766
|
+
results.push({ success: false, msg: `解析 ${item.name} 新闻失败` });
|
|
767
|
+
continue;
|
|
768
|
+
}
|
|
769
|
+
latestIds.push(parsed.guid);
|
|
770
|
+
if (storedIds.includes(parsed.guid) && type != 1) {
|
|
771
|
+
log.debug(`无新闻更新: ${item.name}`);
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
const db = await ctx.database.get("botData", parsed.guid);
|
|
775
|
+
let html;
|
|
776
|
+
if (db[0]) {
|
|
777
|
+
html = db[0].data;
|
|
778
|
+
} else {
|
|
779
|
+
html = parsed.data;
|
|
780
|
+
await ctx.database.upsert("botData", [{ id: parsed.guid, data: html }]);
|
|
781
|
+
}
|
|
782
|
+
const page = await ctx.puppeteer.page();
|
|
783
|
+
try {
|
|
784
|
+
await page.setViewport({
|
|
785
|
+
width: 800,
|
|
786
|
+
height: 800,
|
|
787
|
+
deviceScaleFactor: 2
|
|
788
|
+
});
|
|
789
|
+
await page.setContent(html, {
|
|
790
|
+
timeout: ctx.config.htmlTimeout,
|
|
791
|
+
waitUntil: "networkidle0"
|
|
792
|
+
});
|
|
793
|
+
const { width, height } = await page.evaluate(() => ({
|
|
794
|
+
width: document.body.scrollWidth,
|
|
795
|
+
height: document.body.scrollHeight
|
|
796
|
+
}));
|
|
797
|
+
await page.setViewport({ width, height, deviceScaleFactor: 2 });
|
|
798
|
+
const image = await page.screenshot({
|
|
799
|
+
type: "png",
|
|
800
|
+
fullPage: true,
|
|
801
|
+
omitBackground: true
|
|
802
|
+
});
|
|
803
|
+
results.push({
|
|
804
|
+
success: true,
|
|
805
|
+
data: image,
|
|
806
|
+
msg: `抓取到了新的 Steam 新闻!${item.name} - ${parsed.guid}`
|
|
807
|
+
});
|
|
808
|
+
} catch (err) {
|
|
809
|
+
log.error(`${item.name} 图片渲染失败:`, err);
|
|
810
|
+
results.push({ success: false, msg: `${item.name} 图片渲染失败` });
|
|
811
|
+
} finally {
|
|
812
|
+
if (page && !page.isClosed()) await page.close();
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
if (type == 0 && latestIds.length > 0) {
|
|
816
|
+
await ctx.database.upsert("botData", [{ id: "newsId", data: latestIds.join(",") }]);
|
|
969
817
|
}
|
|
970
|
-
|
|
971
|
-
return { success: false, msg: "请求 Steam API 失败" };
|
|
818
|
+
return results;
|
|
972
819
|
}
|
|
973
|
-
}
|
|
974
|
-
__name(getNewsMsg, "getNewsMsg");
|
|
975
|
-
async function getUse(ctx, session, qq, desc) {
|
|
976
|
-
const log = ctx.logger("getUse");
|
|
977
|
-
log.debug(`Got: {"form":"${session.platform}:${session.event.guild?.id}","user":"${session.event.user?.id}","timestamp":${session.event.timestamp},"messageId":"${session.event.message?.id}"}`);
|
|
978
|
-
await session.send(session.text(".msg", { "at": import_koishi2.h.at(session.event.user?.id), "at2": import_koishi2.h.at(qq), "desc": desc ?? "使用" }));
|
|
979
|
-
return 0;
|
|
980
|
-
}
|
|
981
|
-
__name(getUse, "getUse");
|
|
820
|
+
};
|
|
982
821
|
|
|
983
822
|
// package.json
|
|
984
|
-
var version = "
|
|
823
|
+
var version = "3.0.0";
|
|
985
824
|
|
|
986
|
-
// src/
|
|
987
|
-
var
|
|
825
|
+
// src/config.ts
|
|
826
|
+
var import_koishi3 = require("koishi");
|
|
988
827
|
var name = "node-async-bot-all";
|
|
989
828
|
var usage = "这是一个私有插件。";
|
|
990
829
|
var Config = import_koishi3.Schema.intersect([
|
|
@@ -1012,211 +851,246 @@ var Config = import_koishi3.Schema.intersect([
|
|
|
1012
851
|
import_koishi3.Schema.object({
|
|
1013
852
|
baAPI: import_koishi3.Schema.array(String).default(["https://rba.kanostar.top/portrait"]).description("随机BA图 API")
|
|
1014
853
|
}).description("随机BA图"),
|
|
1015
|
-
import_koishi3.Schema.object({
|
|
1016
|
-
steamAPI: import_koishi3.Schema.string().default("https://api.tasaed.top/get/steamid/").description("转换 Steam ID API")
|
|
1017
|
-
}).description("转换 Steam ID"),
|
|
1018
|
-
import_koishi3.Schema.object({
|
|
1019
|
-
memesAPI: import_koishi3.Schema.dict(String).role("table").description("群友 meme API")
|
|
1020
|
-
}).description("群友 meme"),
|
|
1021
854
|
import_koishi3.Schema.object({
|
|
1022
855
|
catAPI: import_koishi3.Schema.string().default("https://api.thecatapi.com/v1/images/search").description("随机猫猫图 API")
|
|
1023
856
|
}).description("随机猫猫图"),
|
|
1024
857
|
import_koishi3.Schema.object({
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
858
|
+
steamNews: import_koishi3.Schema.array(String).default([""]).description("{platform}:{channelId}"),
|
|
859
|
+
newsAPI: import_koishi3.Schema.array(
|
|
860
|
+
import_koishi3.Schema.object({
|
|
861
|
+
name: import_koishi3.Schema.string().description("新闻抓取的 App 名称,随便写"),
|
|
862
|
+
appUrl: import_koishi3.Schema.string().description(
|
|
863
|
+
"新闻抓取的 AppId URL,可加参数,如 3629270/?l=schinese"
|
|
864
|
+
)
|
|
865
|
+
})
|
|
866
|
+
).default([{ name: "SCP SL", appUrl: "700330/?l=schinese" }]).description("新闻抓取配置")
|
|
867
|
+
}).description("Steam 新闻抓取列表"),
|
|
1031
868
|
import_koishi3.Schema.object({
|
|
1032
869
|
specialMsg: import_koishi3.Schema.array(String).default([]).description("特殊消息"),
|
|
1033
870
|
reactionId: import_koishi3.Schema.array(Number).default([]).description("回应表情 ID")
|
|
1034
|
-
}).description("特殊消息回应")
|
|
1035
|
-
import_koishi3.Schema.object({
|
|
1036
|
-
slTest: import_koishi3.Schema.array(import_koishi3.Schema.object({
|
|
1037
|
-
id: import_koishi3.Schema.string().description("服务器 ID"),
|
|
1038
|
-
name: import_koishi3.Schema.string().description("服务器 名称")
|
|
1039
|
-
})).default([{ "id": "1", "name": "中心 鲁贝 1" }, { "id": "19", "name": "中心 斯特拉斯堡 1" }, { "id": "3", "name": "Steam 认证 API" }]).description("测试中心服务器")
|
|
1040
|
-
}).description("测试中心服务器")
|
|
871
|
+
}).description("特殊消息回应")
|
|
1041
872
|
]).description("基础设置");
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
__name(startReaction, "startReaction");
|
|
1046
|
-
async function endReaction(session) {
|
|
1047
|
-
if (session.bot.deleteReaction) await session.bot.deleteReaction(session.channelId, session.messageId, `face|424`);
|
|
1048
|
-
if (session.bot.createReaction) await session.bot.createReaction(session.channelId, session.messageId, `face|144`);
|
|
1049
|
-
}
|
|
1050
|
-
__name(endReaction, "endReaction");
|
|
1051
|
-
async function endReactionFailed(session) {
|
|
1052
|
-
if (session.bot.deleteReaction) await session.bot.deleteReaction(session.channelId, session.messageId, `face|424`);
|
|
1053
|
-
if (session.bot.createReaction) await session.bot.createReaction(session.channelId, session.messageId, `face|38`);
|
|
1054
|
-
}
|
|
1055
|
-
__name(endReactionFailed, "endReactionFailed");
|
|
873
|
+
|
|
874
|
+
// src/index.ts
|
|
875
|
+
var inject = ["database", "installer", "puppeteer", "cron"];
|
|
1056
876
|
function apply(ctx) {
|
|
1057
877
|
ctx.i18n.define("zh-CN", require_zh_CN());
|
|
1058
878
|
ctx.on("ready", async () => {
|
|
1059
|
-
|
|
879
|
+
const naBot = new NodeAsyncBot();
|
|
880
|
+
await naBot.init(ctx);
|
|
881
|
+
await naBot.registerNews();
|
|
882
|
+
await naBot.registerCommand();
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
__name(apply, "apply");
|
|
886
|
+
var NodeAsyncBot = class {
|
|
887
|
+
static {
|
|
888
|
+
__name(this, "NodeAsyncBot");
|
|
889
|
+
}
|
|
890
|
+
_ctx;
|
|
891
|
+
_botData;
|
|
892
|
+
_na;
|
|
893
|
+
_registeredNews = false;
|
|
894
|
+
_registeredCommand = false;
|
|
895
|
+
get ctx() {
|
|
896
|
+
if (!this._ctx) throw new Error("未初始化");
|
|
897
|
+
return this._ctx;
|
|
898
|
+
}
|
|
899
|
+
set ctx(value) {
|
|
900
|
+
this._ctx = value;
|
|
901
|
+
}
|
|
902
|
+
get botData() {
|
|
903
|
+
if (!this._botData) throw new Error("未初始化");
|
|
904
|
+
return this._botData;
|
|
905
|
+
}
|
|
906
|
+
set botData(value) {
|
|
907
|
+
this._botData = value;
|
|
908
|
+
}
|
|
909
|
+
get na() {
|
|
910
|
+
if (!this._na) throw new Error("未初始化");
|
|
911
|
+
return this._na;
|
|
912
|
+
}
|
|
913
|
+
set na(value) {
|
|
914
|
+
this._na = value;
|
|
915
|
+
}
|
|
916
|
+
async init(ct) {
|
|
917
|
+
this.ctx = ct;
|
|
918
|
+
const date = /* @__PURE__ */ new Date();
|
|
919
|
+
this.botData = {
|
|
920
|
+
version,
|
|
921
|
+
uptime: date.getTime().toString().substring(0, 10)
|
|
922
|
+
};
|
|
923
|
+
this.ctx.model.extend("botData", {
|
|
1060
924
|
// 向表中注入字符串
|
|
1061
925
|
id: "string",
|
|
1062
926
|
data: "string"
|
|
1063
927
|
});
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
{ id: "
|
|
1067
|
-
{ id: "version", data: version }
|
|
928
|
+
await this.ctx.database.upsert("botData", [
|
|
929
|
+
{ id: "uptime", data: this.botData.uptime },
|
|
930
|
+
{ id: "version", data: this.botData.version }
|
|
1068
931
|
]);
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
932
|
+
this.na = this.ctx.command("na");
|
|
933
|
+
}
|
|
934
|
+
// reaction 辅助方法
|
|
935
|
+
async startReaction(session) {
|
|
936
|
+
if (session.bot.createReaction)
|
|
937
|
+
await session.bot.createReaction(
|
|
938
|
+
session.channelId,
|
|
939
|
+
session.messageId,
|
|
940
|
+
`face|424`
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
async endReaction(session) {
|
|
944
|
+
if (session.bot.deleteReaction)
|
|
945
|
+
await session.bot.deleteReaction(
|
|
946
|
+
session.channelId,
|
|
947
|
+
session.messageId,
|
|
948
|
+
`face|424`
|
|
949
|
+
);
|
|
950
|
+
if (session.bot.createReaction)
|
|
951
|
+
await session.bot.createReaction(
|
|
952
|
+
session.channelId,
|
|
953
|
+
session.messageId,
|
|
954
|
+
`face|144`
|
|
955
|
+
);
|
|
956
|
+
}
|
|
957
|
+
async endReactionFailed(session) {
|
|
958
|
+
if (session.bot.deleteReaction)
|
|
959
|
+
await session.bot.deleteReaction(
|
|
960
|
+
session.channelId,
|
|
961
|
+
session.messageId,
|
|
962
|
+
`face|424`
|
|
963
|
+
);
|
|
964
|
+
if (session.bot.createReaction)
|
|
965
|
+
await session.bot.createReaction(
|
|
966
|
+
session.channelId,
|
|
967
|
+
session.messageId,
|
|
968
|
+
`face|38`
|
|
969
|
+
);
|
|
970
|
+
}
|
|
971
|
+
// 执行指令的通用流程:reaction + 命令执行
|
|
972
|
+
async execCommand(session, loggerName, fn) {
|
|
973
|
+
const handler = new CommandHandler(this.ctx, session, loggerName);
|
|
974
|
+
await this.startReaction(session);
|
|
975
|
+
const result = await fn(handler);
|
|
976
|
+
if (result === 0 || result === void 0) {
|
|
977
|
+
await this.endReaction(session);
|
|
1093
978
|
} else {
|
|
1094
|
-
|
|
1095
|
-
await ctx.broadcast(ctx.config.slNews, outMsg.msg);
|
|
979
|
+
await this.endReactionFailed(session);
|
|
1096
980
|
}
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
981
|
+
}
|
|
982
|
+
async registerNews() {
|
|
983
|
+
if (this._registeredNews) return;
|
|
984
|
+
this._registeredNews = true;
|
|
985
|
+
this.na.subcommand("steamNews").action(async ({ session }) => {
|
|
986
|
+
const log = this.ctx.logger("steamNews");
|
|
987
|
+
const results = await CommandHandler.getNewsMsg(this.ctx, 1);
|
|
988
|
+
for (const outMsg of results) {
|
|
989
|
+
if (outMsg.data) {
|
|
990
|
+
await session?.send(`${outMsg.msg}
|
|
991
|
+
${import_koishi4.h.image(outMsg.data, "image/png")}`);
|
|
992
|
+
} else {
|
|
993
|
+
log.error(outMsg);
|
|
994
|
+
await session?.send(outMsg.msg);
|
|
995
|
+
}
|
|
1102
996
|
}
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
await
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
}
|
|
1146
|
-
await
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
}
|
|
1178
|
-
await
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
}
|
|
1197
|
-
await getQQInfo(ctx, session, qq);
|
|
1198
|
-
await endReaction(session);
|
|
1199
|
-
});
|
|
1200
|
-
na.subcommand("msg2img").option("inversion", "-i").alias("消息转图").alias("m").action(async ({ session, options }) => {
|
|
1201
|
-
await startReaction(session);
|
|
1202
|
-
await getMsg(ctx, session, options?.inversion);
|
|
1203
|
-
await endReaction(session);
|
|
1204
|
-
});
|
|
1205
|
-
na.subcommand("use <user:user> [方法:string]").alias("u").action(async ({ session }, user, desc) => {
|
|
1206
|
-
await startReaction(session);
|
|
1207
|
-
const qq = user?.split(":")?.[1];
|
|
1208
|
-
if (qq == void 0 || isNaN(Number(qq))) {
|
|
1209
|
-
await endReactionFailed(session);
|
|
1210
|
-
return session?.text(".command");
|
|
1211
|
-
}
|
|
1212
|
-
await getUse(ctx, session, qq, desc);
|
|
1213
|
-
await endReaction(session);
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
__name(apply, "apply");
|
|
997
|
+
});
|
|
998
|
+
this.ctx.cron("0 * * * *", async () => {
|
|
999
|
+
this.ctx.emit("node-async/news");
|
|
1000
|
+
});
|
|
1001
|
+
this.ctx.cron("30 * * * *", async () => {
|
|
1002
|
+
this.ctx.emit("node-async/news");
|
|
1003
|
+
});
|
|
1004
|
+
this.ctx.on("node-async/news", async () => {
|
|
1005
|
+
const results = await CommandHandler.getNewsMsg(this.ctx, 0);
|
|
1006
|
+
if (results.length === 0) return;
|
|
1007
|
+
for (const outMsg of results) {
|
|
1008
|
+
if (outMsg.data) {
|
|
1009
|
+
await this.ctx.broadcast(
|
|
1010
|
+
this.ctx.config.steamNews,
|
|
1011
|
+
`${outMsg.msg}
|
|
1012
|
+
${import_koishi4.h.image(outMsg.data, "image/png")}`
|
|
1013
|
+
);
|
|
1014
|
+
} else {
|
|
1015
|
+
await this.ctx.broadcast(this.ctx.config.steamNews, outMsg.msg);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
});
|
|
1019
|
+
this.ctx.on("message", async (session) => {
|
|
1020
|
+
if (session.bot.createReaction) {
|
|
1021
|
+
for (const content of this.ctx.config.specialMsg) {
|
|
1022
|
+
if (session.content === content) {
|
|
1023
|
+
await session.bot.createReaction(
|
|
1024
|
+
session.channelId,
|
|
1025
|
+
session.messageId,
|
|
1026
|
+
`face|${String(random(2, this.ctx.config.reactionId))}`
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
async registerCommand() {
|
|
1034
|
+
if (this._registeredCommand) return;
|
|
1035
|
+
this._registeredCommand = true;
|
|
1036
|
+
this.na.subcommand("cxGame").action(async ({ session }) => {
|
|
1037
|
+
await this.execCommand(session, "cx", (handler) => handler.server());
|
|
1038
|
+
});
|
|
1039
|
+
this.na.subcommand("status").alias("stats").alias("状态").action(async ({ session }) => {
|
|
1040
|
+
await this.execCommand(session, "status", async (handler) => {
|
|
1041
|
+
const status2 = await handler.status();
|
|
1042
|
+
await session?.send(
|
|
1043
|
+
session?.bot.adapterName == "qq" ? (0, import_koishi4.h)("qq:markdown", {
|
|
1044
|
+
content: session?.text(status2["success"] == 0 ? ".msg-md" : "failed-md", status2)
|
|
1045
|
+
}) : session?.text(status2["success"] == 0 ? ".msg" : "failed", status2)
|
|
1046
|
+
);
|
|
1047
|
+
return status2["success"] == 0 ? 0 : 1;
|
|
1048
|
+
});
|
|
1049
|
+
});
|
|
1050
|
+
this.na.subcommand("random [最小数:number] [最大数:number]").alias("随机数").action(async ({ session }, min, max) => {
|
|
1051
|
+
await this.execCommand(session, "random", async (handler) => {
|
|
1052
|
+
const random2 = await handler.random(min, max);
|
|
1053
|
+
await session?.send(
|
|
1054
|
+
session?.bot.adapterName == "qq" ? (0, import_koishi4.h)("qq:markdown", {
|
|
1055
|
+
content: session?.text(".msg-md", random2)
|
|
1056
|
+
}) : session?.text(".msg", random2)
|
|
1057
|
+
);
|
|
1058
|
+
});
|
|
1059
|
+
});
|
|
1060
|
+
this.na.subcommand("info").action(async ({ session }) => {
|
|
1061
|
+
await this.execCommand(session, "info", async (handler) => {
|
|
1062
|
+
const info = await handler.info();
|
|
1063
|
+
await session?.send(
|
|
1064
|
+
session?.bot.adapterName == "qq" ? (0, import_koishi4.h)("qq:markdown", {
|
|
1065
|
+
content: session?.text(info["success"] == 0 ? ".msg-md" : "failed-md", info)
|
|
1066
|
+
}) : session?.text(info["success"] == 0 ? ".msg" : "failed", info)
|
|
1067
|
+
);
|
|
1068
|
+
return info["success"] == 0 ? 0 : 1;
|
|
1069
|
+
});
|
|
1070
|
+
});
|
|
1071
|
+
this.na.subcommand("rw").action(async ({ session }) => {
|
|
1072
|
+
await this.execCommand(session, "rw", async (handler) => {
|
|
1073
|
+
const rw = await handler.randomWord();
|
|
1074
|
+
await session?.send(
|
|
1075
|
+
session?.bot.adapterName == "qq" ? (0, import_koishi4.h)("qq:markdown", {
|
|
1076
|
+
content: session?.text(rw["success"] == 0 ? "failed-md" : "failed-md", rw)
|
|
1077
|
+
}) : session?.text(rw["success"] == 0 ? "failed" : "failed", rw)
|
|
1078
|
+
);
|
|
1079
|
+
return rw["success"] == 0 ? 0 : 1;
|
|
1080
|
+
});
|
|
1081
|
+
});
|
|
1082
|
+
this.na.subcommand("randomBA").alias("随机ba图").action(async ({ session }) => {
|
|
1083
|
+
await this.execCommand(session, "ba", (handler) => handler.blueArchive());
|
|
1084
|
+
});
|
|
1085
|
+
this.na.subcommand("randomCat").alias("随机猫猫图").alias("随机猫猫").action(async ({ session }) => {
|
|
1086
|
+
await this.execCommand(session, "cat", (handler) => handler.cat());
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1217
1090
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1218
1091
|
0 && (module.exports = {
|
|
1219
1092
|
Config,
|
|
1093
|
+
NodeAsyncBot,
|
|
1220
1094
|
apply,
|
|
1221
1095
|
inject,
|
|
1222
1096
|
name,
|