koishi-plugin-nmc-radar 1.3.2 → 1.4.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/lib/index.d.ts +2 -2
- package/lib/index.js +40 -18
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -6,9 +6,9 @@ export declare const inject: {
|
|
|
6
6
|
};
|
|
7
7
|
interface Product {
|
|
8
8
|
url: string;
|
|
9
|
-
|
|
9
|
+
slug: string;
|
|
10
10
|
}
|
|
11
|
-
type Resolver = (products: Product[],
|
|
11
|
+
type Resolver = (products: Product[], options: Dict) => Awaitable<h>;
|
|
12
12
|
declare const resolvers: Record<string, Resolver>;
|
|
13
13
|
export interface Config {
|
|
14
14
|
defaultResolver: keyof typeof resolvers;
|
package/lib/index.js
CHANGED
|
@@ -36,8 +36,10 @@ __export(src_exports, {
|
|
|
36
36
|
name: () => name
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(src_exports);
|
|
39
|
+
var import_node_buffer = require("node:buffer");
|
|
39
40
|
var import_promises = require("node:fs/promises");
|
|
40
41
|
var import_node_path = __toESM(require("node:path"));
|
|
42
|
+
var import_node_url = require("node:url");
|
|
41
43
|
var import_jsdom = require("jsdom");
|
|
42
44
|
var import_koishi = require("koishi");
|
|
43
45
|
|
|
@@ -332,36 +334,56 @@ var Config = import_koishi.Schema.object({
|
|
|
332
334
|
defaultResolver: import_koishi.Schema.union(Object.keys(resolvers)).default("img").description("默认输出类型。")
|
|
333
335
|
});
|
|
334
336
|
function apply(ctx, config) {
|
|
335
|
-
const command = ctx.command("radar <name:string>", "查看雷达图"
|
|
337
|
+
const command = ctx.command("radar <name:string>", "查看雷达图").alias("雷达").option("name", "--name <name:string> 雷达站名称").option("count", "-n <count:number> 最大输出数量").option("reverse", "-R 反转顺序").option("type", "--type <type:string> 输出类型", { type: Object.keys(resolvers) }).option("type", "--img 输出图片", { value: "img" }).option("type", "--url 输出 URL", { value: "url" }).action(async ({ session, options = {} }, name2) => {
|
|
338
|
+
options.name ??= name2;
|
|
336
339
|
if (!(name2 in radars_default))
|
|
337
340
|
return void session?.send("雷达站不存在,可使用 radar.list 查看所有雷达站。");
|
|
338
|
-
const url = radars_default[
|
|
341
|
+
const url = radars_default[options.name];
|
|
339
342
|
const { window: { document } } = new import_jsdom.JSDOM(await ctx.http.get(url));
|
|
340
343
|
const nodes = document.querySelectorAll("div[data-img]");
|
|
341
344
|
options.type ??= config.defaultResolver;
|
|
342
345
|
options.count ??= options.type === "img" ? 1 : void 0;
|
|
343
346
|
const products = Array.from(nodes).slice(0, options.count).map((node) => ({
|
|
344
347
|
url: node.dataset.img,
|
|
345
|
-
|
|
346
|
-
// MM/DD HH:mm
|
|
348
|
+
slug: node.dataset.time.replaceAll(/[/ :]/g, "")
|
|
347
349
|
}));
|
|
348
350
|
options.reverse || products.reverse();
|
|
349
|
-
return await resolvers[options.type](products,
|
|
351
|
+
return await resolvers[options.type](products, options);
|
|
350
352
|
});
|
|
351
353
|
ctx.inject(["ffmpeg"], async (ctx2) => {
|
|
352
|
-
command.option("type", "--gif 输出 GIF 动画", { value: "gif" }).option("fps", "--fps <fps:number> 帧率", { fallback: 10 });
|
|
353
|
-
resolvers.gif = async (products,
|
|
354
|
-
const baseDir = import_node_path.default.join(ctx2.baseDir, "
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
await (0, import_promises.
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
354
|
+
command.option("type", "--gif 输出 GIF 动画", { value: "gif" }).option("fps", "--fps <fps:number> 帧率", { fallback: 10 }).option("loop", "--loop <loop:number> 循环次数", { fallback: -1 });
|
|
355
|
+
resolvers.gif = async (products, options) => {
|
|
356
|
+
const baseDir = import_node_path.default.join(ctx2.baseDir, "cache", name, options.name);
|
|
357
|
+
const outputPath = import_node_path.default.join(baseDir, [
|
|
358
|
+
`${products[0].slug}+${products[products.length - 1].slug}`,
|
|
359
|
+
`#${options.fps}@${options.loop}.gif`
|
|
360
|
+
].join(""));
|
|
361
|
+
try {
|
|
362
|
+
await (0, import_promises.access)(outputPath);
|
|
363
|
+
} catch {
|
|
364
|
+
await (0, import_promises.mkdir)(baseDir, { recursive: true });
|
|
365
|
+
const filePaths = await Promise.all(products.map(async ({ url, slug }) => {
|
|
366
|
+
const filePath = import_node_path.default.join(baseDir, `${slug}.png`);
|
|
367
|
+
try {
|
|
368
|
+
await (0, import_promises.access)(filePath);
|
|
369
|
+
} catch {
|
|
370
|
+
try {
|
|
371
|
+
const response = await ctx2.http.get(url, { responseType: "stream" });
|
|
372
|
+
await (0, import_promises.writeFile)(filePath, response);
|
|
373
|
+
} catch {
|
|
374
|
+
return void await (0, import_promises.unlink)(filePath);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return filePath;
|
|
378
|
+
}));
|
|
379
|
+
const buffer = filePaths.filter(Boolean).flatMap((filePath) => `file '${filePath.replaceAll("\\", "/")}'`).join("\n");
|
|
380
|
+
await ctx2.ffmpeg.builder().input(import_node_buffer.Buffer.from(buffer)).inputOption("-f", "concat").inputOption("-safe", "0").inputOption("-protocol_whitelist", "file,fd").inputOption("-r", options.fps).outputOption("-loop", options.loop).outputOption("-filter_complex", [
|
|
381
|
+
"[0:v]split[out1][out2]",
|
|
382
|
+
"[out1]palettegen[p]",
|
|
383
|
+
"[out2][p]paletteuse"
|
|
384
|
+
].join(";")).run("file", outputPath);
|
|
385
|
+
}
|
|
386
|
+
return import_koishi.h.img((0, import_node_url.pathToFileURL)(outputPath).href);
|
|
365
387
|
};
|
|
366
388
|
});
|
|
367
389
|
command.subcommand(".list", "查看所有雷达站").action(() => Object.keys(radars_default).join(" "));
|