koishi-plugin-group-verification 1.0.19 → 1.0.21
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/lib/index.d.ts +4 -4
- package/lib/index.js +59 -22
- package/package.json +1 -1
- package/readme.md +9 -0
- package/src/index.ts +82 -37
package/lib/index.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ export interface GroupVerificationConfig {
|
|
|
17
17
|
reminderMessage: string;
|
|
18
18
|
createdBy: string;
|
|
19
19
|
updatedBy: string;
|
|
20
|
-
createdAt: Date;
|
|
21
|
-
updatedAt: Date;
|
|
20
|
+
createdAt: string | Date;
|
|
21
|
+
updatedAt: string | Date;
|
|
22
22
|
}
|
|
23
23
|
export interface GroupVerificationStats {
|
|
24
24
|
id: number;
|
|
@@ -26,7 +26,7 @@ export interface GroupVerificationStats {
|
|
|
26
26
|
autoApproved: number;
|
|
27
27
|
manuallyApproved: number;
|
|
28
28
|
rejected: number;
|
|
29
|
-
lastUpdated: Date;
|
|
29
|
+
lastUpdated: string | Date;
|
|
30
30
|
}
|
|
31
31
|
export interface PendingVerification {
|
|
32
32
|
id: number;
|
|
@@ -34,7 +34,7 @@ export interface PendingVerification {
|
|
|
34
34
|
userId: string;
|
|
35
35
|
userName: string;
|
|
36
36
|
requestMessage: string;
|
|
37
|
-
applyTime: Date;
|
|
37
|
+
applyTime: string | Date;
|
|
38
38
|
}
|
|
39
39
|
export interface Config {
|
|
40
40
|
defaultReminderMessage?: string;
|
package/lib/index.js
CHANGED
|
@@ -299,8 +299,8 @@ function apply(ctx, config) {
|
|
|
299
299
|
reminderMessage: "string",
|
|
300
300
|
createdBy: "string",
|
|
301
301
|
updatedBy: "string",
|
|
302
|
-
createdAt: "
|
|
303
|
-
updatedAt: "
|
|
302
|
+
createdAt: "string",
|
|
303
|
+
updatedAt: "string"
|
|
304
304
|
}, {
|
|
305
305
|
primary: "id",
|
|
306
306
|
autoInc: true
|
|
@@ -316,7 +316,9 @@ function apply(ctx, config) {
|
|
|
316
316
|
autoApproved: "integer",
|
|
317
317
|
manuallyApproved: "integer",
|
|
318
318
|
rejected: "integer",
|
|
319
|
-
|
|
319
|
+
// store as string (ISO timestamp) to preserve full date+time;
|
|
320
|
+
// Koishi `date` type truncates to day which leads to 00:00:00.
|
|
321
|
+
lastUpdated: "string"
|
|
320
322
|
}, {
|
|
321
323
|
primary: "id",
|
|
322
324
|
autoInc: true
|
|
@@ -327,7 +329,8 @@ function apply(ctx, config) {
|
|
|
327
329
|
userId: "string",
|
|
328
330
|
userName: "string",
|
|
329
331
|
requestMessage: "string",
|
|
330
|
-
|
|
332
|
+
// record full timestamp as string to keep time component
|
|
333
|
+
applyTime: "string"
|
|
331
334
|
}, {
|
|
332
335
|
primary: "id",
|
|
333
336
|
autoInc: true
|
|
@@ -390,29 +393,30 @@ function apply(ctx, config) {
|
|
|
390
393
|
logger.info(`用户 ${userId} 被手动邀请加入群 ${groupId},手动批准统计已更新`);
|
|
391
394
|
}
|
|
392
395
|
});
|
|
393
|
-
async function handleFailedVerification(ctx2, session, config2) {
|
|
394
|
-
const guildId = session.guildId;
|
|
396
|
+
async function handleFailedVerification(ctx2, session, config2, matchedCount, requiredThreshold) {
|
|
397
|
+
const guildId = (session.guildId || session.channelId || "").toString().trim();
|
|
395
398
|
const userId = session.userId;
|
|
396
399
|
const username = session.username || "未知用户";
|
|
397
400
|
const message = session.content || "";
|
|
401
|
+
logger.info(`处理失败验证 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold}`);
|
|
402
|
+
if (matchedCount === void 0 || requiredThreshold === void 0) {
|
|
403
|
+
const result = await verifyApplication(config2, message, session);
|
|
404
|
+
matchedCount = result.matchedCount;
|
|
405
|
+
requiredThreshold = result.requiredThreshold;
|
|
406
|
+
}
|
|
398
407
|
let groupName = "未知群组";
|
|
399
408
|
try {
|
|
400
409
|
const guild = await session.bot.getGuild(guildId);
|
|
401
410
|
groupName = guild.name || groupName;
|
|
402
411
|
} catch (error) {
|
|
403
412
|
}
|
|
404
|
-
const { matchedCount, requiredThreshold } = await verifyApplication(config2, message, session);
|
|
405
413
|
await ctx2.database.create("group_verification_pending", {
|
|
406
414
|
groupId: guildId,
|
|
407
415
|
userId,
|
|
408
416
|
userName: username,
|
|
409
417
|
requestMessage: message,
|
|
410
|
-
applyTime: /* @__PURE__ */ new Date()
|
|
418
|
+
applyTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
411
419
|
});
|
|
412
|
-
if (!guildId) {
|
|
413
|
-
logger.warn("handleFailedVerification 收到无效 guildId,已放弃发送");
|
|
414
|
-
return;
|
|
415
|
-
}
|
|
416
420
|
if (!config2.reminderEnabled || !config2.reminderMessage || config2.reminderMessage === "") {
|
|
417
421
|
logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`);
|
|
418
422
|
return;
|
|
@@ -428,7 +432,7 @@ function apply(ctx, config) {
|
|
|
428
432
|
const stats = existingStats[0];
|
|
429
433
|
await ctx.database.set("group_verification_stats", { id: stats.id }, {
|
|
430
434
|
[action]: stats[action] + 1,
|
|
431
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
435
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
432
436
|
});
|
|
433
437
|
} else {
|
|
434
438
|
await ctx.database.create("group_verification_stats", {
|
|
@@ -436,7 +440,7 @@ function apply(ctx, config) {
|
|
|
436
440
|
autoApproved: action === "autoApproved" ? 1 : 0,
|
|
437
441
|
manuallyApproved: action === "manuallyApproved" ? 1 : 0,
|
|
438
442
|
rejected: action === "rejected" ? 1 : 0,
|
|
439
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
443
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
440
444
|
});
|
|
441
445
|
}
|
|
442
446
|
await syncTotalStats(ctx);
|
|
@@ -533,8 +537,8 @@ ${debugInfo}`];
|
|
|
533
537
|
remove: flags.remove || options.remove
|
|
534
538
|
};
|
|
535
539
|
logger.info(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`);
|
|
536
|
-
if ((cleanedOptions.query || cleanedOptions.remove) && (parsedKeywords.length > 0 || cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || cleanedOptions.message !== void 0 || cleanedOptions.enableMessage || cleanedOptions.disableMessage
|
|
537
|
-
return "参数冲突:-? 或 -r
|
|
540
|
+
if ((cleanedOptions.query || cleanedOptions.remove) && (parsedKeywords.length > 0 || cleanedOptions.method !== void 0 || cleanedOptions.threshold !== void 0 || cleanedOptions.message !== void 0 || cleanedOptions.enableMessage || cleanedOptions.disableMessage)) {
|
|
541
|
+
return "参数冲突:-? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)";
|
|
538
542
|
}
|
|
539
543
|
const hasRealMessageParam = cleanedOptions.message !== void 0;
|
|
540
544
|
const hasRealEnableMessageParam = cleanedOptions.enableMessage === true;
|
|
@@ -712,7 +716,7 @@ gvc -r # 删除配置`;
|
|
|
712
716
|
await ctx.database.set("group_verification_config", { id: existingConfig.id }, {
|
|
713
717
|
reviewParameters,
|
|
714
718
|
updatedBy: session.username || session.userId,
|
|
715
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
719
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
716
720
|
});
|
|
717
721
|
logger.info(`已更新数据库阈值为: ${reviewParameters}`);
|
|
718
722
|
} else {
|
|
@@ -731,17 +735,20 @@ gvc -r # 删除配置`;
|
|
|
731
735
|
reminderEnabled,
|
|
732
736
|
reminderMessage,
|
|
733
737
|
updatedBy: session.username || session.userId,
|
|
734
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
738
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
735
739
|
};
|
|
736
740
|
if (existingConfig) {
|
|
737
|
-
await ctx.database.set("group_verification_config", { id: existingConfig.id },
|
|
741
|
+
await ctx.database.set("group_verification_config", { id: existingConfig.id }, {
|
|
742
|
+
...dbData,
|
|
743
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
744
|
+
});
|
|
738
745
|
logger.info(`更新配置成功 - 审核方式: ${reviewMethod}, 阈值: ${reviewParameters}`);
|
|
739
746
|
} else {
|
|
740
747
|
await ctx.database.create("group_verification_config", {
|
|
741
748
|
groupId: targetGroupId,
|
|
742
749
|
...dbData,
|
|
743
750
|
createdBy: session.username || session.userId,
|
|
744
|
-
createdAt: /* @__PURE__ */ new Date()
|
|
751
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
745
752
|
});
|
|
746
753
|
logger.info(`创建配置成功 - 审核方式: ${reviewMethod}, 阈值: ${reviewParameters}`);
|
|
747
754
|
}
|
|
@@ -1047,6 +1054,36 @@ gvc -r # 删除配置`;
|
|
|
1047
1054
|
- 私聊时必须指定群号(-i参数)`;
|
|
1048
1055
|
});
|
|
1049
1056
|
ctx.on("ready", async () => {
|
|
1057
|
+
try {
|
|
1058
|
+
const configs = await ctx.database.get("group_verification_config", {});
|
|
1059
|
+
for (const cfg of configs) {
|
|
1060
|
+
const updates = {};
|
|
1061
|
+
if (cfg.createdAt instanceof Date) updates.createdAt = cfg.createdAt.toISOString();
|
|
1062
|
+
if (cfg.updatedAt instanceof Date) updates.updatedAt = cfg.updatedAt.toISOString();
|
|
1063
|
+
if (Object.keys(updates).length) {
|
|
1064
|
+
await ctx.database.set("group_verification_config", { id: cfg.id }, updates);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
const stats = await ctx.database.get("group_verification_stats", {});
|
|
1068
|
+
for (const st of stats) {
|
|
1069
|
+
const updates = {};
|
|
1070
|
+
if (st.lastUpdated instanceof Date) updates.lastUpdated = st.lastUpdated.toISOString();
|
|
1071
|
+
if (Object.keys(updates).length) {
|
|
1072
|
+
await ctx.database.set("group_verification_stats", { id: st.id }, updates);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
const pendings = await ctx.database.get("group_verification_pending", {});
|
|
1076
|
+
for (const p of pendings) {
|
|
1077
|
+
const updates = {};
|
|
1078
|
+
if (p.applyTime instanceof Date) updates.applyTime = p.applyTime.toISOString();
|
|
1079
|
+
if (Object.keys(updates).length) {
|
|
1080
|
+
await ctx.database.set("group_verification_pending", { id: p.id }, updates);
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
logger.info("旧版日期字段迁移完成");
|
|
1084
|
+
} catch (e) {
|
|
1085
|
+
logger.warn("迁移旧日期字段时出错", e);
|
|
1086
|
+
}
|
|
1050
1087
|
const totalStats = await ctx.database.get("group_verification_stats", { groupId: "TOTAL" });
|
|
1051
1088
|
if (totalStats.length === 0) {
|
|
1052
1089
|
await ctx.database.create("group_verification_stats", {
|
|
@@ -1054,7 +1091,7 @@ gvc -r # 删除配置`;
|
|
|
1054
1091
|
autoApproved: 0,
|
|
1055
1092
|
manuallyApproved: 0,
|
|
1056
1093
|
rejected: 0,
|
|
1057
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
1094
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
1058
1095
|
});
|
|
1059
1096
|
logger.info("已创建总计统计行");
|
|
1060
1097
|
} else {
|
|
@@ -1103,7 +1140,7 @@ gvc -r # 删除配置`;
|
|
|
1103
1140
|
autoApproved: totalAutoApproved,
|
|
1104
1141
|
manuallyApproved: totalManuallyApproved,
|
|
1105
1142
|
rejected: totalRejected,
|
|
1106
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
1143
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString()
|
|
1107
1144
|
});
|
|
1108
1145
|
logger.info(`总计统计已同步: 自动批准${totalAutoApproved}, 手动批准${totalManuallyApproved}, 拒绝${totalRejected}`);
|
|
1109
1146
|
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -48,6 +48,9 @@ group-verify.config -r
|
|
|
48
48
|
|
|
49
49
|
# 指定群号配置
|
|
50
50
|
group-verify.config -i 123456789 关键词1,关键词2 -m 1 -t 1
|
|
51
|
+
|
|
52
|
+
> **提示**: `-?`(查询)和 `-r`(删除)仍然与所有其它参数 / 关键字互斥,
|
|
53
|
+
> 但可以和 `-i` 组合使用,例如 `gvc -i 123 -?` 或 `gvc -i 123 -r`。这样便于在私聊环境下查询或删除指定群的设置。
|
|
51
54
|
```
|
|
52
55
|
|
|
53
56
|
### 审核命令
|
|
@@ -106,6 +109,12 @@ group-verify.stats total
|
|
|
106
109
|
- `-nomsg` - 禁用提醒消息功能
|
|
107
110
|
- 不带参数的 `-msg` 会显示帮助信息
|
|
108
111
|
|
|
112
|
+
### 提醒消息变量
|
|
113
|
+
|
|
114
|
+
### 其他注意事项
|
|
115
|
+
|
|
116
|
+
- 统计数据的 **最后更新时间** 使用完整的日期+时间存储,升级到最新版后若看到 `00:00:00`,请手动重建或清除旧的统计记录以便记录最新时间。
|
|
117
|
+
|
|
109
118
|
### 提醒消息变量
|
|
110
119
|
```
|
|
111
120
|
{user} - 用户名
|
package/src/index.ts
CHANGED
|
@@ -25,8 +25,8 @@ export interface GroupVerificationConfig {
|
|
|
25
25
|
reminderMessage: string
|
|
26
26
|
createdBy: string
|
|
27
27
|
updatedBy: string
|
|
28
|
-
createdAt: Date
|
|
29
|
-
updatedAt: Date
|
|
28
|
+
createdAt: string | Date
|
|
29
|
+
updatedAt: string | Date
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// 群组统计信息表
|
|
@@ -36,7 +36,7 @@ export interface GroupVerificationStats {
|
|
|
36
36
|
autoApproved: number
|
|
37
37
|
manuallyApproved: number
|
|
38
38
|
rejected: number
|
|
39
|
-
lastUpdated: Date
|
|
39
|
+
lastUpdated: string | Date
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// 待审核申请表
|
|
@@ -46,7 +46,7 @@ export interface PendingVerification {
|
|
|
46
46
|
userId: string
|
|
47
47
|
userName: string
|
|
48
48
|
requestMessage: string
|
|
49
|
-
applyTime: Date
|
|
49
|
+
applyTime: string | Date
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export interface Config {
|
|
@@ -417,8 +417,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
417
417
|
reminderMessage: 'string',
|
|
418
418
|
createdBy: 'string',
|
|
419
419
|
updatedBy: 'string',
|
|
420
|
-
createdAt: '
|
|
421
|
-
updatedAt: '
|
|
420
|
+
createdAt: 'string',
|
|
421
|
+
updatedAt: 'string'
|
|
422
422
|
}, {
|
|
423
423
|
primary: 'id',
|
|
424
424
|
autoInc: true
|
|
@@ -442,7 +442,9 @@ export function apply(ctx: Context, config: Config) {
|
|
|
442
442
|
autoApproved: 'integer',
|
|
443
443
|
manuallyApproved: 'integer',
|
|
444
444
|
rejected: 'integer',
|
|
445
|
-
|
|
445
|
+
// store as string (ISO timestamp) to preserve full date+time;
|
|
446
|
+
// Koishi `date` type truncates to day which leads to 00:00:00.
|
|
447
|
+
lastUpdated: 'string'
|
|
446
448
|
}, {
|
|
447
449
|
primary: 'id',
|
|
448
450
|
autoInc: true
|
|
@@ -454,7 +456,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
454
456
|
userId: 'string',
|
|
455
457
|
userName: 'string',
|
|
456
458
|
requestMessage: 'string',
|
|
457
|
-
|
|
459
|
+
// record full timestamp as string to keep time component
|
|
460
|
+
applyTime: 'string'
|
|
458
461
|
}, {
|
|
459
462
|
primary: 'id',
|
|
460
463
|
autoInc: true
|
|
@@ -546,12 +549,27 @@ export function apply(ctx: Context, config: Config) {
|
|
|
546
549
|
})
|
|
547
550
|
|
|
548
551
|
// 处理验证失败的情况
|
|
549
|
-
|
|
550
|
-
|
|
552
|
+
// 处理验证失败的情况并发送提醒消息
|
|
553
|
+
// matchedCount/requiredThreshold 可选,为空时内部重新计算(兼容旧调用)
|
|
554
|
+
async function handleFailedVerification(
|
|
555
|
+
ctx: Context,
|
|
556
|
+
session: any,
|
|
557
|
+
config: GroupVerificationConfig,
|
|
558
|
+
matchedCount?: number,
|
|
559
|
+
requiredThreshold?: string
|
|
560
|
+
) {
|
|
561
|
+
const guildId = (session.guildId || session.channelId || '').toString().trim();
|
|
551
562
|
const userId = session.userId
|
|
552
563
|
const username = session.username || '未知用户'
|
|
553
564
|
const message = session.content || ''
|
|
554
|
-
|
|
565
|
+
logger.info(`处理失败验证 guild=${guildId} user=${userId} msg="${message}" matched=${matchedCount} threshold=${requiredThreshold}`)
|
|
566
|
+
// 如果未传入匹配信息,则重新计算一次(老调用)
|
|
567
|
+
if (matchedCount === undefined || requiredThreshold === undefined) {
|
|
568
|
+
const result = await verifyApplication(config, message, session)
|
|
569
|
+
matchedCount = result.matchedCount
|
|
570
|
+
requiredThreshold = result.requiredThreshold
|
|
571
|
+
}
|
|
572
|
+
|
|
555
573
|
// 获取群信息
|
|
556
574
|
let groupName = '未知群组'
|
|
557
575
|
try {
|
|
@@ -560,30 +578,21 @@ export function apply(ctx: Context, config: Config) {
|
|
|
560
578
|
} catch (error) {
|
|
561
579
|
// 无法获取群名称时使用默认值
|
|
562
580
|
}
|
|
563
|
-
|
|
564
|
-
// 执行验证获取详细信息
|
|
565
|
-
const { matchedCount, requiredThreshold } = await verifyApplication(config, message, session)
|
|
566
|
-
|
|
581
|
+
|
|
567
582
|
// 将申请加入待审核列表
|
|
568
583
|
await ctx.database.create('group_verification_pending', {
|
|
569
584
|
groupId: guildId,
|
|
570
585
|
userId: userId,
|
|
571
586
|
userName: username,
|
|
572
587
|
requestMessage: message,
|
|
573
|
-
applyTime: new Date()
|
|
588
|
+
applyTime: new Date().toISOString()
|
|
574
589
|
})
|
|
575
|
-
|
|
576
|
-
// 如果 guildId 不合法,跳过
|
|
577
|
-
if (!guildId) {
|
|
578
|
-
logger.warn('handleFailedVerification 收到无效 guildId,已放弃发送')
|
|
579
|
-
return
|
|
580
|
-
}
|
|
581
590
|
// 如果提醒消息被禁用,直接返回
|
|
582
591
|
if (!config.reminderEnabled || !config.reminderMessage || config.reminderMessage === '') {
|
|
583
592
|
logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`)
|
|
584
593
|
return
|
|
585
594
|
}
|
|
586
|
-
|
|
595
|
+
|
|
587
596
|
// 替换提醒消息中的变量
|
|
588
597
|
let reminderMsg = config.reminderMessage
|
|
589
598
|
reminderMsg = reminderMsg
|
|
@@ -592,9 +601,9 @@ export function apply(ctx: Context, config: Config) {
|
|
|
592
601
|
.replace(/{group}/g, guildId)
|
|
593
602
|
.replace(/{gname}/g, groupName)
|
|
594
603
|
.replace(/{question}/g, message)
|
|
595
|
-
.replace(/{answer}/g, matchedCount
|
|
596
|
-
.replace(/{threshold}/g, requiredThreshold)
|
|
597
|
-
|
|
604
|
+
.replace(/{answer}/g, matchedCount!.toString())
|
|
605
|
+
.replace(/{threshold}/g, requiredThreshold!)
|
|
606
|
+
|
|
598
607
|
// 发送提醒消息到群内
|
|
599
608
|
await ctx.broadcast([guildId], reminderMsg)
|
|
600
609
|
}
|
|
@@ -609,7 +618,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
609
618
|
const stats = existingStats[0]
|
|
610
619
|
await ctx.database.set('group_verification_stats', { id: stats.id }, {
|
|
611
620
|
[action]: stats[action] + 1,
|
|
612
|
-
lastUpdated: new Date()
|
|
621
|
+
lastUpdated: new Date().toISOString()
|
|
613
622
|
})
|
|
614
623
|
} else {
|
|
615
624
|
await ctx.database.create('group_verification_stats', {
|
|
@@ -617,7 +626,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
617
626
|
autoApproved: action === 'autoApproved' ? 1 : 0,
|
|
618
627
|
manuallyApproved: action === 'manuallyApproved' ? 1 : 0,
|
|
619
628
|
rejected: action === 'rejected' ? 1 : 0,
|
|
620
|
-
lastUpdated: new Date()
|
|
629
|
+
lastUpdated: new Date().toISOString()
|
|
621
630
|
})
|
|
622
631
|
}
|
|
623
632
|
|
|
@@ -755,11 +764,11 @@ export function apply(ctx: Context, config: Config) {
|
|
|
755
764
|
}
|
|
756
765
|
logger.info(`合并后options: ${JSON.stringify(cleanedOptions, null, 2)}`)
|
|
757
766
|
|
|
758
|
-
// 检查 -? 和 -r
|
|
767
|
+
// 检查 -? 和 -r 的独占性;允许与 -i 并存
|
|
759
768
|
if ((cleanedOptions.query || cleanedOptions.remove) &&
|
|
760
769
|
(parsedKeywords.length > 0 || cleanedOptions.method !== undefined || cleanedOptions.threshold !== undefined ||
|
|
761
|
-
cleanedOptions.message !== undefined || cleanedOptions.enableMessage || cleanedOptions.disableMessage
|
|
762
|
-
return '参数冲突:-? 或 -r
|
|
770
|
+
cleanedOptions.message !== undefined || cleanedOptions.enableMessage || cleanedOptions.disableMessage)) {
|
|
771
|
+
return '参数冲突:-? 或 -r 不能与其他参数或关键词一起使用(仅可搭配 -i)'
|
|
763
772
|
}
|
|
764
773
|
|
|
765
774
|
// 检查消息参数冲突
|
|
@@ -999,7 +1008,7 @@ gvc -r # 删除配置`
|
|
|
999
1008
|
await ctx.database.set('group_verification_config', { id: existingConfig.id }, {
|
|
1000
1009
|
reviewParameters: reviewParameters,
|
|
1001
1010
|
updatedBy: session.username || session.userId,
|
|
1002
|
-
updatedAt: new Date()
|
|
1011
|
+
updatedAt: new Date().toISOString()
|
|
1003
1012
|
})
|
|
1004
1013
|
logger.info(`已更新数据库阈值为: ${reviewParameters}`)
|
|
1005
1014
|
} else {
|
|
@@ -1025,18 +1034,22 @@ gvc -r # 删除配置`
|
|
|
1025
1034
|
reminderEnabled: reminderEnabled,
|
|
1026
1035
|
reminderMessage: reminderMessage,
|
|
1027
1036
|
updatedBy: session.username || session.userId,
|
|
1028
|
-
updatedAt: new Date()
|
|
1037
|
+
updatedAt: new Date().toISOString()
|
|
1029
1038
|
}
|
|
1030
1039
|
|
|
1031
1040
|
if (existingConfig) {
|
|
1032
|
-
|
|
1041
|
+
// ensure timestamp strings for compatibility
|
|
1042
|
+
await ctx.database.set('group_verification_config', { id: existingConfig.id }, {
|
|
1043
|
+
...dbData,
|
|
1044
|
+
updatedAt: new Date().toISOString(),
|
|
1045
|
+
})
|
|
1033
1046
|
logger.info(`更新配置成功 - 审核方式: ${reviewMethod}, 阈值: ${reviewParameters}`)
|
|
1034
1047
|
} else {
|
|
1035
1048
|
await ctx.database.create('group_verification_config', {
|
|
1036
1049
|
groupId: targetGroupId,
|
|
1037
1050
|
...dbData,
|
|
1038
1051
|
createdBy: session.username || session.userId,
|
|
1039
|
-
createdAt: new Date()
|
|
1052
|
+
createdAt: new Date().toISOString()
|
|
1040
1053
|
})
|
|
1041
1054
|
logger.info(`创建配置成功 - 审核方式: ${reviewMethod}, 阈值: ${reviewParameters}`)
|
|
1042
1055
|
}
|
|
@@ -1419,6 +1432,38 @@ gvc -r # 删除配置`
|
|
|
1419
1432
|
|
|
1420
1433
|
// 插件初始化时确保总计统计行存在
|
|
1421
1434
|
ctx.on('ready', async () => {
|
|
1435
|
+
// 迁移:将旧版保留的 Date 对象字段转换为 ISO 字符串,以避免绑定错误
|
|
1436
|
+
try {
|
|
1437
|
+
const configs = await ctx.database.get('group_verification_config', {})
|
|
1438
|
+
for (const cfg of configs) {
|
|
1439
|
+
const updates: any = {}
|
|
1440
|
+
if (cfg.createdAt instanceof Date) updates.createdAt = cfg.createdAt.toISOString()
|
|
1441
|
+
if (cfg.updatedAt instanceof Date) updates.updatedAt = cfg.updatedAt.toISOString()
|
|
1442
|
+
if (Object.keys(updates).length) {
|
|
1443
|
+
await ctx.database.set('group_verification_config', { id: cfg.id }, updates)
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
const stats = await ctx.database.get('group_verification_stats', {})
|
|
1447
|
+
for (const st of stats) {
|
|
1448
|
+
const updates: any = {}
|
|
1449
|
+
if (st.lastUpdated instanceof Date) updates.lastUpdated = st.lastUpdated.toISOString()
|
|
1450
|
+
if (Object.keys(updates).length) {
|
|
1451
|
+
await ctx.database.set('group_verification_stats', { id: st.id }, updates)
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
const pendings = await ctx.database.get('group_verification_pending', {})
|
|
1455
|
+
for (const p of pendings) {
|
|
1456
|
+
const updates: any = {}
|
|
1457
|
+
if (p.applyTime instanceof Date) updates.applyTime = p.applyTime.toISOString()
|
|
1458
|
+
if (Object.keys(updates).length) {
|
|
1459
|
+
await ctx.database.set('group_verification_pending', { id: p.id }, updates)
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
logger.info('旧版日期字段迁移完成')
|
|
1463
|
+
} catch (e) {
|
|
1464
|
+
logger.warn('迁移旧日期字段时出错', e)
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1422
1467
|
// 检查是否已存在总计行(groupId为'TOTAL')
|
|
1423
1468
|
const totalStats = await ctx.database.get('group_verification_stats', { groupId: 'TOTAL' })
|
|
1424
1469
|
|
|
@@ -1429,7 +1474,7 @@ gvc -r # 删除配置`
|
|
|
1429
1474
|
autoApproved: 0,
|
|
1430
1475
|
manuallyApproved: 0,
|
|
1431
1476
|
rejected: 0,
|
|
1432
|
-
lastUpdated: new Date()
|
|
1477
|
+
lastUpdated: new Date().toISOString()
|
|
1433
1478
|
})
|
|
1434
1479
|
logger.info('已创建总计统计行')
|
|
1435
1480
|
} else {
|
|
@@ -1495,7 +1540,7 @@ gvc -r # 删除配置`
|
|
|
1495
1540
|
autoApproved: totalAutoApproved,
|
|
1496
1541
|
manuallyApproved: totalManuallyApproved,
|
|
1497
1542
|
rejected: totalRejected,
|
|
1498
|
-
lastUpdated: new Date()
|
|
1543
|
+
lastUpdated: new Date().toISOString()
|
|
1499
1544
|
})
|
|
1500
1545
|
|
|
1501
1546
|
logger.info(`总计统计已同步: 自动批准${totalAutoApproved}, 手动批准${totalManuallyApproved}, 拒绝${totalRejected}`)
|