koishi-plugin-cocoyyy-console 1.0.2 → 1.0.4

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,
@@ -225,20 +261,143 @@ function getImgsModel() {
225
261
  }
226
262
  __name(getImgsModel, "getImgsModel");
227
263
 
228
- // src/services/tag_service.ts
264
+ // src/utils/common.ts
265
+ function is_at_bot(session) {
266
+ const elements = Array.isArray(session?.elements) ? session.elements : [];
267
+ const atElement = elements.find((element) => element?.type === "at");
268
+ const atId = atElement?.attrs?.id;
269
+ const selfId = session?.bot?.selfId ?? session?.selfId;
270
+ if (atId == null || selfId == null) return false;
271
+ return String(atId) === String(selfId);
272
+ }
273
+ __name(is_at_bot, "is_at_bot");
274
+
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
229
375
  var import_sequelize4 = require("sequelize");
230
376
  var import_fs2 = require("fs");
231
377
  var import_path2 = require("path");
232
378
 
233
- // src/services/img_service.ts
234
- var import_koishi2 = require("koishi");
379
+ // src/services/tag_func/img_service.ts
380
+ var import_koishi6 = require("koishi");
235
381
  var import_path = require("path");
236
382
  var import_fs = require("fs");
237
- async function saveImg(tag_name, img, savePath2) {
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) {
238
398
  try {
239
399
  const Img = getImgsModel();
240
- logger.info("[saveImg Info]: " + img);
241
- let tag = await getTag(tag_name);
400
+ let tag = await getTag(tag_name, guild_id);
242
401
  if (tag == null) {
243
402
  throw new Error(`not found tag '${tag_name}'!`);
244
403
  }
@@ -251,9 +410,19 @@ async function saveImg(tag_name, img, savePath2) {
251
410
  }
252
411
  let dir = (0, import_path.join)(savePath2, String(tag.get("id")));
253
412
  const now = new Date(Date.now() + 8 * 60 * 60 * 1e3);
254
- const filetag_name = 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";
255
- let filePath = (0, import_path.join)(dir, filetag_name);
256
- await import_fs.promises.writeFile(filePath, img);
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);
257
426
  const saveImg2 = await Img.create({ tag_id: tag.get("id"), img_url: filePath, createtime: now });
258
427
  logger.info("[saveImg Info]: save image to '" + tag_name + "' success");
259
428
  return { result: true, error: null };
@@ -263,10 +432,10 @@ async function saveImg(tag_name, img, savePath2) {
263
432
  }
264
433
  }
265
434
  __name(saveImg, "saveImg");
266
- async function randomImgByTag(tag_name) {
435
+ async function randomImgByTag(tag_name, guild_id) {
267
436
  try {
268
437
  const Img = getImgsModel();
269
- const existed = await getTag(tag_name);
438
+ const existed = await getTag(tag_name, guild_id);
270
439
  if (!existed) {
271
440
  throw new Error(`not found tag '${tag_name}'!`);
272
441
  }
@@ -282,11 +451,10 @@ async function randomImgByTag(tag_name) {
282
451
  if (ImgList.length <= 0) {
283
452
  throw new Error("Don't have image!");
284
453
  }
285
- const random = new import_koishi2.Random(() => Math.random());
454
+ const random = new import_koishi6.Random(() => Math.random());
286
455
  let result = ImgList[random.int(0, ImgList.length)];
287
456
  const filePath = result.get("img_url");
288
- const fileContent = await import_fs.promises.readFile(filePath, { encoding: "utf-8" });
289
- return fileContent;
457
+ return filePath;
290
458
  } catch (e) {
291
459
  logger.error("[randomImgByTag Error]: " + e?.message || String(e));
292
460
  return null;
@@ -302,12 +470,13 @@ async function getImgCountByTag(tag_id) {
302
470
  }
303
471
  __name(getImgCountByTag, "getImgCountByTag");
304
472
 
305
- // src/services/tag_service.ts
306
- async function findTagByName(tag_name) {
473
+ // src/services/tag_func/tag_service.ts
474
+ async function findTagByName(tag_name, guild_id) {
307
475
  const Tag = getTagsModel();
308
476
  return await Tag.findOne({
309
477
  where: {
310
478
  status: 0,
479
+ guild_id,
311
480
  [import_sequelize4.Op.or]: [
312
481
  { tags: tag_name },
313
482
  { alias: { [import_sequelize4.Op.like]: `%${tag_name}%` } }
@@ -316,11 +485,12 @@ async function findTagByName(tag_name) {
316
485
  });
317
486
  }
318
487
  __name(findTagByName, "findTagByName");
319
- async function findDeletedTagByName(tag_name) {
488
+ async function findDeletedTagByName(tag_name, guild_id) {
320
489
  const Tag = getTagsModel();
321
490
  return await Tag.findOne({
322
491
  where: {
323
492
  status: 1,
493
+ guild_id,
324
494
  [import_sequelize4.Op.or]: [
325
495
  { tags: tag_name },
326
496
  { alias: { [import_sequelize4.Op.like]: `%${tag_name}%` } }
@@ -329,14 +499,14 @@ async function findDeletedTagByName(tag_name) {
329
499
  });
330
500
  }
331
501
  __name(findDeletedTagByName, "findDeletedTagByName");
332
- async function createorUpdateTag(tag_name, savePath2) {
502
+ async function createorUpdateTag(tag_name, guild_id, savePath2) {
333
503
  try {
334
504
  const Tag = getTagsModel();
335
- let existed = await findTagByName(tag_name);
505
+ let existed = await findTagByName(tag_name, guild_id);
336
506
  if (existed) {
337
507
  throw new Error("already existed!");
338
508
  }
339
- existed = await findDeletedTagByName(tag_name);
509
+ existed = await findDeletedTagByName(tag_name, guild_id);
340
510
  if (existed) {
341
511
  if (existed.get("status") != 0) {
342
512
  existed.set("status", 0);
@@ -349,7 +519,7 @@ async function createorUpdateTag(tag_name, savePath2) {
349
519
  throw new Error("saving path config wrong!");
350
520
  }
351
521
  const now = new Date(Date.now() + 8 * 60 * 60 * 1e3);
352
- const tag = await Tag.create({ tags: tag_name, alias: null, createtime: now });
522
+ const tag = await Tag.create({ tags: tag_name, alias: null, guild_id, createtime: now });
353
523
  const dir = (0, import_path2.join)(savePath2, String(tag.id));
354
524
  (0, import_fs2.mkdirSync)(dir, { recursive: true });
355
525
  return { result: true, error: null };
@@ -359,9 +529,9 @@ async function createorUpdateTag(tag_name, savePath2) {
359
529
  }
360
530
  }
361
531
  __name(createorUpdateTag, "createorUpdateTag");
362
- async function getTag(tag_name) {
532
+ async function getTag(tag_name, guild_id) {
363
533
  try {
364
- let tag = await findTagByName(tag_name);
534
+ let tag = await findTagByName(tag_name, guild_id);
365
535
  return tag;
366
536
  } catch (e) {
367
537
  logger.error("[getTag Error]: " + e?.message || String(e));
@@ -369,27 +539,27 @@ async function getTag(tag_name) {
369
539
  }
370
540
  }
371
541
  __name(getTag, "getTag");
372
- async function bindAlias(tag_name, alias) {
542
+ async function bindAlias(tag_name, guild_id, alias) {
373
543
  try {
374
- return await checkAlias(tag_name, alias, false);
544
+ return await checkAlias(tag_name, alias, guild_id, false);
375
545
  } catch (e) {
376
546
  logger.error("[bindAlias Error]: " + e?.message || String(e));
377
547
  return { result: false, error: e?.message || String(e) };
378
548
  }
379
549
  }
380
550
  __name(bindAlias, "bindAlias");
381
- async function unbindAlias(tag_name, alias) {
551
+ async function unbindAlias(tag_name, guild_id, alias) {
382
552
  try {
383
- return await checkAlias(tag_name, alias, true);
553
+ return await checkAlias(tag_name, alias, guild_id, true);
384
554
  } catch (e) {
385
555
  logger.error("[unbindAlias Error]: " + e?.message || String(e));
386
556
  return { result: false, error: e?.message || String(e) };
387
557
  }
388
558
  }
389
559
  __name(unbindAlias, "unbindAlias");
390
- async function checkAlias(tag_name, alias, isDelete = false) {
560
+ async function checkAlias(tag_name, alias, guild_id, isDelete = false) {
391
561
  try {
392
- let existed = await findTagByName(tag_name);
562
+ let existed = await findTagByName(tag_name, guild_id);
393
563
  if (existed == null) {
394
564
  throw new Error(`not found tag '${tag_name}'`);
395
565
  }
@@ -422,22 +592,23 @@ async function checkAlias(tag_name, alias, isDelete = false) {
422
592
  }
423
593
  }
424
594
  __name(checkAlias, "checkAlias");
425
- async function getTagList() {
595
+ async function getTagList(guild_id) {
426
596
  try {
427
597
  const Tag = getTagsModel();
428
598
  let resultList = await Tag.findAll({
429
- where: { status: 0 }
599
+ where: { status: 0, guild_id }
430
600
  });
431
601
  let tagList = [];
432
- resultList.forEach(async (element) => {
602
+ for (const element of resultList) {
433
603
  let count = await getImgCountByTag(element.get("id"));
434
604
  tagList.push({
435
605
  tag: element.get("tags"),
436
606
  alias: element.get("alias"),
437
607
  count
438
608
  });
439
- });
440
- return tagList;
609
+ }
610
+ ;
611
+ return tagList.sort((a, b) => b.count - a.count);
441
612
  } catch (e) {
442
613
  logger.error("[getTagList Error]: " + e?.message || String(e));
443
614
  return null;
@@ -445,111 +616,201 @@ async function getTagList() {
445
616
  }
446
617
  __name(getTagList, "getTagList");
447
618
 
448
- // src/index.ts
449
- var name = "cocoyyy-console";
450
- var Config = import_koishi3.Schema.object({
451
- mysql: MysqlConfigSchema.description("MySQL 数据库配置"),
452
- save: SaveConfigSchema.description("图片保存配置")
453
- });
454
- var menuList = [
455
- {
456
- name: "maketag",
457
- description: "创建一个标签",
458
- command: "maketag [标签]"
459
- },
460
- {
461
- name: "add",
462
- description: "给标签添加图片",
463
- command: "add [标签] [图片]"
464
- },
465
- {
466
- name: "get",
467
- description: "给标签添加图片",
468
- command: "get [标签]"
469
- },
470
- {
471
- name: "bind",
472
- description: "标签绑定别名",
473
- command: "bind [标签] [别名]"
474
- },
475
- {
476
- name: "unbind",
477
- description: "标签取消别名",
478
- command: "unbind [标签] [别名]"
479
- },
480
- {
481
- name: "taglist",
482
- description: "获取标签列表",
483
- command: "taglist"
484
- }
485
- ];
486
- var logger = new import_koishi3.Logger(name);
487
- var savePath = null;
488
- async function apply(ctx, config) {
489
- const mysqlConf = config?.mysql ?? loadMysqlConfigFromEnv();
490
- initSequelize(mysqlConf);
491
- const connected = await testConnect();
492
- if (connected) {
493
- await getTagsModel().sync();
494
- await getImgsModel().sync();
495
- }
496
- savePath = resolveTagBaseDir(config?.save);
497
- ctx.command("fullhelp", "帮助菜单").action(async ({ session }) => {
498
- return `帮助菜单[所有命令都需要@bot]:
499
- ${menuList.map((item) => item.command + ": " + item.description).join("\n ")}`;
500
- });
501
- ctx.command("maketag <参数>", "创建一个标签").action(async ({ session }, ...args) => {
619
+ // src/services/tag_func/tag_commands.ts
620
+ var import_url = require("url");
621
+ function registerTagCommands(ctx, connected, savePath2) {
622
+ ctx.command("maketag <参数>", "创建一个标签").check(({ session }) => {
623
+ if (!connected) return;
624
+ if (!is_at_bot(session)) return;
625
+ }).action(async ({ session }, ...args) => {
502
626
  const tag = args?.[0];
503
627
  if (!tag) return "请提供正确格式,如:@bot maketag [标签]";
504
- let exec = await createorUpdateTag(tag, savePath);
628
+ let exec = await createorUpdateTag(tag, session.guildId, savePath2);
505
629
  if (!exec.result)
506
630
  return `创建标签失败:${exec.error}`;
507
631
  return `已创建标签:${tag}`;
508
632
  });
509
- ctx.command("add <参数>", "给标签添加图片").action(async ({ session }, ...args) => {
633
+ ctx.command("add <参数>", "给标签添加图片").check(({ session }) => {
634
+ if (!connected) return;
635
+ if (!is_at_bot(session)) return;
636
+ }).action(async ({ session }, ...args) => {
510
637
  const tag = args?.[0];
511
638
  const img = args?.[1];
512
639
  if (!tag || !img) return "请提供正确格式,如:@bot add [标签] [图片]";
513
- let exec = await saveImg(tag, img, savePath);
640
+ let exec = await saveImg(ctx, tag, session.guildId, img, savePath2);
514
641
  if (!exec.result)
515
642
  return `保存图片失败:${exec.error}`;
516
643
  return "保存图片成功";
517
644
  });
518
- ctx.command("get <参数>", "获取标签对应图片").action(async ({ session }, ...args) => {
645
+ ctx.command("get <参数>", "获取标签对应图片").check(({ session }) => {
646
+ if (!connected) return;
647
+ if (!is_at_bot(session)) return;
648
+ }).action(async ({ session }, ...args) => {
519
649
  const tag = args?.[0];
520
650
  if (!tag) return "请提供正确格式,如:@bot get [标签]";
521
- let exec = await randomImgByTag(tag);
651
+ let exec = await randomImgByTag(tag, session.guildId);
522
652
  if (!exec)
523
653
  return `获取图片失败`;
524
- return exec;
654
+ let path = (0, import_url.pathToFileURL)(exec).href;
655
+ return import_koishi7.h.image(path);
525
656
  });
526
- ctx.command("bind <参数>", "标签绑定别名").action(async ({ session }, ...args) => {
657
+ ctx.command("bind <参数>", "标签绑定别名").check(({ session }) => {
658
+ if (!connected) return;
659
+ if (!is_at_bot(session)) return;
660
+ }).action(async ({ session }, ...args) => {
527
661
  const tag = args?.[0];
528
662
  const alia = args?.[1];
529
663
  if (!tag || !alia) return "请提供正确格式,如:@bot bind [标签] [别名]";
530
- let exec = await bindAlias(tag, alia);
664
+ let exec = await bindAlias(tag, session.guildId, alia);
531
665
  if (!exec.result)
532
666
  return `绑定别名失败:${exec.error}`;
533
667
  return `绑定别名成功`;
534
668
  });
535
- ctx.command("unbind <参数>", "标签取消别名").action(async ({ session }, ...args) => {
669
+ ctx.command("unbind <参数>", "标签取消别名").check(({ session }) => {
670
+ if (!connected) return;
671
+ if (!is_at_bot(session)) return;
672
+ }).action(async ({ session }, ...args) => {
536
673
  const tag = args?.[0];
537
674
  const alia = args?.[1];
538
675
  if (!tag || !alia) return "请提供正确格式,如:@bot unbind [标签] [别名]";
539
- let exec = await unbindAlias(tag, alia);
676
+ let exec = await unbindAlias(tag, session.guildId, alia);
540
677
  if (!exec.result)
541
678
  return `取消绑定失败:${exec.error}`;
542
679
  return `取消绑定成功`;
543
680
  });
544
- ctx.command("taglist", "获取标签列表").action(async ({ session }, ...args) => {
545
- let exec = await getTagList();
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);
546
686
  if (exec == null)
547
687
  return `查询失败`;
548
688
  return `查询成功!
689
+ ${exec.map((item) => "标签:" + item.tag + " 黑历史数:" + item.count + "\n别名:" + (item.alias ? item.alias : "无")).join("\n\n")}`;
690
+ });
691
+ }
692
+ __name(registerTagCommands, "registerTagCommands");
549
693
 
550
- ${exec.map((item) => "标签:" + item.tag + " 黑历史数:" + item.count + "\n别名:" + item.alias).join("\n")}`;
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();
551
755
  });
552
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;
781
+ });
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
+ }
553
814
  __name(apply, "apply");
554
815
  // Annotate the CommonJS export names for ESM import in node:
555
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,4 +1,5 @@
1
- declare function saveImg(tag_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
  }>;
@@ -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,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.2",
4
+ "version": "1.0.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "contributors": [