koishi-plugin-echo-cave 1.20.1 → 1.21.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.
@@ -11,5 +11,6 @@ export interface Config {
11
11
  maxRecordSize?: number;
12
12
  useBase64ForMedia?: boolean;
13
13
  sendAllAsForwardMsg?: boolean;
14
+ rankingTopCount?: number;
14
15
  }
15
16
  export declare const Config: Schema<Config>;
@@ -0,0 +1,5 @@
1
+ import { Config } from '../../config/config';
2
+ import { Context, Session } from 'koishi';
3
+ export type Period = 'day' | 'week' | 'month' | 'all';
4
+ export declare const SUPPORTED_PERIODS: Period[];
5
+ export declare function getRanking(ctx: Context, session: Session, cfg: Config, period?: string): Promise<void>;
package/lib/index.cjs CHANGED
@@ -43,7 +43,8 @@ var require_zh_CN = __commonJS({
43
43
  maxFileSize: "\u6700\u5927\u6587\u4EF6\u5927\u5C0F (MB)",
44
44
  maxRecordSize: "\u6700\u5927\u5F55\u97F3\u5927\u5C0F (MB)",
45
45
  useBase64ForMedia: "\u662F\u5426\u4F7F\u7528 Base64 \u7F16\u7801\u53D1\u9001\u5A92\u4F53\u6587\u4EF6\uFF0C\u5F00\u542F\u540E\u5C06\u8BFB\u53D6 base64 \u7F16\u7801\u53D1\u9001\u800C\u4E0D\u662F\u4F7F\u7528 file uri",
46
- sendAllAsForwardMsg: "\u662F\u5426\u5C06\u6240\u6709\u6D88\u606F\u4EE5\u8F6C\u53D1\u6D88\u606F\u5F62\u5F0F\u53D1\u9001\uFF0C\u5F00\u542F\u540E\u666E\u901A\u6D88\u606F\u4E5F\u4F1A\u8F6C\u6362\u4E3A\u8F6C\u53D1\u6D88\u606F\u683C\u5F0F"
46
+ sendAllAsForwardMsg: "\u662F\u5426\u5C06\u6240\u6709\u6D88\u606F\u4EE5\u8F6C\u53D1\u6D88\u606F\u5F62\u5F0F\u53D1\u9001\uFF0C\u5F00\u542F\u540E\u666E\u901A\u6D88\u606F\u4E5F\u4F1A\u8F6C\u6362\u4E3A\u8F6C\u53D1\u6D88\u606F\u683C\u5F0F",
47
+ rankingTopCount: "\u6392\u884C\u699C\u663E\u793A\u7684\u7528\u6237\u6570\u91CF"
47
48
  };
48
49
  }
49
50
  });
@@ -173,6 +174,22 @@ var require_zh_CN2 = __commonJS({
173
174
  msgNotFound: "\u{1F50D} \u672A\u627E\u5230\u8BE5 ID \u7684\u56DE\u58F0\u6D1E\u6D88\u606F",
174
175
  userBoundSuccess: "\u2705 \u5DF2\u6210\u529F\u5C06\u7528\u6237\u7ED1\u5B9A\u5230\u56DE\u58F0\u6D1E #{0}\uFF01"
175
176
  }
177
+ },
178
+ "cave.ranking": {
179
+ description: "\u67E5\u770B\u56DE\u58F0\u6D1E\u6392\u884C\u699C",
180
+ messages: {
181
+ invalidPeriod: "\u65E0\u6548\u7684\u65F6\u95F4\u6BB5\u53C2\u6570\u3002\u652F\u6301\u7684\u65F6\u95F4\u6BB5\uFF1A{0}",
182
+ rankingTitle: "\u{1F4CA} \u56DE\u58F0\u6D1E\u6392\u884C\u699C\uFF08{0}\uFF09",
183
+ noData: "\u6682\u65E0\u6570\u636E",
184
+ rankFormat: "{0} {1}\uFF1A{2} \u4E2A\u56DE\u58F0\u6D1E",
185
+ rankingHeader: "\u4ECA\u65E5\u4EBA\u54C1\u6392\u884C\u699C",
186
+ period: {
187
+ day: "24\u5C0F\u65F6",
188
+ week: "7\u5929",
189
+ month: "1\u4E2A\u6708",
190
+ all: "\u6240\u6709\u65F6\u95F4"
191
+ }
192
+ }
176
193
  }
177
194
  }
178
195
  };
@@ -680,6 +697,16 @@ function createTextMsg(content) {
680
697
  }
681
698
  };
682
699
  }
700
+ function createTextMsgNode(userId, nickname, content) {
701
+ return {
702
+ type: "node",
703
+ data: {
704
+ user_id: userId,
705
+ nickname,
706
+ content
707
+ }
708
+ };
709
+ }
683
710
 
684
711
  // src/core/formatter/msg-formatter.ts
685
712
  async function sendCaveMsg(ctx, session, caveMsg, cfg) {
@@ -868,6 +895,105 @@ async function bindUsersToCave(ctx, session, id, userIds) {
868
895
  return session.text(".userBoundSuccess", [id]);
869
896
  }
870
897
 
898
+ // src/core/command/ranking.ts
899
+ var SUPPORTED_PERIODS = ["day", "week", "month", "all"];
900
+ function getStartTime(period) {
901
+ const now = /* @__PURE__ */ new Date();
902
+ const startTime = /* @__PURE__ */ new Date();
903
+ switch (period) {
904
+ case "day":
905
+ startTime.setDate(now.getDate() - 1);
906
+ break;
907
+ case "week":
908
+ startTime.setDate(now.getDate() - 7);
909
+ break;
910
+ case "month":
911
+ startTime.setMonth(now.getMonth() - 1);
912
+ break;
913
+ case "all":
914
+ startTime.setTime(0);
915
+ break;
916
+ }
917
+ return startTime;
918
+ }
919
+ function countUserOccurrences(caves) {
920
+ const countMap = /* @__PURE__ */ new Map();
921
+ caves.forEach((cave) => {
922
+ cave.relatedUsers.forEach((userId) => {
923
+ countMap.set(userId, (countMap.get(userId) || 0) + 1);
924
+ });
925
+ countMap.set(cave.originUserId, (countMap.get(cave.originUserId) || 0) + 1);
926
+ });
927
+ return countMap;
928
+ }
929
+ async function generateRankingText(ctx, session, countMap, period, topCount) {
930
+ const sortedUsers = Array.from(countMap.entries()).sort(([, a], [, b]) => b - a).slice(0, topCount);
931
+ const periodText = session.text(`.period.${period}`);
932
+ let text = session.text(".rankingTitle", [periodText]) + "\n\n";
933
+ if (sortedUsers.length === 0) {
934
+ text += session.text(".noData");
935
+ } else {
936
+ for (let i = 0; i < sortedUsers.length; i++) {
937
+ const [userId, count] = sortedUsers[i];
938
+ const userName = await getUserName(ctx, session, userId);
939
+ const rank = i + 1;
940
+ let rankEmoji = "";
941
+ switch (rank) {
942
+ case 1:
943
+ rankEmoji = "\u{1F947}";
944
+ break;
945
+ case 2:
946
+ rankEmoji = "\u{1F948}";
947
+ break;
948
+ case 3:
949
+ rankEmoji = "\u{1F949}";
950
+ break;
951
+ default:
952
+ rankEmoji = `#${rank}`;
953
+ }
954
+ text += session.text(".rankFormat", [rankEmoji, userName, count]) + "\n";
955
+ }
956
+ }
957
+ return text;
958
+ }
959
+ async function getRanking(ctx, session, cfg, period = "all") {
960
+ if (!session.guildId) {
961
+ await session.send(session.text("echo-cave.general.privateChatReminder"));
962
+ return;
963
+ }
964
+ const normalizedPeriod = period.toLowerCase();
965
+ if (!SUPPORTED_PERIODS.includes(normalizedPeriod)) {
966
+ await session.send(session.text(".invalidPeriod", [SUPPORTED_PERIODS.join(", ")]));
967
+ return;
968
+ }
969
+ const { channelId } = session;
970
+ const startTime = getStartTime(normalizedPeriod);
971
+ const topCount = cfg.rankingTopCount || 10;
972
+ const caves = await ctx.database.get("echo_cave_v2", {
973
+ channelId,
974
+ createTime: {
975
+ $gte: startTime
976
+ }
977
+ });
978
+ const countMap = countUserOccurrences(caves);
979
+ const rankingText = await generateRankingText(
980
+ ctx,
981
+ session,
982
+ countMap,
983
+ normalizedPeriod,
984
+ topCount
985
+ );
986
+ const botName = await getUserName(this.ctx, session, session.bot?.userId) || "Bot";
987
+ await session.onebot.sendGroupForwardMsg(channelId, [
988
+ createTextMsgNode(
989
+ session.bot?.userId || session.userId,
990
+ botName,
991
+ session.text(".rankingHeader")
992
+ ),
993
+ createTextMsgNode(session.bot?.userId || session.userId, botName, rankingText)
994
+ ]);
995
+ }
996
+
871
997
  // src/core/command/search-cave.ts
872
998
  async function searchCave(ctx, session, userIds) {
873
999
  if (!session.guildId) {
@@ -917,7 +1043,8 @@ var Config = import_koishi2.Schema.object({
917
1043
  maxFileSize: import_koishi2.Schema.number().default(512),
918
1044
  maxRecordSize: import_koishi2.Schema.number().default(512),
919
1045
  useBase64ForMedia: import_koishi2.Schema.boolean().default(false),
920
- sendAllAsForwardMsg: import_koishi2.Schema.boolean().default(false)
1046
+ sendAllAsForwardMsg: import_koishi2.Schema.boolean().default(false),
1047
+ rankingTopCount: import_koishi2.Schema.number().default(10)
921
1048
  }).i18n({
922
1049
  "zh-CN": require_zh_CN()
923
1050
  });
@@ -993,6 +1120,9 @@ function apply(ctx, cfg) {
993
1120
  ctx.command("cave.bind <id:number> <...userIds>", { authority: 4 }).action(
994
1121
  async ({ session }, id, ...userIds) => await bindUsersToCave(ctx, session, id, userIds)
995
1122
  );
1123
+ ctx.command("cave.ranking [period:string]").action(
1124
+ async ({ session }, period) => await getRanking(ctx, session, cfg, period)
1125
+ );
996
1126
  }
997
1127
  // Annotate the CommonJS export names for ESM import in node:
998
1128
  0 && (module.exports = {
@@ -4,3 +4,11 @@ export declare function createTextMsg(content: string): {
4
4
  text: string;
5
5
  };
6
6
  };
7
+ export declare function createTextMsgNode(userId: string, nickname: string, content: string): {
8
+ type: string;
9
+ data: {
10
+ user_id: string;
11
+ nickname: string;
12
+ content: string;
13
+ };
14
+ };
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.20.1",
4
+ "version": "1.21.0",
5
5
  "main": "lib/index.cjs",
6
6
  "typings": "lib/index.d.ts",
7
7
  "type": "module",
@@ -45,8 +45,8 @@
45
45
  "conventional-changelog-conventionalcommits": "^9.1.0",
46
46
  "esbuild": "^0.27.1",
47
47
  "esbuild-plugin-yaml": "^0.0.1",
48
- "oxfmt": "^0.16.0",
49
- "oxlint": "^1.31.0",
48
+ "oxfmt": "^0.17.0",
49
+ "oxlint": "^1.32.0",
50
50
  "semantic-release": "^25.0.2",
51
51
  "typescript": "^5.9.3"
52
52
  }