koishi-plugin-echo-cave 1.18.5 → 1.19.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/README.md CHANGED
@@ -11,19 +11,13 @@
11
11
  ## ✨ 功能特性
12
12
 
13
13
  - 📥 **消息存储**:支持存储普通消息和转发消息到数据库
14
- - 🖼️ **图片保存**:自动保存消息中的图片资源到本地
15
14
  - 🔍 **消息查询**:支持随机获取消息或通过 ID 精确查找
16
15
  - 🗑️ **消息管理**:支持删除特定 ID 的消息(消息存储者、原始发送者或管理员)
17
- - 📊 **数据持久化**:使用 Koishi 数据库系统,确保数据不会丢失
18
16
  - 👤 **个人追踪**:支持查看自己投稿的消息列表
19
17
  - 🔍 **发言回溯**:支持查看自己被他人投稿的消息列表
20
- - 🎨 **精美展示**:消息展示时自带多种风格的外部包裹信息,显示消息详情
21
- - 🔒 **管理员保护**:可配置管理员消息保护,确保管理员发布的消息安全
18
+ - 🎨 **模板化展示**:消息展示时自带多种风格的外部包裹信息
19
+ - 🔒 **管理员保护**:可配置管理员消息保护
22
20
  - 📏 **媒体限制**:支持配置媒体文件大小限制
23
- - 🌐 **多语言支持**:支持中文语言包
24
- - 🔄 **嵌套转发**:支持嵌套转发消息的递归处理
25
- - 📝 **模板化展示**:支持多种风格的消息展示模板
26
- - 🔁 **重复检测**:自动检测重复消息,避免存储重复内容
27
21
 
28
22
  ## 📋 命令列表
29
23
 
@@ -32,13 +26,13 @@
32
26
  | `cave` | 随机获取一条回声洞消息 | 所有人 |
33
27
  | `cave <id>` | 获取特定 ID 的回声洞消息 | 所有人 |
34
28
  | `cave.echo` | 将引用的消息存入回声洞 | 所有人 |
35
- | `cave.wipe <id>` | 删除特定 ID 的回声洞消息 | 消息存储者、原始发送者或管理员 |
29
+ | `cave.drop <id>` | 删除特定 ID 的回声洞消息 | 消息存储者、原始发送者或管理员 |
36
30
  | `cave.listen` | 获取自己投稿的回声洞列表 | 所有人 |
37
31
  | `cave.trace` | 获取自己发言被投稿的回声洞列表 | 所有人 |
38
32
 
39
33
  ## 🚀 使用指南
40
34
 
41
- ### 1. 安装插件
35
+ ### 安装插件
42
36
 
43
37
  ```bash
44
38
  npm install koishi-plugin-echo-cave
@@ -46,24 +40,6 @@ npm install koishi-plugin-echo-cave
46
40
 
47
41
  或在插件商城中搜索 `koishi-plugin-echo-cave` 进行安装。
48
42
 
49
- ### 2. 基本使用
50
-
51
- 1. **存储消息**:在群聊中引用一条消息,然后发送命令 `cave.echo`
52
- 2. **查看随机消息**:发送命令 `cave` 获取一条随机消息
53
- 3. **查看特定消息**:发送命令 `cave <id>` 查看指定 ID 的消息
54
- 4. **删除消息**:消息存储者、原始发送者或管理员发送命令 `cave.wipe <id>` 删除指定 ID 的消息
55
- 5. **查看自己的投稿**:发送命令 `cave.listen` 查看自己曾经存入的所有回声洞消息
56
- 6. **查看自己的发言**:发送命令 `cave.trace` 查看自己曾经被他人存入的回声洞消息
57
-
58
- ## 🔧 技术说明
59
-
60
- - 插件使用 Koishi 数据库系统存储消息记录
61
- - 支持嵌套转发消息的处理
62
- - 自动检测重复消息,避免存储重复内容
63
- - 支持媒体文件大小限制
64
- - 支持多语言配置(中文)
65
- - 支持嵌套转发消息的递归处理
66
-
67
43
  ## 🛠️ 配置选项
68
44
 
69
45
  | 配置项 | 类型 | 默认值 | 说明 |
package/lib/index.cjs CHANGED
@@ -155,16 +155,14 @@ var require_zh_CN2 = __commonJS({
155
155
  description: "\u83B7\u5F97\u7531\u81EA\u5DF1\u6295\u7A3F\u7684\u56DE\u58F0\u6D1E\u5217\u8868",
156
156
  messages: {
157
157
  noMsgContributed: '\u{1F680} \u60A8\u5728\u56DE\u58F0\u6D1E\u4E2D\u6682\u65E0\u6295\u7A3F\uFF0C\u5FEB\u4F7F\u7528 "cave.echo" \u547D\u4EE4\u6DFB\u52A0\u7B2C\u4E00\u6761\u6D88\u606F\u5427\uFF01',
158
- msgListHeader: "\u{1F4DC} \u60A8\u5728\u672C\u9891\u9053\u6295\u7A3F\u7684\u56DE\u58F0\u6D1E\u6D88\u606F\u5217\u8868\uFF1A",
159
- msgListItem: "ID: {0} | \u521B\u5EFA\u65F6\u95F4\uFF1A{1}"
158
+ msgListHeader: "\u{1F4DC} \u60A8\u5728\u672C\u9891\u9053\u6295\u7A3F\u7684\u56DE\u58F0\u6D1E\u6D88\u606F\u5217\u8868\uFF1A"
160
159
  }
161
160
  },
162
161
  "cave.trace": {
163
162
  description: "\u83B7\u5F97\u81EA\u5DF1\u53D1\u8A00\u7684\u56DE\u58F0\u6D1E\u5217\u8868",
164
163
  messages: {
165
164
  noMsgTraced: '\u{1F680} \u60A8\u5728\u56DE\u58F0\u6D1E\u4E2D\u6682\u65E0\u53D1\u8A00\u88AB\u6295\u7A3F\uFF0C\u5FEB\u4F7F\u7528 "cave.echo" \u547D\u4EE4\u6DFB\u52A0\u7B2C\u4E00\u6761\u6D88\u606F\u5427\uFF01',
166
- msgListHeader: "\u{1F4DC} \u60A8\u5728\u672C\u9891\u9053\u53D1\u8A00\u7684\u56DE\u58F0\u6D1E\u6D88\u606F\u5217\u8868\uFF1A",
167
- msgListItem: "ID: {0} | \u521B\u5EFA\u65F6\u95F4\uFF1A{1}"
165
+ msgListHeader: "\u{1F4DC} \u60A8\u5728\u672C\u9891\u9053\u53D1\u8A00\u7684\u56DE\u58F0\u6D1E\u6D88\u606F\u5217\u8868\uFF1A"
168
166
  }
169
167
  },
170
168
  "cave.bind": {
@@ -510,9 +508,11 @@ async function addCave(ctx, session, cfg, userIds) {
510
508
  return session.text("echo-cave.user.invalidAllMention");
511
509
  }
512
510
  parsedUserIds = result.parsedUserIds;
513
- const isAllUsersInGroup = await checkUsersInGroup(ctx, session, parsedUserIds);
514
- if (!isAllUsersInGroup) {
515
- return session.text(".userNotInGroup");
511
+ if (parsedUserIds.length > 0) {
512
+ const isAllUsersInGroup = await checkUsersInGroup(ctx, session, parsedUserIds);
513
+ if (!isAllUsersInGroup) {
514
+ return session.text("echo-cave.user.userNotInGroup");
515
+ }
516
516
  }
517
517
  }
518
518
  let content;
@@ -540,13 +540,13 @@ async function addCave(ctx, session, cfg, userIds) {
540
540
  }
541
541
  content = JSON.stringify(await processMessageContent(ctx, msgJson, cfg));
542
542
  }
543
- await ctx.database.get("echo_cave", { content }).then((existing) => {
543
+ await ctx.database.get("echo_cave_v2", { content }).then((existing) => {
544
544
  if (existing) {
545
545
  return session.text(".existingMsg");
546
546
  }
547
547
  });
548
548
  try {
549
- const result = await ctx.database.create("echo_cave", {
549
+ const result = await ctx.database.create("echo_cave_v2", {
550
550
  channelId,
551
551
  createTime: /* @__PURE__ */ new Date(),
552
552
  userId,
@@ -569,7 +569,7 @@ async function deleteCave(ctx, session, cfg, id) {
569
569
  if (!id) {
570
570
  return session.text(".noIdProvided");
571
571
  }
572
- const caves = await ctx.database.get("echo_cave", id);
572
+ const caves = await ctx.database.get("echo_cave_v2", id);
573
573
  if (caves.length === 0) {
574
574
  return session.text("echo-cave.general.noMsgWithId");
575
575
  }
@@ -601,7 +601,7 @@ async function deleteCave(ctx, session, cfg, id) {
601
601
  if (cfg.deleteMediaWhenDeletingMsg) {
602
602
  await deleteMediaFilesFromMessage(ctx, caveMsg.content);
603
603
  }
604
- await ctx.database.remove("echo_cave", id);
604
+ await ctx.database.remove("echo_cave_v2", id);
605
605
  return session.text(".msgDeleted", [id]);
606
606
  }
607
607
  async function deleteCaves(ctx, session, cfg, ids) {
@@ -616,7 +616,7 @@ async function deleteCaves(ctx, session, cfg, ids) {
616
616
  const user = await ctx.database.getUser(session.platform, currentUserId);
617
617
  const userAuthority = user.authority;
618
618
  const isCurrentUserAdmin = userAuthority >= 4;
619
- const caves = await ctx.database.get("echo_cave", ids);
619
+ const caves = await ctx.database.get("echo_cave_v2", ids);
620
620
  for (const cave of caves) {
621
621
  const caveMsg = caves[0];
622
622
  if (cfg.adminMessageProtection) {
@@ -642,7 +642,7 @@ async function deleteCaves(ctx, session, cfg, ids) {
642
642
  if (cfg.deleteMediaWhenDeletingMsg) {
643
643
  await deleteMediaFilesFromMessage(ctx, caveMsg.content);
644
644
  }
645
- await ctx.database.remove("echo_cave", cave.id);
645
+ await ctx.database.remove("echo_cave_v2", cave.id);
646
646
  }
647
647
  const foundIds = new Set(caves.map((r) => r.id));
648
648
  const missingIds = ids.filter((id) => !foundIds.has(id));
@@ -744,36 +744,38 @@ async function getCaveListByUser(ctx, session) {
744
744
  return session.text("echo-cave.general.privateChatReminder");
745
745
  }
746
746
  const { userId, channelId } = session;
747
- const caves = await ctx.database.get("echo_cave", {
748
- userId,
749
- channelId
750
- });
747
+ const caves = await ctx.database.get(
748
+ "echo_cave_v2",
749
+ {
750
+ userId,
751
+ channelId
752
+ },
753
+ ["id"]
754
+ );
751
755
  if (caves.length === 0) {
752
756
  return session.text(".noMsgContributed");
753
757
  }
754
- let response = session.text(".msgListHeader") + "\n";
755
- for (const cave of caves) {
756
- response += session.text(".msgListItem", [cave.id, formatDate(cave.createTime)]) + "\n";
757
- }
758
- return response;
758
+ const ids = caves.map((cave) => cave.id).join(" | ");
759
+ return session.text(".msgListHeader") + "\n" + ids;
759
760
  }
760
761
  async function getCaveListByOriginUser(ctx, session) {
761
762
  if (!session.guildId) {
762
763
  return session.text("echo-cave.general.privateChatReminder");
763
764
  }
764
765
  const { userId, channelId } = session;
765
- const caves = await ctx.database.get("echo_cave", {
766
- originUserId: userId,
767
- channelId
768
- });
766
+ const caves = await ctx.database.get(
767
+ "echo_cave_v2",
768
+ {
769
+ originUserId: userId,
770
+ channelId
771
+ },
772
+ ["id"]
773
+ );
769
774
  if (caves.length === 0) {
770
775
  return session.text(".noMsgTraced");
771
776
  }
772
- let response = session.text(".msgListHeader") + "\n";
773
- for (const cave of caves) {
774
- response += session.text(".msgListItem", [cave.id, formatDate(cave.createTime)]) + "\n";
775
- }
776
- return response;
777
+ const ids = caves.map((cave) => cave.id).join(" | ");
778
+ return session.text(".msgListHeader") + "\n" + ids;
777
779
  }
778
780
  async function getCave(ctx, session, cfg, id) {
779
781
  if (!session.guildId) {
@@ -782,7 +784,7 @@ async function getCave(ctx, session, cfg, id) {
782
784
  let caveMsg;
783
785
  const { channelId } = session;
784
786
  if (!id) {
785
- const caves = await ctx.database.get("echo_cave", {
787
+ const caves = await ctx.database.get("echo_cave_v2", {
786
788
  channelId
787
789
  });
788
790
  if (caves.length === 0) {
@@ -790,7 +792,7 @@ async function getCave(ctx, session, cfg, id) {
790
792
  }
791
793
  caveMsg = caves[Math.floor(Math.random() * caves.length)];
792
794
  } else {
793
- const caves = await ctx.database.get("echo_cave", {
795
+ const caves = await ctx.database.get("echo_cave_v2", {
794
796
  id,
795
797
  channelId
796
798
  });
@@ -821,7 +823,7 @@ async function bindUsersToCave(ctx, session, id, userIds) {
821
823
  if (parsedUserIds.length === 0) {
822
824
  return session.text(".noValidUserIdProvided");
823
825
  }
824
- const caves = await ctx.database.get("echo_cave", id);
826
+ const caves = await ctx.database.get("echo_cave_v2", id);
825
827
  if (caves.length === 0) {
826
828
  return session.text("echo-cave.general.noMsgWithId");
827
829
  }
@@ -829,7 +831,7 @@ async function bindUsersToCave(ctx, session, id, userIds) {
829
831
  if (!isAllUsersInGroup) {
830
832
  return session.text("echo-cave.user.userNotInGroup");
831
833
  }
832
- await ctx.database.set("echo_cave", id, {
834
+ await ctx.database.set("echo_cave_v2", id, {
833
835
  relatedUsers: parsedUserIds
834
836
  });
835
837
  return session.text(".userBoundSuccess", [id]);
@@ -857,7 +859,7 @@ async function searchCave(ctx, session, userIds) {
857
859
  }
858
860
  const targetUserId = parsedUserIds[0];
859
861
  const { channelId } = session;
860
- const caves = await ctx.database.get("echo_cave", {
862
+ const caves = await ctx.database.get("echo_cave_v2", {
861
863
  channelId
862
864
  });
863
865
  const matchingCaves = caves.filter(
@@ -910,6 +912,33 @@ function apply(ctx, cfg) {
910
912
  autoInc: true
911
913
  }
912
914
  );
915
+ ctx.model.extend(
916
+ "echo_cave_v2",
917
+ {
918
+ id: "unsigned",
919
+ channelId: "string",
920
+ createTime: "timestamp",
921
+ userId: "string",
922
+ originUserId: "string",
923
+ type: "string",
924
+ content: "text",
925
+ relatedUsers: "list"
926
+ },
927
+ {
928
+ primary: "id",
929
+ autoInc: true
930
+ }
931
+ );
932
+ ctx.model.migrate(
933
+ "echo_cave",
934
+ {
935
+ id: "unsigned"
936
+ },
937
+ async (database) => {
938
+ const data = await database.get("echo_cave", {});
939
+ await database.upsert("echo_cave_v2", data);
940
+ }
941
+ );
913
942
  ctx.command("cave [id:number]").action(
914
943
  async ({ session }, id) => await getCave(ctx, session, cfg, id)
915
944
  );
package/lib/index.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface EchoCave {
17
17
  declare module 'koishi' {
18
18
  interface Tables {
19
19
  echo_cave: EchoCave;
20
+ echo_cave_v2: EchoCave;
20
21
  }
21
22
  }
22
23
  export declare function apply(ctx: Context, cfg: Config): void;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-echo-cave",
3
3
  "description": "Group echo cave",
4
- "version": "1.18.5",
4
+ "version": "1.19.0",
5
5
  "main": "lib/index.cjs",
6
6
  "typings": "lib/index.d.ts",
7
7
  "type": "module",