koishi-plugin-cocoyyy-console 1.0.1 → 1.0.3

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
@@ -1,9 +1,12 @@
1
1
  import { Context, Logger, Schema } from 'koishi';
2
- import { MysqlConfig, SaveConfig } from './utils/config';
2
+ import * as my_config from './utils/config';
3
3
  export declare const name = "cocoyyy-console";
4
4
  export interface Config {
5
- mysql?: MysqlConfig;
6
- save?: SaveConfig;
5
+ function_config?: my_config.FunctionConfig;
6
+ mysql_config?: my_config.MysqlConfig;
7
+ tag_config?: my_config.SaveConfig;
8
+ repeat_config?: my_config.RepeatConfig;
9
+ rbq_config?: my_config.RbqConfig;
7
10
  }
8
11
  export declare const Config: Schema<Config>;
9
12
  export declare let logger: Logger;
package/lib/index.js CHANGED
@@ -27,16 +27,24 @@ __export(src_exports, {
27
27
  savePath: () => savePath
28
28
  });
29
29
  module.exports = __toCommonJS(src_exports);
30
- var import_koishi3 = require("koishi");
30
+ var import_koishi9 = require("koishi");
31
31
 
32
- // src/utils/config.ts
32
+ // src/utils/configs/function_config.ts
33
33
  var import_koishi = require("koishi");
34
- var MysqlConfigSchema = import_koishi.Schema.object({
35
- host: import_koishi.Schema.string().default("127.0.0.1").description("MySQL 主机地址"),
36
- port: import_koishi.Schema.number().default(3306).description("MySQL 端口"),
37
- user: import_koishi.Schema.string().default("root").description("用户名"),
38
- password: import_koishi.Schema.string().role("secret").default("").description("密码"),
39
- database: import_koishi.Schema.string().default("test").description("数据库名")
34
+ var FunctionConfigSchema = import_koishi.Schema.object({
35
+ tag_flag: import_koishi.Schema.boolean().default(true).description("标签功能是否启用"),
36
+ repeat_flag: import_koishi.Schema.boolean().default(true).description("复读功能是否启用"),
37
+ rbq_flag: import_koishi.Schema.boolean().default(true).description("*人功能是否启用")
38
+ });
39
+
40
+ // src/utils/configs/mysql_config.ts
41
+ var import_koishi2 = require("koishi");
42
+ var MysqlConfigSchema = import_koishi2.Schema.object({
43
+ host: import_koishi2.Schema.string().default("127.0.0.1").description("MySQL 主机地址"),
44
+ port: import_koishi2.Schema.number().default(3306).description("MySQL 端口"),
45
+ user: import_koishi2.Schema.string().default("root").description("用户名"),
46
+ password: import_koishi2.Schema.string().role("secret").default("").description("密码"),
47
+ database: import_koishi2.Schema.string().default("test").description("数据库名")
40
48
  });
41
49
  function loadMysqlConfigFromEnv(env = process.env) {
42
50
  return {
@@ -48,8 +56,11 @@ function loadMysqlConfigFromEnv(env = process.env) {
48
56
  };
49
57
  }
50
58
  __name(loadMysqlConfigFromEnv, "loadMysqlConfigFromEnv");
51
- var SaveConfigSchema = import_koishi.Schema.object({
52
- save_path: import_koishi.Schema.string().default("").description("保存图片路径(绝对路径)")
59
+
60
+ // src/utils/configs/tag_config.ts
61
+ var import_koishi3 = require("koishi");
62
+ var SaveConfigSchema = import_koishi3.Schema.object({
63
+ save_path: import_koishi3.Schema.string().default("").description("保存图片路径(绝对路径)")
53
64
  });
54
65
  function resolveTagBaseDir(config) {
55
66
  if (config?.save_path && config.save_path.trim().length > 0) return config.save_path;
@@ -57,6 +68,26 @@ function resolveTagBaseDir(config) {
57
68
  }
58
69
  __name(resolveTagBaseDir, "resolveTagBaseDir");
59
70
 
71
+ // src/utils/configs/repeat_config.ts
72
+ var import_koishi4 = require("koishi");
73
+ var RepeatConfigSchema = import_koishi4.Schema.object({
74
+ minTimes: import_koishi4.Schema.number().default(1).description("最小重复次数"),
75
+ probability: import_koishi4.Schema.number().default(1).description("复读概率[0-1]"),
76
+ guild_ids: import_koishi4.Schema.string().default("").description("不需要复读的群ID,多个群ID用逗号分隔"),
77
+ resetInterval: import_koishi4.Schema.number().default(60).description("过期秒数")
78
+ });
79
+
80
+ // src/utils/configs/rbq_config.ts
81
+ var import_koishi5 = require("koishi");
82
+ var RbqConfigSchema = import_koishi5.Schema.object({
83
+ configList: import_koishi5.Schema.array(import_koishi5.Schema.object({
84
+ probability: import_koishi5.Schema.number().default(1).description("触发概率[0-1]"),
85
+ guild_id: import_koishi5.Schema.string().default("").description("触发群聊id"),
86
+ uid: import_koishi5.Schema.string().default("").description("触发用户id"),
87
+ content: import_koishi5.Schema.string().default("*死你").description("触发内容")
88
+ })).description("触发配置")
89
+ });
90
+
60
91
  // src/infra/mysql_init.ts
61
92
  var import_sequelize = require("sequelize");
62
93
  var sequelize = null;
@@ -99,6 +130,7 @@ var TagsModel = class extends import_sequelize2.Model {
99
130
  id;
100
131
  tags;
101
132
  alias;
133
+ guild_id;
102
134
  status;
103
135
  createtime;
104
136
  };
@@ -123,6 +155,10 @@ function getTagsModel() {
123
155
  type: import_sequelize2.DataTypes.STRING(191),
124
156
  allowNull: true
125
157
  },
158
+ guild_id: {
159
+ type: import_sequelize2.DataTypes.STRING(191),
160
+ allowNull: false
161
+ },
126
162
  status: {
127
163
  type: import_sequelize2.DataTypes.TINYINT,
128
164
  allowNull: false,
@@ -236,57 +272,241 @@ function is_at_bot(session) {
236
272
  }
237
273
  __name(is_at_bot, "is_at_bot");
238
274
 
239
- // src/services/tag_service.ts
275
+ // src/services/menu_service.ts
276
+ var menuList = [
277
+ {
278
+ name: "tag",
279
+ description: "标签功能,用于记录黑历史",
280
+ command: "maketag [标签]"
281
+ },
282
+ {
283
+ name: "repeat",
284
+ description: "复读功能,用于复读",
285
+ command: "无"
286
+ },
287
+ {
288
+ name: "rbq",
289
+ description: "*人功能,用于*人",
290
+ command: "无"
291
+ }
292
+ ];
293
+ function getMenuList(command = null, functionConfig) {
294
+ switch (command) {
295
+ case "tag":
296
+ if (!functionConfig.tag_flag)
297
+ return "标签功能已关闭";
298
+ return getTagFuncMenu(command);
299
+ case "repeat":
300
+ if (!functionConfig.repeat_flag)
301
+ return "复读功能已关闭";
302
+ return `[所有命令都需要@bot]
303
+ 复读功能菜单:
304
+ 群内重复一定次数的消息会进行复读
305
+ 如果遇到问题请联系开发人员。`;
306
+ case "rbq":
307
+ if (!functionConfig.rbq_flag)
308
+ return "*人功能已关闭";
309
+ return `[所有命令都需要@bot]
310
+ *人功能菜单:
311
+ 联系管理人员配置群内指定用户,在群内@指定用户,会触发*人功能
312
+ 如果遇到问题请联系开发人员。`;
313
+ default:
314
+ return `[所有命令都需要@bot]
315
+ 当前可用功能列表:
316
+ ${menuList.map((item) => item.name + ": " + item.description).join("\n ")}
317
+ 输入"help 功能名"查看特定功能的指令和使用示例。`;
318
+ }
319
+ }
320
+ __name(getMenuList, "getMenuList");
321
+ var tagFuncMenuList = [
322
+ {
323
+ name: "maketag",
324
+ description: "创建一个标签",
325
+ command: "maketag [标签]"
326
+ },
327
+ {
328
+ name: "add",
329
+ description: "给标签添加图片",
330
+ command: "add [标签] [图片]"
331
+ },
332
+ {
333
+ name: "get",
334
+ description: "给标签添加图片",
335
+ command: "get [标签]"
336
+ },
337
+ {
338
+ name: "bind",
339
+ description: "标签绑定别名",
340
+ command: "bind [标签] [别名]"
341
+ },
342
+ {
343
+ name: "unbind",
344
+ description: "标签取消别名",
345
+ command: "unbind [标签] [别名]"
346
+ },
347
+ {
348
+ name: "taglist",
349
+ description: "获取标签列表",
350
+ command: "taglist"
351
+ }
352
+ ];
353
+ function getTagFuncMenu(command = null) {
354
+ return `[所有命令都需要@bot]
355
+ 标签功能菜单:
356
+ ${tagFuncMenuList.map((item) => item.command + ": " + item.description).join("\n ")}
357
+ 输入对应指令使用标签功能,如果遇到问题请联系开发人员。`;
358
+ }
359
+ __name(getTagFuncMenu, "getTagFuncMenu");
360
+ function registerMenuCommands(ctx, connected, functionConfig) {
361
+ ctx.command("help <参数>", "帮助菜单").check(({ session }) => {
362
+ if (!connected) return;
363
+ if (!is_at_bot(session)) return;
364
+ }).action(async ({ session }, ...args) => {
365
+ const command = args?.[0];
366
+ return getMenuList(command, functionConfig);
367
+ });
368
+ }
369
+ __name(registerMenuCommands, "registerMenuCommands");
370
+
371
+ // src/services/tag_func/tag_commands.ts
372
+ var import_koishi7 = require("koishi");
373
+
374
+ // src/services/tag_func/tag_service.ts
240
375
  var import_sequelize4 = require("sequelize");
241
- var import_fs = require("fs");
376
+ var import_fs2 = require("fs");
377
+ var import_path2 = require("path");
378
+
379
+ // src/services/tag_func/img_service.ts
380
+ var import_koishi6 = require("koishi");
242
381
  var import_path = require("path");
243
- async function findTagByName(name2) {
382
+ var import_fs = require("fs");
383
+ async function loadImageFromUrl(ctx, url) {
384
+ try {
385
+ const responseArrayBuffer = await ctx.http.get(url, {
386
+ responseType: "arraybuffer",
387
+ timeout: 2e4
388
+ // 设置 20 秒超时
389
+ });
390
+ return Buffer.from(responseArrayBuffer);
391
+ } catch (error) {
392
+ logger.error(`[loadImageFromUrl] Failed to load image from URL: ${url}`, error);
393
+ throw new Error(`Failed to download image: ${error.message}`);
394
+ }
395
+ }
396
+ __name(loadImageFromUrl, "loadImageFromUrl");
397
+ async function saveImg(ctx, tag_name, guild_id, imgurl, savePath2) {
398
+ try {
399
+ const Img = getImgsModel();
400
+ let tag = await getTag(tag_name, guild_id);
401
+ if (tag == null) {
402
+ throw new Error(`not found tag '${tag_name}'!`);
403
+ }
404
+ if (tag.get("status") !== 0) {
405
+ logger.info(`[saveImg Info]:tag '${tag_name}' is deleted`);
406
+ throw new Error(`tag '${tag_name}' is deleted!`);
407
+ }
408
+ if (savePath2 == null) {
409
+ throw new Error("saving path config wrong!");
410
+ }
411
+ let dir = (0, import_path.join)(savePath2, String(tag.get("id")));
412
+ const now = new Date(Date.now() + 8 * 60 * 60 * 1e3);
413
+ const srcMatch = imgurl.match(/src="([^"]+)"/);
414
+ if (!srcMatch) throw new Error("invalid img tag, no src found!");
415
+ const srcUrl = srcMatch[1];
416
+ const imageBuffer = await loadImageFromUrl(ctx, srcUrl);
417
+ if (!imageBuffer || imageBuffer.byteLength === 0) {
418
+ throw new Error("Downloaded image data is empty.");
419
+ }
420
+ logger.info("[saveImg Info]: Downloaded image data success!");
421
+ const fileNameMatch = imgurl.match(/file="([^"]+)"/);
422
+ if (!fileNameMatch) throw new Error("invalid img tag, no file name found!");
423
+ const fileName = fileNameMatch[1];
424
+ const filePath = (0, import_path.join)(dir, fileName);
425
+ await import_fs.promises.writeFile(filePath, imageBuffer);
426
+ const saveImg2 = await Img.create({ tag_id: tag.get("id"), img_url: filePath, createtime: now });
427
+ logger.info("[saveImg Info]: save image to '" + tag_name + "' success");
428
+ return { result: true, error: null };
429
+ } catch (e) {
430
+ logger.error("[saveImg Error]: " + e?.message || String(e));
431
+ return { result: false, error: e?.message || String(e) };
432
+ }
433
+ }
434
+ __name(saveImg, "saveImg");
435
+ async function randomImgByTag(tag_name, guild_id) {
436
+ try {
437
+ const Img = getImgsModel();
438
+ const existed = await getTag(tag_name, guild_id);
439
+ if (!existed) {
440
+ throw new Error(`not found tag '${tag_name}'!`);
441
+ }
442
+ if (existed.status == 0) {
443
+ throw new Error(`not found tag '${tag_name}'!`);
444
+ }
445
+ let ImgList = await Img.findAll({
446
+ where: {
447
+ status: 0,
448
+ tag_id: existed.get("id")
449
+ }
450
+ });
451
+ if (ImgList.length <= 0) {
452
+ throw new Error("Don't have image!");
453
+ }
454
+ const random = new import_koishi6.Random(() => Math.random());
455
+ let result = ImgList[random.int(0, ImgList.length)];
456
+ const filePath = result.get("img_url");
457
+ return filePath;
458
+ } catch (e) {
459
+ logger.error("[randomImgByTag Error]: " + e?.message || String(e));
460
+ return null;
461
+ }
462
+ }
463
+ __name(randomImgByTag, "randomImgByTag");
464
+ async function getImgCountByTag(tag_id) {
465
+ const Img = getImgsModel();
466
+ let count = await Img.count({
467
+ where: { status: 0, tag_id }
468
+ });
469
+ return count;
470
+ }
471
+ __name(getImgCountByTag, "getImgCountByTag");
472
+
473
+ // src/services/tag_func/tag_service.ts
474
+ async function findTagByName(tag_name, guild_id) {
244
475
  const Tag = getTagsModel();
245
476
  return await Tag.findOne({
246
477
  where: {
247
478
  status: 0,
479
+ guild_id,
248
480
  [import_sequelize4.Op.or]: [
249
- { tags: name2 },
250
- { alias: { [import_sequelize4.Op.like]: `%${name2}%` } }
481
+ { tags: tag_name },
482
+ { alias: { [import_sequelize4.Op.like]: `%${tag_name}%` } }
251
483
  ]
252
484
  }
253
485
  });
254
486
  }
255
487
  __name(findTagByName, "findTagByName");
256
- async function findDeletedTagByName(name2) {
488
+ async function findDeletedTagByName(tag_name, guild_id) {
257
489
  const Tag = getTagsModel();
258
490
  return await Tag.findOne({
259
491
  where: {
260
492
  status: 1,
493
+ guild_id,
261
494
  [import_sequelize4.Op.or]: [
262
- { tags: name2 },
263
- { alias: { [import_sequelize4.Op.like]: `%${name2}%` } }
495
+ { tags: tag_name },
496
+ { alias: { [import_sequelize4.Op.like]: `%${tag_name}%` } }
264
497
  ]
265
498
  }
266
499
  });
267
500
  }
268
501
  __name(findDeletedTagByName, "findDeletedTagByName");
269
- async function createorUpdateTag(name2, alias, savePath2) {
502
+ async function createorUpdateTag(tag_name, guild_id, savePath2) {
270
503
  try {
271
504
  const Tag = getTagsModel();
272
- let existed = await findTagByName(name2);
505
+ let existed = await findTagByName(tag_name, guild_id);
273
506
  if (existed) {
274
- if (alias == null) {
275
- throw new Error("already existed!");
276
- }
277
- let now_alias = existed.get("alias");
278
- if (now_alias != null) {
279
- const list = now_alias.split(";");
280
- if (!list.includes(alias)) list.push(alias);
281
- now_alias = list.join(";");
282
- } else {
283
- now_alias = alias;
284
- }
285
- existed.alias = now_alias;
286
- await existed.save();
287
- return { result: true, error: null };
507
+ throw new Error("already existed!");
288
508
  }
289
- existed = await findDeletedTagByName(name2);
509
+ existed = await findDeletedTagByName(tag_name, guild_id);
290
510
  if (existed) {
291
511
  if (existed.get("status") != 0) {
292
512
  existed.set("status", 0);
@@ -299,9 +519,9 @@ async function createorUpdateTag(name2, alias, savePath2) {
299
519
  throw new Error("saving path config wrong!");
300
520
  }
301
521
  const now = new Date(Date.now() + 8 * 60 * 60 * 1e3);
302
- const tag = await Tag.create({ tags: name2, alias: alias ?? null, createtime: now });
303
- const dir = (0, import_path.join)(savePath2, String(tag.id));
304
- (0, import_fs.mkdirSync)(dir, { recursive: true });
522
+ const tag = await Tag.create({ tags: tag_name, alias: null, guild_id, createtime: now });
523
+ const dir = (0, import_path2.join)(savePath2, String(tag.id));
524
+ (0, import_fs2.mkdirSync)(dir, { recursive: true });
305
525
  return { result: true, error: null };
306
526
  } catch (e) {
307
527
  logger.error("[createorUpdateTag Error]: " + e?.message || String(e));
@@ -309,9 +529,9 @@ async function createorUpdateTag(name2, alias, savePath2) {
309
529
  }
310
530
  }
311
531
  __name(createorUpdateTag, "createorUpdateTag");
312
- async function getTag(name2) {
532
+ async function getTag(tag_name, guild_id) {
313
533
  try {
314
- let tag = await findTagByName(name2);
534
+ let tag = await findTagByName(tag_name, guild_id);
315
535
  return tag;
316
536
  } catch (e) {
317
537
  logger.error("[getTag Error]: " + e?.message || String(e));
@@ -319,119 +539,93 @@ async function getTag(name2) {
319
539
  }
320
540
  }
321
541
  __name(getTag, "getTag");
322
-
323
- // src/services/img_service.ts
324
- var import_koishi2 = require("koishi");
325
- var import_path2 = require("path");
326
- var import_fs2 = require("fs");
327
- async function saveImg(name2, img, savePath2) {
542
+ async function bindAlias(tag_name, guild_id, alias) {
328
543
  try {
329
- const Img = getImgsModel();
330
- logger.info("[saveImg Info]: " + img);
331
- let tag = await getTag(name2);
332
- if (tag == null) {
333
- throw new Error(`not found tag '${name2}'!`);
334
- }
335
- if (tag.get("status") !== 0) {
336
- logger.info(`[saveImg Info]:tag '${name2}' is deleted`);
337
- throw new Error(`tag '${name2}' is deleted!`);
544
+ return await checkAlias(tag_name, alias, guild_id, false);
545
+ } catch (e) {
546
+ logger.error("[bindAlias Error]: " + e?.message || String(e));
547
+ return { result: false, error: e?.message || String(e) };
548
+ }
549
+ }
550
+ __name(bindAlias, "bindAlias");
551
+ async function unbindAlias(tag_name, guild_id, alias) {
552
+ try {
553
+ return await checkAlias(tag_name, alias, guild_id, true);
554
+ } catch (e) {
555
+ logger.error("[unbindAlias Error]: " + e?.message || String(e));
556
+ return { result: false, error: e?.message || String(e) };
557
+ }
558
+ }
559
+ __name(unbindAlias, "unbindAlias");
560
+ async function checkAlias(tag_name, alias, guild_id, isDelete = false) {
561
+ try {
562
+ let existed = await findTagByName(tag_name, guild_id);
563
+ if (existed == null) {
564
+ throw new Error(`not found tag '${tag_name}'`);
338
565
  }
339
- if (savePath2 == null) {
340
- throw new Error("saving path config wrong!");
566
+ let now_alias = existed.get("alias");
567
+ let new_list;
568
+ if (!isDelete) {
569
+ if (now_alias != null) {
570
+ const list = now_alias.split(";");
571
+ if (!list.includes(alias)) list.push(alias);
572
+ now_alias = list.join(";");
573
+ } else {
574
+ now_alias = alias;
575
+ }
576
+ } else {
577
+ if (now_alias != null) {
578
+ const list = now_alias.split(";");
579
+ if (list.includes(alias))
580
+ new_list = list.filter((tar) => tar !== alias);
581
+ now_alias = new_list.join(";");
582
+ } else {
583
+ throw new Error(`not found alia '${alias}'`);
584
+ }
341
585
  }
342
- let dir = (0, import_path2.join)(savePath2, String(tag.get("id")));
343
- const now = new Date(Date.now() + 8 * 60 * 60 * 1e3);
344
- const filename = now.getFullYear().toString() + String(now.getMonth() + 1).padStart(2, "0") + String(now.getDate()).padStart(2, "0") + String(now.getHours()).padStart(2, "0") + String(now.getMinutes()).padStart(2, "0") + String(now.getSeconds()).padStart(2, "0") + ".txt";
345
- let filePath = (0, import_path2.join)(dir, filename);
346
- await import_fs2.promises.writeFile(filePath, img);
347
- const saveImg2 = await Img.create({ tag_id: tag.get("id"), img_url: filePath, createtime: now });
348
- logger.info("[saveImg Info]: save image to '" + name2 + "' success");
586
+ existed.set("alias", now_alias);
587
+ await existed.save();
349
588
  return { result: true, error: null };
350
589
  } catch (e) {
351
- logger.error("[saveImg Error]: " + e?.message || String(e));
590
+ logger.error("[checkAlias Error]: " + e?.message || String(e));
352
591
  return { result: false, error: e?.message || String(e) };
353
592
  }
354
593
  }
355
- __name(saveImg, "saveImg");
356
- async function randomImgByTag(name2, savePath2) {
594
+ __name(checkAlias, "checkAlias");
595
+ async function getTagList(guild_id) {
357
596
  try {
358
- const Img = getImgsModel();
359
- const existed = await getTag(name2);
360
- if (!existed) {
361
- throw new Error(`not found tag '${name2}'!`);
362
- }
363
- if (existed.status == 0) {
364
- throw new Error(`not found tag '${name2}'!`);
365
- }
366
- let ImgList = await Img.findAll({
367
- where: {
368
- status: 0,
369
- tag_id: existed.get("id")
370
- }
597
+ const Tag = getTagsModel();
598
+ let resultList = await Tag.findAll({
599
+ where: { status: 0, guild_id }
371
600
  });
372
- if (ImgList.length <= 0) {
373
- throw new Error("Don't have image!");
601
+ let tagList = [];
602
+ for (const element of resultList) {
603
+ let count = await getImgCountByTag(element.get("id"));
604
+ tagList.push({
605
+ tag: element.get("tags"),
606
+ alias: element.get("alias"),
607
+ count
608
+ });
374
609
  }
375
- const random = new import_koishi2.Random(() => Math.random());
376
- let result = ImgList[random.int(0, ImgList.length)];
377
- const filePath = result.get("img_url");
378
- const fileContent = await import_fs2.promises.readFile(filePath, { encoding: "utf-8" });
379
- return fileContent;
610
+ ;
611
+ return tagList.sort((a, b) => b.count - a.count);
380
612
  } catch (e) {
381
- logger.error("[randomImgByTag Error]: " + e?.message || String(e));
613
+ logger.error("[getTagList Error]: " + e?.message || String(e));
382
614
  return null;
383
615
  }
384
616
  }
385
- __name(randomImgByTag, "randomImgByTag");
617
+ __name(getTagList, "getTagList");
386
618
 
387
- // src/index.ts
388
- var name = "cocoyyy-console";
389
- var Config = import_koishi3.Schema.object({
390
- mysql: MysqlConfigSchema.description("MySQL 数据库配置"),
391
- save: SaveConfigSchema.description("图片保存配置")
392
- });
393
- var menuList = [
394
- {
395
- name: "maketag",
396
- description: "创建一个标签",
397
- command: "maketag [标签]"
398
- },
399
- {
400
- name: "add",
401
- description: "给标签添加图片",
402
- command: "add [标签] [图片]"
403
- },
404
- {
405
- name: "get",
406
- description: "给标签添加图片",
407
- command: "get [标签]"
408
- }
409
- ];
410
- var logger = new import_koishi3.Logger(name);
411
- var savePath = null;
412
- async function apply(ctx, config) {
413
- const mysqlConf = config?.mysql ?? loadMysqlConfigFromEnv();
414
- initSequelize(mysqlConf);
415
- const connected = await testConnect();
416
- if (connected) {
417
- await getTagsModel().sync();
418
- await getImgsModel().sync();
419
- }
420
- savePath = resolveTagBaseDir(config?.save);
421
- ctx.command("fullhelp", "帮助菜单").check(({ session }) => {
422
- if (!connected) return;
423
- if (!is_at_bot(session)) return;
424
- }).action(async ({ session }) => {
425
- return `帮助菜单[所有命令都需要@bot]:
426
- ${menuList.map((item) => item.command + ": " + item.description).join("\n ")}`;
427
- });
619
+ // src/services/tag_func/tag_commands.ts
620
+ var import_url = require("url");
621
+ function registerTagCommands(ctx, connected, savePath2) {
428
622
  ctx.command("maketag <参数>", "创建一个标签").check(({ session }) => {
429
623
  if (!connected) return;
430
624
  if (!is_at_bot(session)) return;
431
625
  }).action(async ({ session }, ...args) => {
432
626
  const tag = args?.[0];
433
627
  if (!tag) return "请提供正确格式,如:@bot maketag [标签]";
434
- let exec = await createorUpdateTag(tag, null, savePath);
628
+ let exec = await createorUpdateTag(tag, session.guildId, savePath2);
435
629
  if (!exec.result)
436
630
  return `创建标签失败:${exec.error}`;
437
631
  return `已创建标签:${tag}`;
@@ -443,7 +637,7 @@ async function apply(ctx, config) {
443
637
  const tag = args?.[0];
444
638
  const img = args?.[1];
445
639
  if (!tag || !img) return "请提供正确格式,如:@bot add [标签] [图片]";
446
- let exec = await saveImg(tag, img, savePath);
640
+ let exec = await saveImg(ctx, tag, session.guildId, img, savePath2);
447
641
  if (!exec.result)
448
642
  return `保存图片失败:${exec.error}`;
449
643
  return "保存图片成功";
@@ -454,12 +648,169 @@ async function apply(ctx, config) {
454
648
  }).action(async ({ session }, ...args) => {
455
649
  const tag = args?.[0];
456
650
  if (!tag) return "请提供正确格式,如:@bot get [标签]";
457
- let exec = await randomImgByTag(tag, savePath);
651
+ let exec = await randomImgByTag(tag, session.guildId);
458
652
  if (!exec)
459
653
  return `获取图片失败`;
460
- return exec;
654
+ let path = (0, import_url.pathToFileURL)(exec).href;
655
+ return import_koishi7.h.image(path);
656
+ });
657
+ ctx.command("bind <参数>", "标签绑定别名").check(({ session }) => {
658
+ if (!connected) return;
659
+ if (!is_at_bot(session)) return;
660
+ }).action(async ({ session }, ...args) => {
661
+ const tag = args?.[0];
662
+ const alia = args?.[1];
663
+ if (!tag || !alia) return "请提供正确格式,如:@bot bind [标签] [别名]";
664
+ let exec = await bindAlias(tag, session.guildId, alia);
665
+ if (!exec.result)
666
+ return `绑定别名失败:${exec.error}`;
667
+ return `绑定别名成功`;
668
+ });
669
+ ctx.command("unbind <参数>", "标签取消别名").check(({ session }) => {
670
+ if (!connected) return;
671
+ if (!is_at_bot(session)) return;
672
+ }).action(async ({ session }, ...args) => {
673
+ const tag = args?.[0];
674
+ const alia = args?.[1];
675
+ if (!tag || !alia) return "请提供正确格式,如:@bot unbind [标签] [别名]";
676
+ let exec = await unbindAlias(tag, session.guildId, alia);
677
+ if (!exec.result)
678
+ return `取消绑定失败:${exec.error}`;
679
+ return `取消绑定成功`;
680
+ });
681
+ ctx.command("taglist", "获取标签列表").check(({ session }) => {
682
+ if (!connected) return;
683
+ if (!is_at_bot(session)) return;
684
+ }).action(async ({ session }, ...args) => {
685
+ let exec = await getTagList(session.guildId);
686
+ if (exec == null)
687
+ return `查询失败`;
688
+ return `查询成功!
689
+ ${exec.map((item) => "标签:" + item.tag + " 黑历史数:" + item.count + "\n别名:" + (item.alias ? item.alias : "无")).join("\n\n")}`;
690
+ });
691
+ }
692
+ __name(registerTagCommands, "registerTagCommands");
693
+
694
+ // src/services/repeat_func/repeat_service.ts
695
+ function registerRepeatMiddleware(ctx, config) {
696
+ const states = {};
697
+ const minTimes = config?.minTimes ?? 3;
698
+ const probability = config?.probability ?? 1;
699
+ const guild_ids = config?.guild_ids?.split(",") ?? [];
700
+ const resetInterval = config?.resetInterval ?? 300;
701
+ function getState(id) {
702
+ if (!states[id]) {
703
+ states[id] = {
704
+ content: "",
705
+ repeated: false,
706
+ times: 0,
707
+ users: {}
708
+ };
709
+ }
710
+ return states[id];
711
+ }
712
+ __name(getState, "getState");
713
+ function resetState(id) {
714
+ const state = getState(id);
715
+ state.content = "";
716
+ state.repeated = false;
717
+ state.times = 0;
718
+ state.users = {};
719
+ }
720
+ __name(resetState, "resetState");
721
+ ctx.before("send", ({ cid, content }) => {
722
+ const state = getState(cid);
723
+ state.repeated = true;
724
+ if (state.content === content) {
725
+ state.times += 1;
726
+ } else {
727
+ state.content = content;
728
+ state.times = 1;
729
+ state.users = {};
730
+ }
731
+ });
732
+ ctx.middleware((session, next) => {
733
+ const { content, uid, userId } = session;
734
+ const cid = session.cid;
735
+ if (guild_ids.includes(session.guildId)) return next();
736
+ if (ctx.bots[uid]) return next();
737
+ const state = getState(cid);
738
+ if (state.timer) clearTimeout(state.timer);
739
+ state.timer = setTimeout(() => resetState(cid), resetInterval * 1e3);
740
+ if (content === state.content) {
741
+ state.times += 1;
742
+ state.users[userId] = (state.users[userId] || 0) + 1;
743
+ const uniqueUsers = Object.keys(state.users).length;
744
+ if (!state.repeated && state.times >= minTimes && uniqueUsers >= 2 && Math.random() < probability) {
745
+ state.repeated = true;
746
+ return next(content);
747
+ }
748
+ return next();
749
+ }
750
+ state.content = content;
751
+ state.repeated = false;
752
+ state.times = 1;
753
+ state.users = { [userId]: 1 };
754
+ return next();
755
+ });
756
+ }
757
+ __name(registerRepeatMiddleware, "registerRepeatMiddleware");
758
+
759
+ // src/services/rbq_func/rbq_service.ts
760
+ var import_koishi8 = require("koishi");
761
+ function registerRbqMiddleware(ctx, config) {
762
+ if (!config?.configList || config.configList.length === 0) return;
763
+ ctx.middleware((session, next) => {
764
+ const { guildId, elements } = session;
765
+ if (ctx.bots[session.uid]) return next();
766
+ if (!config.configList.some((item) => item.guild_id === guildId)) return next();
767
+ const atElements = elements?.filter((el) => el.type === "at") || [];
768
+ if (atElements.length === 0) return next();
769
+ const matched = config.configList.find((item) => {
770
+ const targetUid = item.uid?.trim();
771
+ if (!targetUid) return false;
772
+ const isAtTarget = atElements.some((el) => el.attrs?.id === targetUid);
773
+ if (!isAtTarget) return false;
774
+ const probability = item.probability ?? 1;
775
+ return Math.random() <= probability;
776
+ });
777
+ if (!matched) return next();
778
+ const content = matched.content || "*死你";
779
+ session.send((0, import_koishi8.h)("at", { id: matched.uid.trim() }) + " " + content);
780
+ return;
461
781
  });
462
782
  }
783
+ __name(registerRbqMiddleware, "registerRbqMiddleware");
784
+
785
+ // src/index.ts
786
+ var name = "cocoyyy-console";
787
+ var Config = import_koishi9.Schema.object({
788
+ function_config: FunctionConfigSchema.description("功能开关配置"),
789
+ mysql_config: MysqlConfigSchema.description("MySQL 数据库配置"),
790
+ tag_config: SaveConfigSchema.description("tag图片保存配置"),
791
+ repeat_config: RepeatConfigSchema.description("复读配置"),
792
+ rbq_config: RbqConfigSchema.description("*人配置")
793
+ });
794
+ var logger = new import_koishi9.Logger(name);
795
+ var savePath = null;
796
+ async function apply(ctx, config) {
797
+ ctx = ctx.guild();
798
+ const mysqlConf = config?.mysql_config ?? loadMysqlConfigFromEnv();
799
+ initSequelize(mysqlConf);
800
+ const connected = await testConnect();
801
+ if (connected) {
802
+ await getTagsModel().sync();
803
+ await getImgsModel().sync();
804
+ }
805
+ savePath = resolveTagBaseDir(config?.tag_config);
806
+ registerMenuCommands(ctx, connected, config.function_config);
807
+ if (config.function_config.tag_flag)
808
+ registerTagCommands(ctx, connected, savePath);
809
+ if (config.function_config.repeat_flag)
810
+ registerRepeatMiddleware(ctx, config?.repeat_config);
811
+ if (config.function_config.rbq_flag)
812
+ registerRbqMiddleware(ctx, config?.rbq_config);
813
+ }
463
814
  __name(apply, "apply");
464
815
  // Annotate the CommonJS export names for ESM import in node:
465
816
  0 && (module.exports = {
@@ -3,14 +3,16 @@ export interface TagAttributes {
3
3
  id: number;
4
4
  tags: string;
5
5
  alias: string | null;
6
+ guild_id: string | null;
6
7
  status: number | null;
7
8
  createtime: Date;
8
9
  }
9
- export type TagCreationAttributes = Optional<TagAttributes, 'id' | 'alias' | 'status' | 'createtime'>;
10
+ export type TagCreationAttributes = Optional<TagAttributes, 'id' | 'alias' | 'guild_id' | 'status' | 'createtime'>;
10
11
  export declare class TagsModel extends Model<TagAttributes, TagCreationAttributes> implements TagAttributes {
11
12
  id: number;
12
13
  tags: string;
13
14
  alias: string | null;
15
+ guild_id: string | null;
14
16
  status: number | null;
15
17
  createtime: Date;
16
18
  }
@@ -1,6 +1,8 @@
1
- declare function saveImg(name: string, img: string, savePath: string): Promise<{
1
+ import { Context } from "koishi";
2
+ declare function saveImg(ctx: Context, tag_name: string, imgurl: string, savePath: string): Promise<{
2
3
  result: boolean;
3
4
  error: string | null;
4
5
  }>;
5
- declare function randomImgByTag(name: string, savePath: string): Promise<string | null>;
6
- export { saveImg, randomImgByTag };
6
+ declare function randomImgByTag(tag_name: string): Promise<string | null>;
7
+ declare function getImgCountByTag(tag_id: number): Promise<number>;
8
+ export { saveImg, randomImgByTag, getImgCountByTag };
@@ -0,0 +1,5 @@
1
+ import { Context } from 'koishi';
2
+ import * as my_config from '../utils/config';
3
+ declare function getMenuList(command: string, functionConfig: my_config.FunctionConfig): string;
4
+ declare function registerMenuCommands(ctx: Context, connected: boolean, functionConfig: my_config.FunctionConfig): void;
5
+ export { getMenuList, registerMenuCommands };
File without changes
@@ -0,0 +1,4 @@
1
+ import { Context } from 'koishi';
2
+ import { RbqConfig } from '../../utils/config';
3
+ declare function registerRbqMiddleware(ctx: Context, config?: RbqConfig): void;
4
+ export { registerRbqMiddleware, };
@@ -0,0 +1,12 @@
1
+ import { Context, Dict, Session } from 'koishi';
2
+ import { RepeatConfig } from '../../utils/config';
3
+ interface RepeatState {
4
+ content: string;
5
+ repeated: boolean;
6
+ times: number;
7
+ users: Dict<number>;
8
+ timer?: NodeJS.Timeout;
9
+ }
10
+ type StateCallback = (state: RepeatState, session: Session) => void | string;
11
+ declare function registerRepeatMiddleware(ctx: Context, config?: RepeatConfig): void;
12
+ export { registerRepeatMiddleware, RepeatState, StateCallback };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,8 @@
1
+ import { Context } from "koishi";
2
+ declare function saveImg(ctx: Context, tag_name: string, guild_id: string, imgurl: string, savePath: string): Promise<{
3
+ result: boolean;
4
+ error: string | null;
5
+ }>;
6
+ declare function randomImgByTag(tag_name: string, guild_id: string): Promise<string | null>;
7
+ declare function getImgCountByTag(tag_id: number): Promise<number>;
8
+ export { saveImg, randomImgByTag, getImgCountByTag };
@@ -0,0 +1,3 @@
1
+ import { Context } from 'koishi';
2
+ declare function registerTagCommands(ctx: Context, connected: boolean, savePath: string | null): void;
3
+ export { registerTagCommands };
@@ -0,0 +1,20 @@
1
+ import { TagsModel } from '../../models/tags';
2
+ declare function createorUpdateTag(tag_name: string, guild_id: string, savePath?: string | null): Promise<{
3
+ result: boolean;
4
+ error: string | null;
5
+ }>;
6
+ declare function getTag(tag_name: string, guild_id: string): Promise<TagsModel | null>;
7
+ declare function bindAlias(tag_name: string, guild_id: string, alias: string): Promise<{
8
+ result: boolean;
9
+ error: string | null;
10
+ }>;
11
+ declare function unbindAlias(tag_name: string, guild_id: string, alias: string): Promise<{
12
+ result: boolean;
13
+ error: string | null;
14
+ }>;
15
+ declare function getTagList(guild_id: string): Promise<{
16
+ tag: string;
17
+ alias: string;
18
+ count: number;
19
+ }[]>;
20
+ export { createorUpdateTag, getTag, bindAlias, unbindAlias, getTagList };
@@ -1,7 +1,20 @@
1
1
  import { TagsModel } from '../models/tags';
2
- declare function createorUpdateTag(name: string, alias?: string | null, savePath?: string | null): Promise<{
2
+ declare function createorUpdateTag(tag_name: string, savePath?: string | null): Promise<{
3
3
  result: boolean;
4
4
  error: string | null;
5
5
  }>;
6
- declare function getTag(name: string): Promise<TagsModel | null>;
7
- export { createorUpdateTag, getTag };
6
+ declare function getTag(tag_name: string): Promise<TagsModel | null>;
7
+ declare function bindAlias(tag_name: string, alias: string): Promise<{
8
+ result: boolean;
9
+ error: string | null;
10
+ }>;
11
+ declare function unbindAlias(tag_name: string, alias: string): Promise<{
12
+ result: boolean;
13
+ error: string | null;
14
+ }>;
15
+ declare function getTagList(): Promise<{
16
+ tag: string;
17
+ alias: string;
18
+ count: number;
19
+ }[]>;
20
+ export { createorUpdateTag, getTag, bindAlias, unbindAlias, getTagList };
@@ -1,17 +1,5 @@
1
- import { Schema } from 'koishi';
2
- interface MysqlConfig {
3
- host: string;
4
- port: number;
5
- user: string;
6
- password: string;
7
- database: string;
8
- }
9
- declare const MysqlConfigSchema: Schema<MysqlConfig>;
10
- declare function loadMysqlConfigFromEnv(env?: NodeJS.ProcessEnv): MysqlConfig;
11
- declare function toMysqlUri(cfg: MysqlConfig): string;
12
- interface SaveConfig {
13
- save_path: string;
14
- }
15
- declare const SaveConfigSchema: Schema<SaveConfig>;
16
- declare function resolveTagBaseDir(config?: SaveConfig): string;
17
- export { MysqlConfigSchema, SaveConfigSchema, MysqlConfig, SaveConfig, loadMysqlConfigFromEnv, toMysqlUri, resolveTagBaseDir };
1
+ export * from './configs/function_config';
2
+ export * from './configs/mysql_config';
3
+ export * from './configs/tag_config';
4
+ export * from './configs/repeat_config';
5
+ export * from './configs/rbq_config';
@@ -0,0 +1,8 @@
1
+ import { Schema } from 'koishi';
2
+ interface FunctionConfig {
3
+ tag_flag: boolean;
4
+ repeat_flag: boolean;
5
+ rbq_flag: boolean;
6
+ }
7
+ declare const FunctionConfigSchema: Schema<FunctionConfig>;
8
+ export { FunctionConfig, FunctionConfigSchema, };
@@ -0,0 +1,12 @@
1
+ import { Schema } from 'koishi';
2
+ interface MysqlConfig {
3
+ host: string;
4
+ port: number;
5
+ user: string;
6
+ password: string;
7
+ database: string;
8
+ }
9
+ declare const MysqlConfigSchema: Schema<MysqlConfig>;
10
+ declare function loadMysqlConfigFromEnv(env?: NodeJS.ProcessEnv): MysqlConfig;
11
+ declare function toMysqlUri(cfg: MysqlConfig): string;
12
+ export { MysqlConfig, MysqlConfigSchema, loadMysqlConfigFromEnv, toMysqlUri, };
@@ -0,0 +1,12 @@
1
+ import { Schema } from 'koishi';
2
+ interface RbqConfigItem {
3
+ probability?: number;
4
+ guild_id?: string;
5
+ uid?: string;
6
+ content?: string;
7
+ }
8
+ interface RbqConfig {
9
+ configList?: RbqConfigItem[];
10
+ }
11
+ declare const RbqConfigSchema: Schema<RbqConfig>;
12
+ export { RbqConfig, RbqConfigSchema, };
@@ -0,0 +1,9 @@
1
+ import { Schema } from 'koishi';
2
+ interface RepeatConfig {
3
+ minTimes?: number;
4
+ probability?: number;
5
+ guild_ids?: string;
6
+ resetInterval?: number;
7
+ }
8
+ declare const RepeatConfigSchema: Schema<RepeatConfig>;
9
+ export { RepeatConfig, RepeatConfigSchema, };
@@ -0,0 +1,7 @@
1
+ import { Schema } from 'koishi';
2
+ interface SaveConfig {
3
+ save_path: string;
4
+ }
5
+ declare const SaveConfigSchema: Schema<SaveConfig>;
6
+ declare function resolveTagBaseDir(config?: SaveConfig): string;
7
+ export { SaveConfig, SaveConfigSchema, resolveTagBaseDir, };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-cocoyyy-console",
3
3
  "description": "for self using, function console",
4
- "version": "1.0.1",
4
+ "version": "1.0.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "contributors": [