koishi-plugin-group-verification 1.0.33 → 1.0.35

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 (4) hide show
  1. package/lib/index.js +97 -89
  2. package/package.json +4 -4
  3. package/readme.md +2 -2
  4. package/src/index.ts +2155 -2140
package/lib/index.js CHANGED
@@ -45,12 +45,12 @@ var import_koishi = require("koishi");
45
45
  var name = "group-verification";
46
46
  var logger = console;
47
47
  var Config = import_koishi.Schema.object({
48
- defaultReminderMessage: import_koishi.Schema.string().description("默认提醒消息模板(使用 \\n 表示换行,可包含下方变量)").default("{user}({id}) 申请加入群 {gname}({group})\n申请理由:{question}\n匹配情况:{answer}/{threshold}\n使用 gva 同意或 gvr 拒绝申请"),
48
+ defaultReminderMessage: import_koishi.Schema.string().description("默认提醒消息模板(使用 \\n 表示换行,可包含下方变量)").default("{user}({id}) 申请入群\\n申请理由: {question}\\n匹配情况: {answer}/{threshold}\\n使用 gva 同意或 gvr 拒绝申请"),
49
49
  enableStrictGroupCheck: import_koishi.Schema.boolean().description("是否启用严格的群号检查(检查群号长度)").default(false),
50
50
  logLevel: import_koishi.Schema.union(["debug", "info", "warn", "error"]).description("日志级别").default("info"),
51
- permissionDeniedMessage: import_koishi.Schema.string().description("权限不足时返回给调用者的提示").default("权限不足:需要群主/管理员权限或koishi三级以上权限"),
51
+ permissionDeniedMessage: import_koishi.Schema.string().description("权限不足时返回给调用者的提示").default("权限不足: 需要群主/管理员权限或koishi三级以上权限"),
52
52
  invalidGroupMessage: import_koishi.Schema.string().description("无效群号或机器人未在该群时的提示").default("群号 {group} 格式不合法或机器人不在该群中"),
53
- parameterConflictMessage: import_koishi.Schema.string().description("参数冲突时提示").default("参数冲突:-? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)"),
53
+ parameterConflictMessage: import_koishi.Schema.string().description("参数冲突时提示").default("参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)"),
54
54
  noKeywordsMessage: import_koishi.Schema.string().description("未提供关键词且无法从现有配置继承时的提示").default("请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置"),
55
55
  blacklistAddSuccess: import_koishi.Schema.string().description("将用户加入黑名单后的提示,可使用 {user},{group},{reason}").default("已将用户 {user} 加入群 {group} 黑名单{reason}"),
56
56
  blacklistRemoveSuccess: import_koishi.Schema.string().description("从黑名单移除用户后的提示,可使用 {user},{group}").default("已从群 {group} 的黑名单中移除用户 {user}"),
@@ -162,25 +162,31 @@ function validateKeywordFormat(raw) {
162
162
  }
163
163
  __name(validateKeywordFormat, "validateKeywordFormat");
164
164
  function usageString() {
165
- return `用法:
166
- # 创建/修改配置
167
- gvc 关键词1,关键词2 -m 1 -t 2 # 创建配置
168
- gvc -m 1 -t 2 # 修改审核参数
165
+ return `用法:
166
+ -i 群号
167
+ -m (0|1|2|3)审核方式
168
+ -t 阈值
169
+ -msg [可选,消息内容] 并打开提醒消息
170
+ -nomsg 取消提醒消息(与-msg冲突)
171
+ -r 删除配置
172
+ -? 查询配置
169
173
 
170
- # 提醒消息控制(可用变量详见下方)
171
- gvc -msg "消息内容" # 修改提醒消息
174
+ 对于存在空格的关键词/提醒消息用双引号""包裹
175
+
176
+ # 例
177
+ gvc 关键词1,关键词2 -m 1 -t 2 # 创建配置
178
+ gvc -msg "消息内容" # 修改提醒消息
172
179
  gvc -nomsg # 禁用提醒消息
173
- # 查询/删除
174
180
  gvc -? # 查询配置
175
181
  gvc -r # 删除配置
176
182
 
177
- 审核方式说明(使用 -m 参数):
183
+ 审核方式说明(使用 -m 参数):
178
184
  0 全部同意(默认)
179
- 1 按数量同意,需要 -t 指定数量
185
+ 1 按数量同意,需要 -t 指定数量
180
186
  2 按比例同意,需要 -t 指定百分比
181
- 3 全部拒绝(拒绝后系统会自动阻止任何通过)
187
+ 3 全部拒绝
182
188
 
183
- 提醒消息可用变量:{user} 用户名 {id} 用户ID
189
+ 提醒消息可用变量: {user} 用户名 {id} 用户ID
184
190
  {group} 群号 {gname} 群名称
185
191
  {question} 申请理由 {answer} 匹配情况 {threshold} 阈值
186
192
  使用 \\n 换行`;
@@ -188,7 +194,7 @@ function usageString() {
188
194
  __name(usageString, "usageString");
189
195
  function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasRealEnableMessageParam, hasRealDisableMessageParam, logger2, defaultMessage) {
190
196
  let reminderEnabled = true;
191
- let reminderMessage = defaultMessage || "{user}({id}) 申请加入群 {gname}({group})\n申请理由:{question}\n匹配情况:{answer}/{threshold}";
197
+ let reminderMessage = defaultMessage || "{user}({id}) 申请入群\\n申请理由: {question}\\n匹配情况: {answer}/{threshold}\\n使用 gva 同意或 gvr 拒绝申请";
192
198
  if (existingConfig) {
193
199
  reminderEnabled = existingConfig.reminderEnabled;
194
200
  reminderMessage = existingConfig.reminderMessage || reminderMessage;
@@ -202,7 +208,7 @@ function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasR
202
208
  } else if (hasRealMessageParam) {
203
209
  reminderEnabled = true;
204
210
  if (cleanedOptions.message !== void 0) {
205
- reminderMessage = cleanedOptions.message.replace(/\\n/g, "\n");
211
+ reminderMessage = cleanedOptions.message;
206
212
  logger2.debug(`设置自定义提醒消息: ${reminderMessage.substring(0, 50)}...`);
207
213
  }
208
214
  }
@@ -353,17 +359,17 @@ async function checkPermission(session, targetGroupId) {
353
359
  }
354
360
  try {
355
361
  const member = await session.bot.getGuildMember(groupId, session.userId);
356
- logger.info(`权限检查 - 获取到成员信息:`, {
362
+ logger.debug(`权限检查 - 获取到成员信息:`, {
357
363
  roles: member?.roles,
358
364
  permissions: member?.permissions
359
365
  });
360
366
  if (member) {
361
367
  if (member.permissions?.includes("OWNER") || member.roles?.includes("owner")) {
362
- logger.info(`权限检查 - 用户是群主`);
368
+ logger.debug(`权限检查 - 用户是群主`);
363
369
  return [true];
364
370
  }
365
371
  if (member.roles?.includes("admin") || member.permissions?.includes("ADMINISTRATOR")) {
366
- logger.info(`权限检查 - 用户是管理员`);
372
+ logger.debug(`权限检查 - 用户是管理员`);
367
373
  return [true];
368
374
  }
369
375
  }
@@ -455,7 +461,7 @@ function parseConfigArgs(raw) {
455
461
  }
456
462
  }
457
463
  tokens = tokens.map(
458
- (t) => t.replace(new RegExp(ESC_QUOTE, "g"), '"').replace(new RegExp(ESC_BACKSLASH, "g"), "\\")
464
+ (t) => t.replace(new RegExp(ESC_QUOTE, "g"), '"').replace(new RegExp(ESC_BACKSLASH, "g"), "\\\\")
459
465
  );
460
466
  for (let i = 0; i < tokens.length; i++) {
461
467
  const tok = tokens[i];
@@ -516,7 +522,7 @@ function parseConfigArgs(raw) {
516
522
  }
517
523
  const keywordSection = raw.split(/(?:^|\s+)-(?:i|m|t|msg|nomsg|\?|r)\b/)[0].trim();
518
524
  if (keywordSection && !validateKeywordFormat(keywordSection)) {
519
- error = '关键词应使用逗号分隔或引号框起(如:k1,k2,k3 或 "k1","k2" 或 "k1,k2",k3)';
525
+ error = '关键词应使用逗号分隔或引号框起(如: k1,k2,k3 或 "k1","k2" 或 "k1,k2",k3)';
520
526
  }
521
527
  return { keywords, flags, error };
522
528
  }
@@ -600,7 +606,7 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
600
606
  logger.debug(`群 ${guildId} 的提醒消息已被禁用,跳过发送`);
601
607
  return;
602
608
  }
603
- let reminderMsg = config.reminderMessage;
609
+ let reminderMsg = config.reminderMessage.replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
604
610
  reminderMsg = reminderMsg.replace(/{user}/g, username).replace(/{id}/g, userId).replace(/{group}/g, guildId).replace(/{gname}/g, groupName).replace(/{question}/g, message).replace(/{answer}/g, matchedCount.toString()).replace(/{threshold}/g, requiredThreshold);
605
611
  const rawChannel = (session.channelId || "").toString().trim();
606
612
  const channel = rawChannel || guildId;
@@ -610,7 +616,7 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
610
616
  try {
611
617
  await session.bot.broadcast([target], reminderMsg);
612
618
  } catch (err) {
613
- logger.warn("bot.broadcast failed, fallback to ctx.broadcast", err);
619
+ logger.warn("bot.broadcast 失败,回退到 ctx.broadcast", err);
614
620
  if (typeof ctx.broadcast === "function") {
615
621
  await ctx.broadcast([target], reminderMsg);
616
622
  } else {
@@ -645,7 +651,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
645
651
  const op = parts[0]?.toLowerCase();
646
652
  if (!op || !["a", "r", "l", "i"].includes(op)) {
647
653
  return [
648
- "用法:",
654
+ "用法: ",
649
655
  " gvb a id [reason] [group] 将用户加入黑名单",
650
656
  " gvb r id [group] 将用户移出黑名单",
651
657
  " gvb l [group] 查询群黑名单",
@@ -693,7 +699,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
693
699
  const row = rows[0];
694
700
  const entries = row.entries || {};
695
701
  if (entries[targetUser] !== void 0) {
696
- return `用户 ${targetUser} 已在群 ${group} 的黑名单中:${entries[targetUser]}`;
702
+ return `用户 ${targetUser} 已在群 ${group} 的黑名单中: ${entries[targetUser]}`;
697
703
  }
698
704
  entries[targetUser] = storedReason;
699
705
  await ctx.database.set("group_verification_blacklist", { id: row.id }, { entries });
@@ -711,7 +717,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
711
717
  }
712
718
  }
713
719
  const tmpl = config && config.blacklistAddSuccess || "已将用户 {user} 加入群 {group} 黑名单{reason}";
714
- return tmpl.replace("{user}", targetUser).replace("{group}", group).replace("{reason}", reason ? `,原因:${reason}` : "");
720
+ return tmpl.replace("{user}", targetUser).replace("{group}", group).replace("{reason}", reason ? `,原因: ${reason}` : "");
715
721
  }
716
722
  if (op === "r") {
717
723
  targetUser = parts[1];
@@ -768,7 +774,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
768
774
  `;
769
775
  let msg = prefix;
770
776
  for (const uid in entries) {
771
- msg += `${uid}${entries[uid] ? `:${entries[uid]}` : ""}
777
+ msg += `${uid}${entries[uid] ? `: ${entries[uid]}` : ""}
772
778
  `;
773
779
  }
774
780
  return msg;
@@ -802,7 +808,7 @@ async function processBlacklistCommand(ctx, session, rawArgs, config) {
802
808
  }
803
809
  if (groupArg.toLowerCase() === "all") {
804
810
  const auth = session.author?.authority || session.user?.authority;
805
- if (!(auth && auth >= 3)) return "权限不足:查看全局/所有群黑名单需要 koishi 3 级以上权限";
811
+ if (!(auth && auth >= 3)) return "权限不足: 查看全局/所有群黑名单需要 koishi 3 级以上权限";
806
812
  const rows2 = await ctx.database.get("group_verification_blacklist", {});
807
813
  const globalReason2 = globalHit ? globalRows[0].entries[targetUser] : "无";
808
814
  const lines = [];
@@ -869,8 +875,8 @@ function apply(ctx, config) {
869
875
  manuallyApproved: "integer",
870
876
  rejected: "integer",
871
877
  totalJoined: "integer",
872
- // store as string (ISO timestamp) to preserve full date+time;
873
- // Koishi `date` type truncates to day which leads to 00:00:00.
878
+ // 以字符串(ISO 时间戳)格式存储,保留完整日期+时间;
879
+ // Koishi date 类型会截断到天,导致时间显示为 00:00:00
874
880
  lastUpdated: "string"
875
881
  }, {
876
882
  primary: "id",
@@ -884,7 +890,7 @@ function apply(ctx, config) {
884
890
  requestMessage: "string",
885
891
  // 保存 OneBot 事件提供的原始 requestId;用于同意/拒绝操作
886
892
  requestId: "string",
887
- // record full timestamp as string to keep time component
893
+ // 以字符串格式记录完整时间戳,保留时间分量
888
894
  applyTime: "string"
889
895
  }, {
890
896
  primary: "id",
@@ -900,7 +906,7 @@ function apply(ctx, config) {
900
906
  indexes: [["groupId"]]
901
907
  });
902
908
  ctx.on("guild-member-request", async (session) => {
903
- logger.info("收到 guild-member-request 事件,转发给处理函数");
909
+ logger.debug("收到 guild-member-request 事件,转发给处理函数");
904
910
  await handleGuildMemberRequestEvent(ctx, session);
905
911
  });
906
912
  ctx.on("guild-member-added", async (session) => {
@@ -973,7 +979,7 @@ function apply(ctx, config) {
973
979
  });
974
980
  if (member) {
975
981
  if (member.permissions?.includes("OWNER") || member.roles?.includes("owner")) {
976
- logger.info(`权限检查 - 用户是群主`);
982
+ logger.debug(`权限检查 - 用户是群主`);
977
983
  return [true];
978
984
  }
979
985
  if (member.roles?.includes("admin") || member.permissions?.includes("ADMINISTRATOR")) {
@@ -987,7 +993,7 @@ function apply(ctx, config) {
987
993
  }
988
994
  logger.debug(`权限检查 - 权限不足`);
989
995
  const debugInfo = `调试信息 - 用户ID:${session.userId}, 群号:${groupId}, 权限等级:${koishiAuthority || "未知"}`;
990
- return [false, (config.permissionDeniedMessage || "权限不足:需要群主/管理员权限或koishi三级以上权限") + `
996
+ return [false, (config.permissionDeniedMessage || "权限不足: 需要群主/管理员权限或koishi三级以上权限") + `
991
997
  ${debugInfo}`];
992
998
  }
993
999
  __name(checkPermission2, "checkPermission");
@@ -1001,30 +1007,30 @@ ${debugInfo}`];
1001
1007
  "group-verify.配置",
1002
1008
  "gvc"
1003
1009
  ).option("groupId", "-i <groupId> 指定群号").option("method", "-m <method> 审核方式 (0-3)").option("threshold", "-t <threshold> 阈值参数").option("message", "-msg [message] 自定义提醒消息").option("disableMessage", "-nomsg 禁用提醒消息").option("query", "-? 查询当前配置").option("remove", "-r 删除配置").action(async ({ session, options }, keywords) => {
1004
- logger.info(`=== 命令解析调试 ===`);
1005
- logger.info(`session内容: guildId=${session.guildId}, userId=${session.userId}`);
1010
+ logger.debug(`=== 命令解析调试 ===`);
1011
+ logger.debug(`session内容: guildId=${session.guildId}, userId=${session.userId}`);
1006
1012
  const rawInput = session.content.split(/\s+/).slice(1).join(" ");
1007
- logger.info(`原始命令参数: "${rawInput}"`);
1013
+ logger.debug(`原始命令参数: "${rawInput}"`);
1008
1014
  const parsed = parseConfigArgs(rawInput);
1009
1015
  const { keywords: parsedKeywords, flags, error: parseError } = parsed;
1010
1016
  if (parseError) {
1011
1017
  return parseError;
1012
1018
  }
1013
- logger.info(`解析结果 flags=${JSON.stringify(flags)}, keywords=[${parsedKeywords.join(", ")}]`);
1019
+ logger.debug(`解析结果 flags=${JSON.stringify(flags)}, keywords=[${parsedKeywords.join(", ")}]`);
1014
1020
  const cleanedOptions = {
1015
1021
  groupId: flags.groupId || options.groupId,
1016
1022
  method: flags.method || (options.method === "" ? void 0 : options.method),
1017
1023
  threshold: flags.threshold || options.threshold,
1018
1024
  message: flags.message !== void 0 ? flags.message : options.message,
1019
1025
  enableMessage: flags.enableMessage,
1020
- // 新增:-msg 裸调用标记
1026
+ // 新增: -msg 裸调用标记
1021
1027
  disableMessage: flags.disableMessage || options.disableMessage,
1022
1028
  query: flags.query || options.query,
1023
1029
  remove: flags.remove || options.remove
1024
1030
  };
1025
- logger.info(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`);
1031
+ logger.debug(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`);
1026
1032
  if ((cleanedOptions.query || cleanedOptions.remove) && (parsedKeywords.length > 0 || cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || cleanedOptions.message !== void 0 || cleanedOptions.enableMessage || cleanedOptions.disableMessage)) {
1027
- return config.parameterConflictMessage || "参数冲突:-? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)";
1033
+ return config.parameterConflictMessage || "参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)";
1028
1034
  }
1029
1035
  const hasRealMessageParam = cleanedOptions.message !== void 0;
1030
1036
  const hasRealEnableMessageParam = cleanedOptions.enableMessage === true;
@@ -1049,7 +1055,7 @@ ${debugInfo}`];
1049
1055
  return "请在群聊中使用此命令或指定群号(-i参数)";
1050
1056
  }
1051
1057
  if ((hasRealMessageParam || hasRealEnableMessageParam) && hasRealDisableMessageParam) {
1052
- return "参数冲突:不能同时使用 -msg 和 -nomsg";
1058
+ return "参数冲突: 不能同时使用 -msg 和 -nomsg";
1053
1059
  }
1054
1060
  const usedOptions = [];
1055
1061
  if (cleanedOptions.method !== void 0) usedOptions.push("-m");
@@ -1107,13 +1113,14 @@ ${debugInfo}`];
1107
1113
  const createTime = new Date(config2.createdAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1108
1114
  const updateTime = new Date(config2.updatedAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1109
1115
  const reminderStatus = config2.reminderEnabled ? "启用" : "禁用";
1110
- return `群 ${targetGroupId} 配置:
1116
+ const displayMsg = (config2.reminderMessage || "无").replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
1117
+ return `群 ${targetGroupId} 配置:
1111
1118
  关键词: ${decodedKeywords2.join(", ")}
1112
1119
  审核方式: ${methodDesc}
1113
1120
  阈值: ${thresholdInfo}
1114
1121
  提醒消息: ${reminderStatus}
1115
1122
  自定义消息:
1116
- ${config2.reminderMessage || "无"}
1123
+ ${displayMsg}
1117
1124
  创建时间: ${createTime}
1118
1125
  更新时间: ${updateTime}
1119
1126
  创建者: ${config2.createdBy}
@@ -1123,7 +1130,7 @@ ${config2.reminderMessage || "无"}
1123
1130
  }
1124
1131
  }
1125
1132
  let keywordList = parsedKeywords.slice();
1126
- logger.info(`关键词解析结果: [${keywordList.join(", ")}] - 原始输入: "${rawInput}"`);
1133
+ logger.debug(`关键词解析结果: [${keywordList.join(", ")}] - 原始输入: "${rawInput}"`);
1127
1134
  if (keywordList.length === 0 && !cleanedOptions.query && !cleanedOptions.remove) {
1128
1135
  const hasConfigParams = cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || hasRealMessageParam || hasRealEnableMessageParam || hasRealDisableMessageParam;
1129
1136
  if (!hasConfigParams) {
@@ -1156,7 +1163,7 @@ ${config2.reminderMessage || "无"}
1156
1163
  reviewMethod = existingConfig.reviewMethod;
1157
1164
  if (existingConfig.reviewParameters === void 0 || existingConfig.reviewParameters === null || isNaN(existingConfig.reviewParameters)) {
1158
1165
  reviewParameters = 0;
1159
- logger.info(`检测到老版本数据或无效值,使用默认阈值: 0`);
1166
+ logger.debug(`检测到老版本数据或无效值,使用默认阈值: 0`);
1160
1167
  } else {
1161
1168
  reviewParameters = existingConfig.reviewParameters;
1162
1169
  }
@@ -1164,7 +1171,7 @@ ${config2.reminderMessage || "无"}
1164
1171
  if (cleanedOptions.method !== void 0 && cleanedOptions.method !== "") {
1165
1172
  const methodNum = parseInt(cleanedOptions.method);
1166
1173
  if (isNaN(methodNum) || methodNum < 0 || methodNum > 3) {
1167
- return "审核方式参数错误:0-全部同意, 1-按数量同意, 2-按比例同意, 3-全部拒绝";
1174
+ return "审核方式参数错误: 0-全部同意, 1-按数量同意, 2-按比例同意, 3-全部拒绝";
1168
1175
  }
1169
1176
  const oldMethod = reviewMethod;
1170
1177
  reviewMethod = methodNum;
@@ -1209,7 +1216,7 @@ ${config2.reminderMessage || "无"}
1209
1216
  const encodedKeywords = keywordList.map((keyword) => {
1210
1217
  return keyword.replace(/,/g, "[[COMMA]]");
1211
1218
  });
1212
- logger.info(`编码后准备存储的关键词: ${JSON.stringify(encodedKeywords)}`);
1219
+ logger.debug(`编码后准备存储的关键词: ${JSON.stringify(encodedKeywords)}`);
1213
1220
  const dbData = {
1214
1221
  keywords: encodedKeywords,
1215
1222
  reviewMethod,
@@ -1253,24 +1260,25 @@ ${config2.reminderMessage || "无"}
1253
1260
  feedbackMessage += `提醒状态: ${reminderEnabled ? "启用" : "禁用"}
1254
1261
  `;
1255
1262
  if (reminderMessage && reminderEnabled) {
1263
+ const displayReminder = reminderMessage.replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
1256
1264
  feedbackMessage += `提醒消息:
1257
- ${reminderMessage}
1265
+ ${displayReminder}
1258
1266
  `;
1259
1267
  }
1260
- logger.info(`准备存储到数据库的关键词: ${JSON.stringify(encodedKeywords)}`);
1261
- logger.info(`=== 配置处理详情 ===`);
1262
- logger.info(`原始输入: ${keywords || "无关键词"}`);
1263
- logger.info(`审核方式: ${reviewMethod} (${["全部同意", "按数量", "按比例", "全部拒绝"][reviewMethod]})`);
1264
- logger.info(`阈值参数: ${JSON.stringify(reviewParameters)}`);
1265
- logger.info(`关键词列表: [${keywordList.map((k) => `"${k}"`).join(", ")}]`);
1266
- logger.info(`现有配置: ${existingConfig ? "存在" : "不存在"}`);
1268
+ logger.debug(`准备存储到数据库的关键词: ${JSON.stringify(encodedKeywords)}`);
1269
+ logger.debug(`=== 配置处理详情 ===`);
1270
+ logger.debug(`原始输入: ${keywords || "无关键词"}`);
1271
+ logger.debug(`审核方式: ${reviewMethod} (${["全部同意", "按数量", "按比例", "全部拒绝"][reviewMethod]})`);
1272
+ logger.debug(`阈值参数: ${JSON.stringify(reviewParameters)}`);
1273
+ logger.debug(`关键词列表: [${keywordList.map((k) => `"${k}"`).join(", ")}]`);
1274
+ logger.debug(`现有配置: ${existingConfig ? "存在" : "不存在"}`);
1267
1275
  if (existingConfig) {
1268
- logger.info(`原审核方式: ${existingConfig.reviewMethod}`);
1269
- logger.info(`原阈值: ${JSON.stringify(existingConfig.reviewParameters)}`);
1270
- logger.info(`原关键词数: ${existingConfig.keywords.length}`);
1271
- logger.info(`新关键词数: ${keywordList.length}`);
1276
+ logger.debug(`原审核方式: ${existingConfig.reviewMethod}`);
1277
+ logger.debug(`原阈值: ${JSON.stringify(existingConfig.reviewParameters)}`);
1278
+ logger.debug(`原关键词数: ${existingConfig.keywords.length}`);
1279
+ logger.debug(`新关键词数: ${keywordList.length}`);
1272
1280
  }
1273
- logger.info(`==================`);
1281
+ logger.debug(`==================`);
1274
1282
  logger.info(feedbackMessage.replace(/\n/g, "; "));
1275
1283
  return feedbackMessage;
1276
1284
  });
@@ -1455,7 +1463,7 @@ ${reminderMessage}
1455
1463
  const isGroupId = target && /^\d+$/.test(target);
1456
1464
  const isSpecialTarget = target && validTargets.includes(target.toLowerCase());
1457
1465
  if (target && !isGroupId && !isSpecialTarget) {
1458
- return "参数错误:只能指定群号、all、total或留空";
1466
+ return "参数错误: 只能指定群号、all、total或留空";
1459
1467
  }
1460
1468
  if (target?.toLowerCase() === "total" || target?.toLowerCase() === "all") {
1461
1469
  const koishiAuthority = session.author?.authority || session.user?.authority;
@@ -1496,11 +1504,11 @@ ${reminderMessage}
1496
1504
  if (pendingApplications.length === 0) {
1497
1505
  return "当前没有待审核的加群申请";
1498
1506
  }
1499
- let result = "待审核申请列表:\n";
1507
+ let result = "待审核申请列表: \n";
1500
1508
  pendingApplications.forEach((app, index) => {
1501
1509
  result += `${index + 1}. ${app.userName}(${app.userId})
1502
- 申请时间:${app.applyTime.toLocaleString()}
1503
- 申请理由:${app.requestMessage}
1510
+ 申请时间: ${app.applyTime.toLocaleString()}
1511
+ 申请理由: ${app.requestMessage}
1504
1512
 
1505
1513
  `;
1506
1514
  });
@@ -1518,19 +1526,19 @@ ${reminderMessage}
1518
1526
  return await processBlacklistCommand(ctx, session, args || "", config);
1519
1527
  });
1520
1528
  groupVerify.subcommand(".help", "显示帮助信息").alias("gv.帮助", "gverify.帮助", "group-verify.帮助", "帮助", "hlp", "帮助信息").action(() => {
1521
- return `群组验证命令帮助:
1522
- 主指令别名:gv, gverify
1529
+ return `群组验证命令帮助:
1530
+ 主指令别名: gv, gverify
1523
1531
 
1524
1532
  配置命令 (.config/.cfg):
1525
- 用法:
1526
- 1. 创建新配置:gv.cfg 关键词1,关键词2 -m 1 -t 2
1527
- 2. 修改现有配置:gv.cfg -m 1 -t 2 (不提供关键词)
1528
- 3. 启用提醒消息:gv.cfg -msg "消息内容"
1529
- 4. 禁用提醒消息:gv.cfg -nomsg
1530
- 5. 查询配置:gv.cfg -?
1531
- 6. 删除配置:gv.cfg -r
1533
+ 用法:
1534
+ 1. 创建新配置: gv.cfg 关键词1,关键词2 -m 1 -t 2
1535
+ 2. 修改现有配置: gv.cfg -m 1 -t 2 (不提供关键词)
1536
+ 3. 启用提醒消息: gv.cfg -msg "消息内容"
1537
+ 4. 禁用提醒消息: gv.cfg -nomsg
1538
+ 5. 查询配置: gv.cfg -?
1539
+ 6. 删除配置: gv.cfg -r
1532
1540
 
1533
- 参数说明:
1541
+ 参数说明:
1534
1542
  -i <群号> 指定群号(私聊时必需)
1535
1543
  -m <方式> 审核方式 (0=全部同意, 1=按数量, 2=按比例, 3=全部拒绝)
1536
1544
  -t <阈值> 阈值参数(方式1:0-关键词数, 方式2:0-100)
@@ -1542,19 +1550,19 @@ ${reminderMessage}
1542
1550
  -? 查询当前配置
1543
1551
  -r 删除配置
1544
1552
 
1545
- 引号使用规则:
1546
- 关键词包含空格:gv.cfg "关键词1,关键词 2,关键词3"
1547
- 提醒消息包含空格:gv.cfg -msg "这是包含空格的消息"
1548
- 内部引号转义:gv.cfg -msg "包含\\"引号\\"的内容"
1549
- 换行符:gv.cfg -msg "第一行\\n第二行"
1553
+ 引号使用规则:
1554
+ 关键词包含空格: gv.cfg "关键词1,关键词 2,关键词3"
1555
+ 提醒消息包含空格: gv.cfg -msg "这是包含空格的消息"
1556
+ 内部引号转义: gv.cfg -msg "包含\\"引号\\"的内容"
1557
+ 换行符: gv.cfg -msg "第一行\\n第二行"
1550
1558
 
1551
- 特殊说明:
1559
+ 特殊说明:
1552
1560
  • 阈值可设为0表示全部同意
1553
1561
  • 关键词数量变化时阈值会自动调整
1554
1562
  • 重复参数会使用最后出现的值并提醒
1555
1563
  • 群号检查可在插件配置中开关
1556
1564
 
1557
- 提醒消息变量:
1565
+ 提醒消息变量:
1558
1566
  {user} - 用户名
1559
1567
  {id} - 用户ID
1560
1568
  {group} - 群号
@@ -1563,9 +1571,9 @@ ${reminderMessage}
1563
1571
  {answer} - 答对数量/比例
1564
1572
  {threshold} - 阈值要求
1565
1573
 
1566
- 使用示例:
1574
+ 使用示例:
1567
1575
  gv.cfg "关键词1,关键词2" -m 1 -t 2
1568
- gv.cfg -msg "用户 {user}\\n申请理由:{question}"
1576
+ gv.cfg -msg "用户 {user}\\n申请理由: {question}"
1569
1577
  gv.cfg -m 2 -t 80
1570
1578
  gv.cfg -nomsg
1571
1579
 
@@ -1575,21 +1583,21 @@ ${reminderMessage}
1575
1583
  l [group] 查询群黑名单;传入 all 时查看全局黑名单
1576
1584
  i id [group] 查询账号黑名单;不带参数时查询本群与全局,
1577
1585
  指定群号查询该群与全局,传入 all 则列出所有群及全局(需Koishi 3级)
1578
- 使用示例:
1586
+ 使用示例:
1579
1587
  gvb a 12345 作弊记录
1580
1588
  gvb r 12345 67890
1581
1589
  gvb l
1582
1590
  gvb l all
1583
1591
  gvb i 12345
1584
1592
 
1585
- 快捷命令:
1593
+ 快捷命令:
1586
1594
  gvc - 配置命令快捷方式
1587
1595
  gva - 同意申请快捷命令
1588
1596
  gvr - 拒绝申请快捷命令
1589
1597
  gvp - 查看待审核列表快捷命令
1590
1598
  gvs - 查看统计信息快捷命令
1591
1599
 
1592
- 权限说明:
1600
+ 权限说明:
1593
1601
  - 群主/管理员权限
1594
1602
  - koishi三级以上权限
1595
1603
  - 私聊时必须指定群号(-i参数)`;
@@ -1649,7 +1657,7 @@ ${reminderMessage}
1649
1657
  }
1650
1658
  const stat = stats[0];
1651
1659
  const lastUpdated = new Date(stat.lastUpdated).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1652
- return `群 ${groupId} 验证统计:
1660
+ return `群 ${groupId} 验证统计:
1653
1661
  自动批准: ${stat.autoApproved}
1654
1662
  手动批准: ${stat.manuallyApproved}
1655
1663
  拒绝: ${stat.rejected}
@@ -1663,7 +1671,7 @@ ${reminderMessage}
1663
1671
  }
1664
1672
  const stat = stats[0];
1665
1673
  const lastUpdated = new Date(stat.lastUpdated).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1666
- return `总计验证统计:
1674
+ return `总计验证统计:
1667
1675
  自动批准: ${stat.autoApproved}
1668
1676
  手动批准: ${stat.manuallyApproved}
1669
1677
  拒绝: ${stat.rejected}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koishi-plugin-group-verification",
3
- "description": "Koishi 群组加群验证插件,支持多关键词匹配审核、多种审核方式和详细统计功能",
3
+ "description": "Koishi 群组加群验证插件,支持多关键词匹配审核、多种审核方式、黑名单和详细统计功能",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/LHDyx/koishi-plugin-group-verification.git"
@@ -8,7 +8,7 @@
8
8
  "bugs": {
9
9
  "url": "https://github.com/LHDyx/koishi-plugin-group-verification/issues"
10
10
  },
11
- "version": "1.0.33",
11
+ "version": "1.0.35",
12
12
  "main": "lib/index.js",
13
13
  "typings": "lib/index.d.ts",
14
14
  "files": [
@@ -44,7 +44,7 @@
44
44
  "koishi": "^4.15.0"
45
45
  },
46
46
  "devDependencies": {
47
- "typescript": "^4.9.0",
48
- "@types/node": "^16.0.0"
47
+ "@types/node": "^16.0.0",
48
+ "typescript": "^4.9.0"
49
49
  }
50
50
  }
package/readme.md CHANGED
@@ -138,11 +138,11 @@ group-verify.blacklist i <用户ID> [群号|all]
138
138
 
139
139
  插件启动时会输出运行状态,并根据 `logLevel` 调整输出量。
140
140
  - `debug`:打印所有调试细节,包括权限检查、命令解析等。
141
- - `info`:默认值,记录关键事件(插件启动、配置修改、自动拒绝、黑名单踢人等)。
141
+ - `info`:默认值,记录关键事件(插件启动、配置修改、自动拒绝、黑名单踢人等),包括成功踢人日志。
142
142
  - `warn`:记录可恢复的异常,例如尝试踢出用户失败、数据库操作问题。
143
143
  - `error`:仅在遇到严重错误时输出。
144
144
 
145
- 添加黑名单时会尝试在对应群踢出该用户,成功记为 `info`,失败记为 `warn`。
145
+ 添加黑名单时会尝试在对应群踢出该用户,成功记为 `info`,失败记为 `warn`。权限检查的详细过程则只会在 `debug` 级别输出。
146
146
 
147
147
  ### 严格群号检查
148
148