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 CHANGED
@@ -6,9 +6,9 @@ export declare const inject: {
6
6
  };
7
7
  interface Product {
8
8
  url: string;
9
- time: string;
9
+ slug: string;
10
10
  }
11
- type Resolver = (products: Product[], id: string, options: Dict) => Awaitable<h>;
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>", "查看雷达图", { checkUnknown: true }).alias("雷达").option("reverse", "-R 反转顺序").option("count", "-n <count:number> 最大输出数量").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) => {
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[name2];
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
- time: node.dataset.time
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, import_koishi.Random.id(), options);
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, id, options) => {
354
- const baseDir = import_node_path.default.join(ctx2.baseDir, "temp", name, id);
355
- await (0, import_promises.mkdir)(baseDir, { recursive: true });
356
- await Promise.all(products.map(async ({ url }, i) => {
357
- const response = await ctx2.http.get(url, { responseType: "stream" });
358
- const filename = `${String(i + 1).padStart(3, "0")}.png`;
359
- const filePath = import_node_path.default.join(baseDir, filename);
360
- await (0, import_promises.writeFile)(filePath, response);
361
- }));
362
- const outputPath = import_node_path.default.join(baseDir, "..", `${id}.gif`);
363
- await ctx2.ffmpeg.builder().input(import_node_path.default.join(baseDir, "%03d.png")).outputOption("-loop", "-1").outputOption("-r", options.fps).run("file", outputPath);
364
- return import_koishi.h.img(`file://${outputPath}`);
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(" "));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-nmc-radar",
3
- "version": "1.3.2",
3
+ "version": "1.4.1",
4
4
  "description": "气象台雷达图插件",
5
5
  "typings": "lib/index.d.ts",
6
6
  "license": "MIT",