koishi-plugin-group-verification 1.0.34 → 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 +38 -36
  2. package/package.json +3 -3
  3. package/readme.md +2 -2
  4. package/src/index.ts +2155 -2146
package/lib/index.js CHANGED
@@ -45,7 +45,7 @@ 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
51
  permissionDeniedMessage: import_koishi.Schema.string().description("权限不足时返回给调用者的提示").default("权限不足: 需要群主/管理员权限或koishi三级以上权限"),
@@ -194,7 +194,7 @@ function usageString() {
194
194
  __name(usageString, "usageString");
195
195
  function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasRealEnableMessageParam, hasRealDisableMessageParam, logger2, defaultMessage) {
196
196
  let reminderEnabled = true;
197
- 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 拒绝申请";
198
198
  if (existingConfig) {
199
199
  reminderEnabled = existingConfig.reminderEnabled;
200
200
  reminderMessage = existingConfig.reminderMessage || reminderMessage;
@@ -208,7 +208,7 @@ function mergeReminder(existingConfig, cleanedOptions, hasRealMessageParam, hasR
208
208
  } else if (hasRealMessageParam) {
209
209
  reminderEnabled = true;
210
210
  if (cleanedOptions.message !== void 0) {
211
- reminderMessage = cleanedOptions.message.replace(/\\n/g, "\n");
211
+ reminderMessage = cleanedOptions.message;
212
212
  logger2.debug(`设置自定义提醒消息: ${reminderMessage.substring(0, 50)}...`);
213
213
  }
214
214
  }
@@ -359,17 +359,17 @@ async function checkPermission(session, targetGroupId) {
359
359
  }
360
360
  try {
361
361
  const member = await session.bot.getGuildMember(groupId, session.userId);
362
- logger.info(`权限检查 - 获取到成员信息:`, {
362
+ logger.debug(`权限检查 - 获取到成员信息:`, {
363
363
  roles: member?.roles,
364
364
  permissions: member?.permissions
365
365
  });
366
366
  if (member) {
367
367
  if (member.permissions?.includes("OWNER") || member.roles?.includes("owner")) {
368
- logger.info(`权限检查 - 用户是群主`);
368
+ logger.debug(`权限检查 - 用户是群主`);
369
369
  return [true];
370
370
  }
371
371
  if (member.roles?.includes("admin") || member.permissions?.includes("ADMINISTRATOR")) {
372
- logger.info(`权限检查 - 用户是管理员`);
372
+ logger.debug(`权限检查 - 用户是管理员`);
373
373
  return [true];
374
374
  }
375
375
  }
@@ -461,7 +461,7 @@ function parseConfigArgs(raw) {
461
461
  }
462
462
  }
463
463
  tokens = tokens.map(
464
- (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"), "\\\\")
465
465
  );
466
466
  for (let i = 0; i < tokens.length; i++) {
467
467
  const tok = tokens[i];
@@ -606,7 +606,7 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
606
606
  logger.debug(`群 ${guildId} 的提醒消息已被禁用,跳过发送`);
607
607
  return;
608
608
  }
609
- let reminderMsg = config.reminderMessage;
609
+ let reminderMsg = config.reminderMessage.replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
610
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);
611
611
  const rawChannel = (session.channelId || "").toString().trim();
612
612
  const channel = rawChannel || guildId;
@@ -616,7 +616,7 @@ async function handleFailedVerification(ctx, session, config, matchedCount, requ
616
616
  try {
617
617
  await session.bot.broadcast([target], reminderMsg);
618
618
  } catch (err) {
619
- logger.warn("bot.broadcast failed, fallback to ctx.broadcast", err);
619
+ logger.warn("bot.broadcast 失败,回退到 ctx.broadcast", err);
620
620
  if (typeof ctx.broadcast === "function") {
621
621
  await ctx.broadcast([target], reminderMsg);
622
622
  } else {
@@ -875,8 +875,8 @@ function apply(ctx, config) {
875
875
  manuallyApproved: "integer",
876
876
  rejected: "integer",
877
877
  totalJoined: "integer",
878
- // store as string (ISO timestamp) to preserve full date+time;
879
- // Koishi `date` type truncates to day which leads to 00:00:00.
878
+ // 以字符串(ISO 时间戳)格式存储,保留完整日期+时间;
879
+ // Koishi date 类型会截断到天,导致时间显示为 00:00:00
880
880
  lastUpdated: "string"
881
881
  }, {
882
882
  primary: "id",
@@ -890,7 +890,7 @@ function apply(ctx, config) {
890
890
  requestMessage: "string",
891
891
  // 保存 OneBot 事件提供的原始 requestId;用于同意/拒绝操作
892
892
  requestId: "string",
893
- // record full timestamp as string to keep time component
893
+ // 以字符串格式记录完整时间戳,保留时间分量
894
894
  applyTime: "string"
895
895
  }, {
896
896
  primary: "id",
@@ -906,7 +906,7 @@ function apply(ctx, config) {
906
906
  indexes: [["groupId"]]
907
907
  });
908
908
  ctx.on("guild-member-request", async (session) => {
909
- logger.info("收到 guild-member-request 事件,转发给处理函数");
909
+ logger.debug("收到 guild-member-request 事件,转发给处理函数");
910
910
  await handleGuildMemberRequestEvent(ctx, session);
911
911
  });
912
912
  ctx.on("guild-member-added", async (session) => {
@@ -979,7 +979,7 @@ function apply(ctx, config) {
979
979
  });
980
980
  if (member) {
981
981
  if (member.permissions?.includes("OWNER") || member.roles?.includes("owner")) {
982
- logger.info(`权限检查 - 用户是群主`);
982
+ logger.debug(`权限检查 - 用户是群主`);
983
983
  return [true];
984
984
  }
985
985
  if (member.roles?.includes("admin") || member.permissions?.includes("ADMINISTRATOR")) {
@@ -1007,16 +1007,16 @@ ${debugInfo}`];
1007
1007
  "group-verify.配置",
1008
1008
  "gvc"
1009
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) => {
1010
- logger.info(`=== 命令解析调试 ===`);
1011
- logger.info(`session内容: guildId=${session.guildId}, userId=${session.userId}`);
1010
+ logger.debug(`=== 命令解析调试 ===`);
1011
+ logger.debug(`session内容: guildId=${session.guildId}, userId=${session.userId}`);
1012
1012
  const rawInput = session.content.split(/\s+/).slice(1).join(" ");
1013
- logger.info(`原始命令参数: "${rawInput}"`);
1013
+ logger.debug(`原始命令参数: "${rawInput}"`);
1014
1014
  const parsed = parseConfigArgs(rawInput);
1015
1015
  const { keywords: parsedKeywords, flags, error: parseError } = parsed;
1016
1016
  if (parseError) {
1017
1017
  return parseError;
1018
1018
  }
1019
- logger.info(`解析结果 flags=${JSON.stringify(flags)}, keywords=[${parsedKeywords.join(", ")}]`);
1019
+ logger.debug(`解析结果 flags=${JSON.stringify(flags)}, keywords=[${parsedKeywords.join(", ")}]`);
1020
1020
  const cleanedOptions = {
1021
1021
  groupId: flags.groupId || options.groupId,
1022
1022
  method: flags.method || (options.method === "" ? void 0 : options.method),
@@ -1028,7 +1028,7 @@ ${debugInfo}`];
1028
1028
  query: flags.query || options.query,
1029
1029
  remove: flags.remove || options.remove
1030
1030
  };
1031
- logger.info(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`);
1031
+ logger.debug(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`);
1032
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)) {
1033
1033
  return config.parameterConflictMessage || "参数冲突: -? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)";
1034
1034
  }
@@ -1113,13 +1113,14 @@ ${debugInfo}`];
1113
1113
  const createTime = new Date(config2.createdAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1114
1114
  const updateTime = new Date(config2.updatedAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
1115
1115
  const reminderStatus = config2.reminderEnabled ? "启用" : "禁用";
1116
+ const displayMsg = (config2.reminderMessage || "无").replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
1116
1117
  return `群 ${targetGroupId} 配置:
1117
1118
  关键词: ${decodedKeywords2.join(", ")}
1118
1119
  审核方式: ${methodDesc}
1119
1120
  阈值: ${thresholdInfo}
1120
1121
  提醒消息: ${reminderStatus}
1121
1122
  自定义消息:
1122
- ${config2.reminderMessage || "无"}
1123
+ ${displayMsg}
1123
1124
  创建时间: ${createTime}
1124
1125
  更新时间: ${updateTime}
1125
1126
  创建者: ${config2.createdBy}
@@ -1129,7 +1130,7 @@ ${config2.reminderMessage || "无"}
1129
1130
  }
1130
1131
  }
1131
1132
  let keywordList = parsedKeywords.slice();
1132
- logger.info(`关键词解析结果: [${keywordList.join(", ")}] - 原始输入: "${rawInput}"`);
1133
+ logger.debug(`关键词解析结果: [${keywordList.join(", ")}] - 原始输入: "${rawInput}"`);
1133
1134
  if (keywordList.length === 0 && !cleanedOptions.query && !cleanedOptions.remove) {
1134
1135
  const hasConfigParams = cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || hasRealMessageParam || hasRealEnableMessageParam || hasRealDisableMessageParam;
1135
1136
  if (!hasConfigParams) {
@@ -1162,7 +1163,7 @@ ${config2.reminderMessage || "无"}
1162
1163
  reviewMethod = existingConfig.reviewMethod;
1163
1164
  if (existingConfig.reviewParameters === void 0 || existingConfig.reviewParameters === null || isNaN(existingConfig.reviewParameters)) {
1164
1165
  reviewParameters = 0;
1165
- logger.info(`检测到老版本数据或无效值,使用默认阈值: 0`);
1166
+ logger.debug(`检测到老版本数据或无效值,使用默认阈值: 0`);
1166
1167
  } else {
1167
1168
  reviewParameters = existingConfig.reviewParameters;
1168
1169
  }
@@ -1215,7 +1216,7 @@ ${config2.reminderMessage || "无"}
1215
1216
  const encodedKeywords = keywordList.map((keyword) => {
1216
1217
  return keyword.replace(/,/g, "[[COMMA]]");
1217
1218
  });
1218
- logger.info(`编码后准备存储的关键词: ${JSON.stringify(encodedKeywords)}`);
1219
+ logger.debug(`编码后准备存储的关键词: ${JSON.stringify(encodedKeywords)}`);
1219
1220
  const dbData = {
1220
1221
  keywords: encodedKeywords,
1221
1222
  reviewMethod,
@@ -1259,24 +1260,25 @@ ${config2.reminderMessage || "无"}
1259
1260
  feedbackMessage += `提醒状态: ${reminderEnabled ? "启用" : "禁用"}
1260
1261
  `;
1261
1262
  if (reminderMessage && reminderEnabled) {
1263
+ const displayReminder = reminderMessage.replace(/\\\\n/g, "").replace(/\\n/g, "\n").replace(/\x01/g, "\\n");
1262
1264
  feedbackMessage += `提醒消息:
1263
- ${reminderMessage}
1265
+ ${displayReminder}
1264
1266
  `;
1265
1267
  }
1266
- logger.info(`准备存储到数据库的关键词: ${JSON.stringify(encodedKeywords)}`);
1267
- logger.info(`=== 配置处理详情 ===`);
1268
- logger.info(`原始输入: ${keywords || "无关键词"}`);
1269
- logger.info(`审核方式: ${reviewMethod} (${["全部同意", "按数量", "按比例", "全部拒绝"][reviewMethod]})`);
1270
- logger.info(`阈值参数: ${JSON.stringify(reviewParameters)}`);
1271
- logger.info(`关键词列表: [${keywordList.map((k) => `"${k}"`).join(", ")}]`);
1272
- 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 ? "存在" : "不存在"}`);
1273
1275
  if (existingConfig) {
1274
- logger.info(`原审核方式: ${existingConfig.reviewMethod}`);
1275
- logger.info(`原阈值: ${JSON.stringify(existingConfig.reviewParameters)}`);
1276
- logger.info(`原关键词数: ${existingConfig.keywords.length}`);
1277
- 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}`);
1278
1280
  }
1279
- logger.info(`==================`);
1281
+ logger.debug(`==================`);
1280
1282
  logger.info(feedbackMessage.replace(/\n/g, "; "));
1281
1283
  return feedbackMessage;
1282
1284
  });
package/package.json CHANGED
@@ -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.34",
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