koishi-plugin-lili-hub 0.3.1 → 0.3.2

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.
Files changed (2) hide show
  1. package/lib/index.js +121 -33
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -264,7 +264,6 @@ var Config = import_koishi.Schema.object({
264
264
  enabled: import_koishi.Schema.boolean().description("\u542F\u7528\u4E3D\u4E3D\u6298\u53E0\u529F\u80FD").default(false),
265
265
  groups: import_koishi.Schema.string().description("\u7FA4\u53F7\u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09").default(""),
266
266
  groupMode: import_koishi.Schema.union(["whitelist", "blacklist"]).description("\u7FA4\u7EC4\u8FC7\u6EE4\u6A21\u5F0F\uFF1A\u767D\u540D\u5355 / \u9ED1\u540D\u5355").default("whitelist"),
267
- adminOnly: import_koishi.Schema.boolean().description("\u4EC5\u7FA4\u4E3B\u548C\u7BA1\u7406\u5458\u53EF\u4EE5\u4F7F\u7528\u4E3D\u4E3D\u6298\u53E0").default(false),
268
267
  minutes: import_koishi.Schema.number().description("\u6298\u53E0\u65F6\u95F4\u8303\u56F4\uFF08\u5206\u949F\uFF09").default(10).min(1).max(1440)
269
268
  }).description("\u{1F4E6} \u4E3D\u4E3D\u6298\u53E0"),
270
269
  imitation: import_koishi.Schema.object({
@@ -288,7 +287,12 @@ var Config = import_koishi.Schema.object({
288
287
  drawTimeoutSeconds: import_koishi.Schema.number().description("\u62D4\u67AA\u7A97\u53E3\u8D85\u65F6\uFF08\u79D2\uFF09").default(10).min(3).max(60),
289
288
  earlyDrawMuteSeconds: import_koishi.Schema.number().description("\u63D0\u524D\u62D4\u67AA\u7981\u8A00\u65F6\u957F\uFF08\u79D2\uFF09").default(600).min(0).max(2592e3),
290
289
  lateMuteSeconds: import_koishi.Schema.number().description("\u665A\u62D4\u67AA/\u672A\u62D4\u67AA\u7981\u8A00\u65F6\u957F\uFF08\u79D2\uFF09").default(300).min(0).max(2592e3)
291
- }).description("\u2694\uFE0F \u4E3D\u4E3D\u5BF9\u51B3")
290
+ }).description("\u2694\uFE0F \u4E3D\u4E3D\u5BF9\u51B3"),
291
+ chain: import_koishi.Schema.object({
292
+ enabled: import_koishi.Schema.boolean().description("\u542F\u7528\u7FA4\u63A5\u9F99\u529F\u80FD").default(false),
293
+ groups: import_koishi.Schema.string().description("\u7FA4\u53F7\u5217\u8868\uFF08\u9017\u53F7\u5206\u9694\uFF09").default(""),
294
+ groupMode: import_koishi.Schema.union(["whitelist", "blacklist"]).description("\u7FA4\u7EC4\u8FC7\u6EE4\u6A21\u5F0F\uFF1A\u767D\u540D\u5355 / \u9ED1\u540D\u5355").default("whitelist")
295
+ }).description("\u{1F4DD} \u7FA4\u63A5\u9F99")
292
296
  });
293
297
  function getGroupId(session) {
294
298
  return session.guildId || session.channelId;
@@ -389,6 +393,15 @@ function apply(ctx, config) {
389
393
  const rouletteStates = /* @__PURE__ */ new Map();
390
394
  const imitationCounters = /* @__PURE__ */ new Map();
391
395
  const duelStates = /* @__PURE__ */ new Map();
396
+ const chainStates = /* @__PURE__ */ new Map();
397
+ function formatChain(chain) {
398
+ const lines = [chain.content];
399
+ for (let i = 0; i < chain.participants.length; i++) {
400
+ const p = chain.participants[i];
401
+ lines.push(`${i + 1}.${p.userName}\uFF08${p.userId}\uFF09`);
402
+ }
403
+ return lines.join("\n");
404
+ }
392
405
  function isDrunk(gid) {
393
406
  const s = drinkStates.get(gid);
394
407
  if (!s || s.drunkUntil === 0) return false;
@@ -709,26 +722,19 @@ ${import_koishi.segment.at(targetId)} \u5DF2\u88AB\u89E3\u9664\u7981\u8A00\u3002
709
722
  const fc = config.fold;
710
723
  if (!fc.enabled) return;
711
724
  if (!isGroupAllowed(gid, fc.groups, fc.groupMode)) return;
712
- if (fc.adminOnly) {
713
- try {
714
- const info = await session.bot.getGroupMemberInfo(gid, String(session.userId));
715
- if (!info || info.role !== "owner" && info.role !== "admin") {
716
- return "\u{1F4E6} \u4EC5\u7FA4\u4E3B\u6216\u7BA1\u7406\u5458\u53EF\u4EE5\u4F7F\u7528\u4E3D\u4E3D\u6298\u53E0\u529F\u80FD\u3002";
717
- }
718
- } catch {
719
- return "\u{1F4E6} \u65E0\u6CD5\u9A8C\u8BC1\u7BA1\u7406\u5458\u8EAB\u4EFD\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002";
720
- }
721
- }
722
725
  const targetId = extractTarget(session, targetUser);
723
726
  if (!targetId) return "\u{1F4E6} \u65E0\u6CD5\u89E3\u6790\u76EE\u6807\u7528\u6237\u3002\u8BF7\u4F7F\u7528 @ \u529F\u80FD\u6216\u76F4\u63A5\u8F93\u5165 QQ \u53F7\u3002";
724
727
  const foldedMinutes = typeof minutesArg === "number" && minutesArg >= 1 && minutesArg <= 1440 ? minutesArg : fc.minutes;
725
728
  const since = Date.now() - foldedMinutes * 60 * 1e3;
729
+ dbg("\u6298\u53E0-\u67E5\u8BE2", { gid, targetId, since: new Date(since).toLocaleTimeString("zh-CN"), foldedMinutes });
726
730
  let messages;
727
731
  try {
728
732
  messages = await ctx.database.get("lili_message", { gid, userId: targetId, timestamp: { $gte: since } }, { sort: { timestamp: "asc" }, limit: 100 });
729
- } catch {
733
+ } catch (e) {
734
+ dbg("\u6298\u53E0-\u67E5\u8BE2\u5931\u8D25", { gid, error: String(e) });
730
735
  return "\u{1F4E6} \u67E5\u8BE2\u6D88\u606F\u5931\u8D25\u3002";
731
736
  }
737
+ dbg("\u6298\u53E0-\u67E5\u8BE2\u7ED3\u679C", { gid, targetId, count: messages?.length || 0 });
732
738
  if (!messages || messages.length === 0) return `\u{1F4E6} ${import_koishi.segment.at(targetId)} \u6700\u8FD1 ${foldedMinutes} \u5206\u949F\u5185\u6CA1\u6709\u53D1\u8A00\u8BB0\u5F55\u3002`;
733
739
  const nodes = messages.map((m) => ({
734
740
  type: "node",
@@ -1031,6 +1037,78 @@ ${import_koishi.segment.at(targetId)} \u5DF2\u88AB\u89E3\u9664\u7981\u8A00\u3002
1031
1037
  }
1032
1038
  return next();
1033
1039
  });
1040
+ ctx.command("\u521B\u5EFA\u63A5\u9F99 <content:string>", "\u521B\u5EFA\u7FA4\u63A5\u9F99\uFF0C\u521B\u5EFA\u8005\u81EA\u52A8\u4E3A\u7B2C\u4E00\u4F4D").action(async ({ session }, content) => {
1041
+ if (!session?.userId) return;
1042
+ const gid = getGroupId(session);
1043
+ const cc = config.chain;
1044
+ if (!cc.enabled) return;
1045
+ if (!isGroupAllowed(gid, cc.groups, cc.groupMode)) return;
1046
+ if (!content || !content.trim()) {
1047
+ return "\u{1F4DD} \u8BF7\u63D0\u4F9B\u63A5\u9F99\u5185\u5BB9\uFF0C\u4F8B\u5982\uFF1A\u521B\u5EFA\u63A5\u9F99 \u4ECA\u5929\u4E2D\u5348\u5403\u4EC0\u4E48";
1048
+ }
1049
+ const chainContent = content.trim();
1050
+ const userId = String(session.userId);
1051
+ const userName = session.username || userId;
1052
+ chainStates.set(gid, {
1053
+ content: chainContent,
1054
+ creatorId: userId,
1055
+ creatorName: userName,
1056
+ participants: [{ userId, userName }],
1057
+ createdAt: Date.now()
1058
+ });
1059
+ dbg("\u63A5\u9F99-\u521B\u5EFA", { gid, creatorId: userId, content: chainContent });
1060
+ return formatChain(chainStates.get(gid));
1061
+ });
1062
+ ctx.command("\u67E5\u770B\u63A5\u9F99", "\u67E5\u770B\u5F53\u524D\u7FA4\u63A5\u9F99").action(async ({ session }) => {
1063
+ const gid = getGroupId(session);
1064
+ const cc = config.chain;
1065
+ if (!cc.enabled) return;
1066
+ if (!isGroupAllowed(gid, cc.groups, cc.groupMode)) return;
1067
+ const chain = chainStates.get(gid);
1068
+ if (!chain) return '\u{1F4DD} \u672C\u7FA4\u6682\u65E0\u63A5\u9F99\uFF0C\u4F7F\u7528"\u521B\u5EFA\u63A5\u9F99 <\u5185\u5BB9>"\u5F00\u59CB\u4E00\u4E2A\u5427\uFF01';
1069
+ return formatChain(chain);
1070
+ });
1071
+ ctx.command("\u9000\u51FA\u63A5\u9F99", "\u9000\u51FA\u5F53\u524D\u7FA4\u63A5\u9F99").alias("\u53D6\u6D88\u63A5\u9F99").action(async ({ session }) => {
1072
+ const gid = getGroupId(session);
1073
+ const cc = config.chain;
1074
+ if (!cc.enabled) return;
1075
+ if (!isGroupAllowed(gid, cc.groups, cc.groupMode)) return;
1076
+ const chain = chainStates.get(gid);
1077
+ if (!chain) return "\u{1F4DD} \u672C\u7FA4\u6682\u65E0\u63A5\u9F99\u3002";
1078
+ const userId = String(session.userId);
1079
+ const idx = chain.participants.findIndex((p) => p.userId === userId);
1080
+ if (idx === -1) return "\u{1F4DD} \u4F60\u6CA1\u6709\u53C2\u4E0E\u8FD9\u4E2A\u63A5\u9F99\u3002";
1081
+ const userName = chain.participants[idx].userName;
1082
+ chain.participants.splice(idx, 1);
1083
+ dbg("\u63A5\u9F99-\u9000\u51FA", { gid, userId, userName, remaining: chain.participants.length });
1084
+ if (chain.participants.length === 0) {
1085
+ chainStates.delete(gid);
1086
+ return "\u{1F4DD} \u4F60\u9000\u51FA\u4E86\u63A5\u9F99\uFF0C\u63A5\u9F99\u5DF2\u56E0\u65E0\u4EBA\u53C2\u4E0E\u800C\u7ED3\u675F\u3002";
1087
+ }
1088
+ await session.send(`\u{1F4DD} ${userName} \u5DF2\u9000\u51FA\u63A5\u9F99\u3002
1089
+
1090
+ ${formatChain(chain)}`);
1091
+ });
1092
+ ctx.middleware(async (session, next) => {
1093
+ if (!config.chain.enabled) return next();
1094
+ const gid = getGroupId(session);
1095
+ if (!gid) return next();
1096
+ if (!isGroupAllowed(gid, config.chain.groups, config.chain.groupMode)) return next();
1097
+ const text = (session.content || "").trim();
1098
+ if (text !== "\u63A5\u9F99") return next();
1099
+ const chain = chainStates.get(gid);
1100
+ if (!chain) return next();
1101
+ const userId = String(session.userId);
1102
+ if (chain.participants.some((p) => p.userId === userId)) {
1103
+ await session.send("\u{1F4DD} \u4F60\u5DF2\u7ECF\u53C2\u4E0E\u8FC7\u8FD9\u4E2A\u63A5\u9F99\u4E86\uFF01");
1104
+ return;
1105
+ }
1106
+ const userName = session.username || userId;
1107
+ chain.participants.push({ userId, userName });
1108
+ dbg("\u63A5\u9F99-\u53C2\u4E0E", { gid, userId, participantCount: chain.participants.length });
1109
+ await session.send(formatChain(chain));
1110
+ return;
1111
+ });
1034
1112
  ctx.middleware(async (session, next) => {
1035
1113
  const gid = getGroupId(session);
1036
1114
  const content = session.content || "";
@@ -1128,15 +1206,19 @@ ${import_koishi.segment.at(targetId)} \u5DF2\u88AB\u89E3\u9664\u7981\u8A00\u3002
1128
1206
  forwardTextsCount: forwardTexts.length
1129
1207
  });
1130
1208
  if (isFwd && forwardTexts.length > 0) {
1131
- const sevenDaysAgo = Date.now() - 7 * 24 * 60 * 60 * 1e3;
1132
1209
  dbg("\u67E5\u91CD\u68C0\u6D4B", { gid, forwardTextsCount: forwardTexts.length });
1133
1210
  for (const fwdText of forwardTexts) {
1134
1211
  if (!fwdText) continue;
1135
1212
  try {
1136
- const matches = await ctx.database.get("lili_message", { gid, content: fwdText }, { sort: { timestamp: "asc" }, limit: 1 });
1137
- dbg("\u67E5\u91CD\u67E5\u8BE2", { gid, fwdText: fwdText.substring(0, 50), matchCount: matches?.length || 0 });
1138
- if (matches && matches.length > 0 && matches[0].timestamp >= sevenDaysAgo) {
1139
- const original = matches[0];
1213
+ const sevenDaysAgoMs = Date.now() - 7 * 24 * 60 * 60 * 1e3;
1214
+ const recentMsgs = await ctx.database.get("lili_message", { gid, timestamp: { $gte: sevenDaysAgoMs } }, { sort: { timestamp: "asc" }, limit: 1e3 });
1215
+ const match = recentMsgs.find((m) => {
1216
+ if (m.content === fwdText) return true;
1217
+ return normalizeText(m.content) === fwdText;
1218
+ });
1219
+ dbg("\u67E5\u91CD\u67E5\u8BE2", { gid, fwdText: fwdText.substring(0, 50), recentMsgCount: recentMsgs?.length || 0, matched: !!match });
1220
+ if (match) {
1221
+ const original = match;
1140
1222
  const dateStr = new Date(original.timestamp).toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
1141
1223
  await session.send([
1142
1224
  (0, import_koishi.h)("quote", { id: original.messageId }),
@@ -1179,8 +1261,8 @@ ${import_koishi.segment.at(targetId)} \u5DF2\u88AB\u89E3\u9664\u7981\u8A00\u3002
1179
1261
  try {
1180
1262
  await ctx.database.create("lili_message", {
1181
1263
  gid,
1182
- userId: session.userId,
1183
- userName: session.username || session.userId,
1264
+ userId: String(session.userId),
1265
+ userName: session.username || String(session.userId),
1184
1266
  content: fwdText,
1185
1267
  timestamp: Date.now(),
1186
1268
  messageId: session.messageId || ""
@@ -1191,19 +1273,25 @@ ${import_koishi.segment.at(targetId)} \u5DF2\u88AB\u89E3\u9664\u7981\u8A00\u3002
1191
1273
  }
1192
1274
  }
1193
1275
  }
1194
- if (shouldRecord && !isFwd && normalizedText && textLen >= 15 && textLen <= 60) {
1195
- try {
1196
- await ctx.database.create("lili_message", {
1197
- gid,
1198
- userId: session.userId,
1199
- userName: session.username || session.userId,
1200
- content: normalizedText,
1201
- timestamp: Date.now(),
1202
- messageId: session.messageId || ""
1203
- });
1204
- dbg("\u6D88\u606F\u5DF2\u5165\u5E93", { gid, userId: session.userId, contentLen: normalizedText.length, messageId: session.messageId });
1205
- } catch (e) {
1206
- dbg("\u6D88\u606F\u5165\u5E93\u5931\u8D25", { gid, error: String(e) });
1276
+ if (shouldRecord && !isFwd) {
1277
+ const shouldStore = shouldRecordAll || normalizedText && textLen >= 15 && textLen <= 60;
1278
+ if (shouldStore) {
1279
+ const storeContent = shouldRecordAll ? session.content || normalizedText || "" : normalizedText;
1280
+ if (storeContent) {
1281
+ try {
1282
+ await ctx.database.create("lili_message", {
1283
+ gid,
1284
+ userId: String(session.userId),
1285
+ userName: session.username || String(session.userId),
1286
+ content: storeContent,
1287
+ timestamp: Date.now(),
1288
+ messageId: session.messageId || ""
1289
+ });
1290
+ dbg("\u6D88\u606F\u5DF2\u5165\u5E93", { gid, userId: String(session.userId), contentLen: storeContent.length, shouldRecordAll, messageId: session.messageId });
1291
+ } catch (e) {
1292
+ dbg("\u6D88\u606F\u5165\u5E93\u5931\u8D25", { gid, error: String(e) });
1293
+ }
1294
+ }
1207
1295
  }
1208
1296
  }
1209
1297
  if (config.imitation.enabled && isGroupAllowed(gid, config.imitation.groups, config.imitation.groupMode)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-lili-hub",
3
3
  "description": "丽丽Hub — 自用丽丽主题QQ群娱乐插件:俄罗斯轮盘赌、喝酒发酒疯、模仿群友说话、合并消息查重(水过了)",
4
- "version": "0.3.1",
4
+ "version": "0.3.2",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [