koishi-plugin-echo-cave 1.29.14 → 1.30.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
@@ -21,6 +21,7 @@
21
21
  - 📏 **媒体限制**:支持配置媒体文件大小限制
22
22
  - 👥 **转发消息用户选择**:支持从转发消息中选择相关用户进行绑定
23
23
  - 🎯 **按人随机抽取**:支持通过 `@用户` 或用户 ID 定向随机抽取该用户相关的回声洞,且不影响全局抽取权重
24
+ - 🖼️ **图片回声洞抽取**:支持通过 `cave.pic` 单独随机抽取包含图片的普通消息,并使用独立的图片抽取计数参与加权随机
24
25
  - 🧭 **转发绑定体验优化**:转发消息关联用户的详细输入指南仅在用户首次成功完成选择前显示,选择完成或超时后会尝试撤回提示消息
25
26
  - 🤖 **特殊转发用户处理**:可配置在检测到转发记录中包含特殊用户 `1094950020` 时直接拒绝存储,或要求二次确认后再存储
26
27
  - 🛠️ **回声洞 ID 重排**:提供管理员维护命令,可在写入备份后安全重排现有回声洞 public ID,而不抬高数据库内部自增主键
@@ -32,6 +33,7 @@
32
33
  概率 = 权重 / 总权重
33
34
  ```
34
35
  其中,`drawCount` 为消息被抽取次数,`α` 为调整因子(可配置,默认0.2)
36
+ `cave.pic` 仅抽取 `type=msg` 且消息内容中包含图片元素的回声洞,并使用独立的 `picDrawCount` 按同一公式计算权重,不影响普通 `cave` 命令使用的 `drawCount`
35
37
 
36
38
  ## 📋 命令列表
37
39
 
@@ -40,6 +42,7 @@
40
42
  | `cave` | 随机获取一条回声洞消息 | 所有人 |
41
43
  | `cave <id>` | 获取特定 ID 的回声洞消息 | 所有人 |
42
44
  | `cave <@用户/用户ID>` | 随机获取与该用户相关的一条回声洞消息(不计入抽取次数) | 所有人 |
45
+ | `cave.pic` | 随机获取一条包含图片的回声洞消息 | 所有人 |
43
46
  | `cave.echo [...userIds]` | 将引用的消息存入回声洞 | 所有人 |
44
47
  | `cave.drop <id>` | 删除特定 ID 的回声洞消息 | 消息存储者、原始发送者或管理员 |
45
48
  | `cave.listen` | 获取自己投稿的回声洞列表 | 所有人 |
@@ -90,6 +93,7 @@ npm install koishi-plugin-echo-cave
90
93
  - 插件仅在群聊中可用,私聊模式下无法正常工作
91
94
  - 使用 `cave.echo` 命令前必须先引用一条消息
92
95
  - 使用 `cave @用户`、`cave <用户ID>` 可定向随机抽取该用户相关的回声洞,这类抽取不会增加 `drawCount`
96
+ - 使用 `cave.pic` 会单独增加图片抽取计数 `picDrawCount`,不会影响普通 `cave` 使用的 `drawCount`
93
97
  - 删除消息权限可通过配置项灵活控制
94
98
  - 存储的消息会保留原始发送者信息
95
99
  - 支持媒体文件大小限制,可通过配置项调整
@@ -11,6 +11,7 @@ export interface CaveSnapshotRecord {
11
11
  content: string;
12
12
  relatedUsers: string[];
13
13
  drawCount: number;
14
+ picDrawCount: number;
14
15
  }
15
16
  export interface CaveBackupRecord extends CaveSnapshotRecord {
16
17
  entryId?: number;
@@ -2,4 +2,4 @@ import { Config } from '../../config/config';
2
2
  import { Context, Session } from 'koishi';
3
3
  export declare function getCaveListByUser(ctx: Context, session: Session): Promise<string>;
4
4
  export declare function getCaveListByOriginUser(ctx: Context, session: Session): Promise<string>;
5
- export declare function getCave(ctx: Context, session: Session, cfg: Config, target?: string): Promise<string>;
5
+ export declare function getCave(ctx: Context, session: Session, cfg: Config, target?: string, pictureOnly?: boolean): Promise<string>;
package/lib/index.cjs CHANGED
@@ -33321,9 +33321,9 @@ var require_dist_cjs72 = __commonJS({
33321
33321
  }
33322
33322
  });
33323
33323
 
33324
- // node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1029.0/node_modules/@aws-sdk/s3-request-presigner/dist-cjs/index.js
33324
+ // node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1030.0/node_modules/@aws-sdk/s3-request-presigner/dist-cjs/index.js
33325
33325
  var require_dist_cjs73 = __commonJS({
33326
- "node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1029.0/node_modules/@aws-sdk/s3-request-presigner/dist-cjs/index.js"(exports2) {
33326
+ "node_modules/.pnpm/@aws-sdk+s3-request-presigner@3.1030.0/node_modules/@aws-sdk/s3-request-presigner/dist-cjs/index.js"(exports2) {
33327
33327
  "use strict";
33328
33328
  var utilFormatUrl = require_dist_cjs72();
33329
33329
  var middlewareEndpoint = require_dist_cjs45();
@@ -33470,7 +33470,8 @@ function toCaveSnapshotRecord(cave) {
33470
33470
  type: cave.type,
33471
33471
  content: cave.content,
33472
33472
  relatedUsers: [...cave.relatedUsers],
33473
- drawCount: cave.drawCount
33473
+ drawCount: cave.drawCount,
33474
+ picDrawCount: cave.picDrawCount ?? 0
33474
33475
  };
33475
33476
  }
33476
33477
  function toCaveBackupRecord(cave) {
@@ -33509,7 +33510,8 @@ async function createCaveRecord(ctx, cave) {
33509
33510
  type: cave.type,
33510
33511
  content: cave.content,
33511
33512
  relatedUsers: [...cave.relatedUsers],
33512
- drawCount: cave.drawCount
33513
+ drawCount: cave.drawCount,
33514
+ picDrawCount: cave.picDrawCount ?? 0
33513
33515
  });
33514
33516
  }
33515
33517
  async function updateCaveByEntryId(ctx, entryId, data2) {
@@ -34805,7 +34807,8 @@ async function mergeChannelCaves(ctx, cfg, sourceChannelId, targetChannelId, kee
34805
34807
  type: cave.type,
34806
34808
  content: rewritten.content,
34807
34809
  relatedUsers: cave.relatedUsers,
34808
- drawCount: cave.drawCount
34810
+ drawCount: cave.drawCount,
34811
+ picDrawCount: cave.picDrawCount ?? 0
34809
34812
  });
34810
34813
  } else {
34811
34814
  if (typeof cave.entryId !== "number") {
@@ -34966,6 +34969,7 @@ function normalizeCaveRecord(cave) {
34966
34969
  content: cave.content,
34967
34970
  createTime: new Date(cave.createTime).toISOString(),
34968
34971
  drawCount: cave.drawCount,
34972
+ picDrawCount: cave.picDrawCount ?? 0,
34969
34973
  id: cave.id,
34970
34974
  originUserId: cave.originUserId,
34971
34975
  relatedUsers: [...cave.relatedUsers],
@@ -34986,7 +34990,7 @@ function isEchoCaveRecord(value) {
34986
34990
  if (!isRecordObject(value)) {
34987
34991
  return false;
34988
34992
  }
34989
- return typeof value.id === "number" && typeof value.channelId === "string" && (value.createTime instanceof Date || typeof value.createTime === "string" || typeof value.createTime === "number") && typeof value.userId === "string" && typeof value.originUserId === "string" && (value.type === "forward" || value.type === "msg") && typeof value.content === "string" && Array.isArray(value.relatedUsers) && value.relatedUsers.every((user) => typeof user === "string") && typeof value.drawCount === "number";
34993
+ return typeof value.id === "number" && typeof value.channelId === "string" && (value.createTime instanceof Date || typeof value.createTime === "string" || typeof value.createTime === "number") && typeof value.userId === "string" && typeof value.originUserId === "string" && (value.type === "forward" || value.type === "msg") && typeof value.content === "string" && Array.isArray(value.relatedUsers) && value.relatedUsers.every((user) => typeof user === "string") && typeof value.drawCount === "number" && (typeof value.picDrawCount === "number" || typeof value.picDrawCount === "undefined");
34990
34994
  }
34991
34995
  function isCaveBackupRecord(value) {
34992
34996
  if (!isEchoCaveRecord(value)) {
@@ -35747,7 +35751,8 @@ async function addCave(ctx, session, cfg, userIds) {
35747
35751
  originUserId: quote.user.id,
35748
35752
  type,
35749
35753
  content,
35750
- relatedUsers: finalParsedUserIds
35754
+ relatedUsers: finalParsedUserIds,
35755
+ picDrawCount: 0
35751
35756
  });
35752
35757
  return session.text(".msgSaved", { id: result.id, relatedUsers: relatedUsersFormatted });
35753
35758
  } catch (error2) {
@@ -36426,7 +36431,7 @@ async function getCaveIdsByField(ctx, session, field, emptyText) {
36426
36431
  }
36427
36432
  return session.text(".msgListHeader") + "\n" + formatCaveIdList(caves);
36428
36433
  }
36429
- async function incrementDrawCount(ctx, caveMsg) {
36434
+ async function incrementDrawCount(ctx, caveMsg, field = "drawCount") {
36430
36435
  await ctx.database.set(
36431
36436
  ACTIVE_CAVE_TABLE,
36432
36437
  {
@@ -36434,7 +36439,7 @@ async function incrementDrawCount(ctx, caveMsg) {
36434
36439
  channelId: caveMsg.channelId
36435
36440
  },
36436
36441
  {
36437
- drawCount: caveMsg.drawCount + 1
36442
+ [field]: (caveMsg[field] ?? 0) + 1
36438
36443
  }
36439
36444
  );
36440
36445
  }
@@ -36447,8 +36452,8 @@ async function getCaveListByOriginUser(ctx, session) {
36447
36452
  function selectRandomCave(caves) {
36448
36453
  return caves[Math.floor(Math.random() * caves.length)];
36449
36454
  }
36450
- function selectWeightedRandomCave(caves, alpha) {
36451
- const weights = caves.map((cave) => 1 / (1 + cave.drawCount * alpha));
36455
+ function selectWeightedRandomCave(caves, alpha, field = "drawCount") {
36456
+ const weights = caves.map((cave) => 1 / (1 + (cave[field] ?? 0) * alpha));
36452
36457
  const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
36453
36458
  let random = Math.random() * totalWeight;
36454
36459
  let selectedIndex = 0;
@@ -36458,6 +36463,17 @@ function selectWeightedRandomCave(caves, alpha) {
36458
36463
  }
36459
36464
  return caves[selectedIndex];
36460
36465
  }
36466
+ function isPictureMsgCave(cave) {
36467
+ if (cave.type !== "msg") {
36468
+ return false;
36469
+ }
36470
+ try {
36471
+ const content = JSON.parse(cave.content);
36472
+ return Array.isArray(content) && content.some((element) => element?.type === "image");
36473
+ } catch {
36474
+ return false;
36475
+ }
36476
+ }
36461
36477
  async function getTargetedUserCave(ctx, session, targetUserId) {
36462
36478
  const isUserInGroup = await checkUsersInGroup(ctx, session, [targetUserId]);
36463
36479
  if (!isUserInGroup) {
@@ -36474,7 +36490,7 @@ async function getTargetedUserCave(ctx, session, targetUserId) {
36474
36490
  }
36475
36491
  return selectRandomCave(matchingCaves);
36476
36492
  }
36477
- async function getCave(ctx, session, cfg, target) {
36493
+ async function getCave(ctx, session, cfg, target, pictureOnly = false) {
36478
36494
  const guildAccessError = ensureGuildSession2(session);
36479
36495
  if (guildAccessError) {
36480
36496
  return session.text(guildAccessError);
@@ -36485,16 +36501,21 @@ async function getCave(ctx, session, cfg, target) {
36485
36501
  }
36486
36502
  let caveMsg;
36487
36503
  let shouldIncrementDrawCount = true;
36504
+ const drawCountField = pictureOnly ? "picDrawCount" : "drawCount";
36488
36505
  const { channelId } = session;
36506
+ if (pictureOnly && target) {
36507
+ return session.text("echo-cave.general.noMsgWithId");
36508
+ }
36489
36509
  if (!target) {
36490
36510
  const caves = await ctx.database.get(ACTIVE_CAVE_TABLE, {
36491
36511
  channelId
36492
36512
  });
36493
- if (caves.length === 0) {
36494
- return session.text(".noMsgInCave");
36513
+ const selectableCaves = pictureOnly ? caves.filter(isPictureMsgCave) : caves;
36514
+ if (selectableCaves.length === 0) {
36515
+ return session.text(pictureOnly ? ".noPicMsgInCave" : ".noMsgInCave");
36495
36516
  }
36496
36517
  const alpha = cfg.alpha ?? 0.2;
36497
- caveMsg = selectWeightedRandomCave(caves, alpha);
36518
+ caveMsg = selectWeightedRandomCave(selectableCaves, alpha, drawCountField);
36498
36519
  } else {
36499
36520
  const trimmedTarget = target.trim();
36500
36521
  const parseResult = parseUserIds(trimmedTarget);
@@ -36515,7 +36536,7 @@ async function getCave(ctx, session, cfg, target) {
36515
36536
  } catch (error2) {
36516
36537
  return await handleCaveSendFailure(ctx, session, caveMsg, cfg, error2);
36517
36538
  }
36518
- await incrementDrawCount(ctx, caveMsg);
36539
+ await incrementDrawCount(ctx, caveMsg, drawCountField);
36519
36540
  return;
36520
36541
  }
36521
36542
  }
@@ -36538,7 +36559,7 @@ async function getCave(ctx, session, cfg, target) {
36538
36559
  return await handleCaveSendFailure(ctx, session, caveMsg, cfg, error2);
36539
36560
  }
36540
36561
  if (shouldIncrementDrawCount) {
36541
- await incrementDrawCount(ctx, caveMsg);
36562
+ await incrementDrawCount(ctx, caveMsg, drawCountField);
36542
36563
  }
36543
36564
  }
36544
36565
 
@@ -36855,6 +36876,12 @@ var zh_CN_default = {
36855
36876
  failureSummaryDetail: "#{caveId}\uFF08\u7FA4 {channelId}\uFF09\u5931\u8D25 {count} \u6B21\uFF0C\u6700\u8FD1 {lastFailTime}\uFF0C\u9519\u8BEF\uFF1A{errorMessage}"
36856
36877
  }
36857
36878
  },
36879
+ "cave.pic": {
36880
+ description: "\u968F\u673A\u83B7\u53D6\u4E00\u6761\u5305\u542B\u56FE\u7247\u7684\u56DE\u58F0\u6D1E\u6D88\u606F",
36881
+ messages: {
36882
+ noPicMsgInCave: '\u{1F5BC}\uFE0F \u5F53\u524D\u56DE\u58F0\u6D1E\u4E2D\u6682\u65E0\u5305\u542B\u56FE\u7247\u7684\u6D88\u606F\uFF0C\u5FEB\u4F7F\u7528 "cave.echo" \u6DFB\u52A0\u4E00\u6761\u5427\uFF01'
36883
+ }
36884
+ },
36858
36885
  "cave.echo": {
36859
36886
  description: "\u5C06\u6D88\u606F\u5B58\u5165\u56DE\u58F0\u6D1E",
36860
36887
  messages: {
@@ -37143,7 +37170,8 @@ function toV3Record(record) {
37143
37170
  type: record.type,
37144
37171
  content: record.content,
37145
37172
  relatedUsers: [...record.relatedUsers],
37146
- drawCount: record.drawCount
37173
+ drawCount: record.drawCount,
37174
+ picDrawCount: record.picDrawCount ?? 0
37147
37175
  };
37148
37176
  }
37149
37177
  function apply(ctx, cfg) {
@@ -37159,7 +37187,8 @@ function apply(ctx, cfg) {
37159
37187
  type: "string",
37160
37188
  content: "text",
37161
37189
  relatedUsers: "list",
37162
- drawCount: { type: "unsigned", initial: 0 }
37190
+ drawCount: { type: "unsigned", initial: 0 },
37191
+ picDrawCount: { type: "unsigned", initial: 0 }
37163
37192
  },
37164
37193
  {
37165
37194
  primary: "id",
@@ -37178,7 +37207,8 @@ function apply(ctx, cfg) {
37178
37207
  type: "string",
37179
37208
  content: "text",
37180
37209
  relatedUsers: "list",
37181
- drawCount: { type: "unsigned", initial: 0 }
37210
+ drawCount: { type: "unsigned", initial: 0 },
37211
+ picDrawCount: { type: "unsigned", initial: 0 }
37182
37212
  },
37183
37213
  {
37184
37214
  primary: "entryId",
@@ -37197,7 +37227,8 @@ function apply(ctx, cfg) {
37197
37227
  type: "string",
37198
37228
  content: "text",
37199
37229
  relatedUsers: "list",
37200
- drawCount: { type: "unsigned", initial: 0 }
37230
+ drawCount: { type: "unsigned", initial: 0 },
37231
+ picDrawCount: { type: "unsigned", initial: 0 }
37201
37232
  },
37202
37233
  {
37203
37234
  primary: "id",
@@ -37252,6 +37283,7 @@ function apply(ctx, cfg) {
37252
37283
  }
37253
37284
  });
37254
37285
  ctx.command("cave [target:text]").action(async ({ session }, target) => await getCave(ctx, session, cfg, target));
37286
+ ctx.command("cave.pic").action(async ({ session }) => await getCave(ctx, session, cfg, void 0, true));
37255
37287
  ctx.command("cave.listen").action(async ({ session }) => await getCaveListByUser(ctx, session));
37256
37288
  ctx.command("cave.trace").action(async ({ session }) => await getCaveListByOriginUser(ctx, session));
37257
37289
  ctx.command("cave.echo [...userIds]").action(async ({ session }, ...userIds) => await addCave(ctx, session, cfg, userIds));
package/lib/index.d.ts CHANGED
@@ -14,6 +14,7 @@ export interface EchoCave {
14
14
  content: string;
15
15
  relatedUsers: string[];
16
16
  drawCount: number;
17
+ picDrawCount: number;
17
18
  }
18
19
  export interface EchoCaveSendFailure {
19
20
  id: number;
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.29.14",
4
+ "version": "1.30.0",
5
5
  "main": "lib/index.cjs",
6
6
  "typings": "lib/index.d.ts",
7
7
  "type": "module",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "dependencies": {
39
39
  "@aws-sdk/client-s3": "^3.1029.0",
40
- "@aws-sdk/s3-request-presigner": "^3.1029.0",
40
+ "@aws-sdk/s3-request-presigner": "^3.1030.0",
41
41
  "@pynickle/koishi-plugin-adapter-onebot": "^1.0.0",
42
42
  "axios": "^1.15.0",
43
43
  "uuid": "^11.1.0"