koishi-plugin-group-verification 1.0.12 → 1.0.14
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 +1 -0
- package/lib/index.js +99 -45
- package/package.json +1 -1
- package/readme.md +132 -99
- package/src/index.ts +130 -51
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -46,6 +46,7 @@ function apply(ctx, config) {
|
|
|
46
46
|
keywords: "list",
|
|
47
47
|
reviewMethod: "integer",
|
|
48
48
|
reviewParameters: "json",
|
|
49
|
+
reminderEnabled: "boolean",
|
|
49
50
|
reminderMessage: "string",
|
|
50
51
|
createdBy: "string",
|
|
51
52
|
updatedBy: "string",
|
|
@@ -134,6 +135,10 @@ function apply(ctx, config) {
|
|
|
134
135
|
requestMessage: message,
|
|
135
136
|
applyTime: /* @__PURE__ */ new Date()
|
|
136
137
|
});
|
|
138
|
+
if (!config2.reminderEnabled || !config2.reminderMessage || config2.reminderMessage === "") {
|
|
139
|
+
logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
137
142
|
let reminderMsg = config2.reminderMessage;
|
|
138
143
|
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);
|
|
139
144
|
await ctx2.broadcast([guildId], reminderMsg);
|
|
@@ -259,7 +264,7 @@ ${debugInfo}`];
|
|
|
259
264
|
"gverify.配置",
|
|
260
265
|
"group-verify.配置",
|
|
261
266
|
"gvc"
|
|
262
|
-
).option("groupId", "-i <groupId> 指定群号").option("method", "-m <method> 审核方式 (0-3)").option("threshold", "-t <threshold> 阈值参数").option("message", "-msg
|
|
267
|
+
).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) => {
|
|
263
268
|
const targetGroupId = options.groupId || session.guildId;
|
|
264
269
|
const [hasPermission, errorMsg] = await checkPermission(session, targetGroupId);
|
|
265
270
|
if (!hasPermission) {
|
|
@@ -308,11 +313,13 @@ ${debugInfo}`];
|
|
|
308
313
|
}
|
|
309
314
|
const createTime = new Date(config2.createdAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
310
315
|
const updateTime = new Date(config2.updatedAt).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
316
|
+
const reminderStatus = config2.reminderEnabled ? "启用" : "禁用";
|
|
311
317
|
return `群 ${targetGroupId} 配置:
|
|
312
318
|
关键词: ${config2.keywords.join(", ")}
|
|
313
319
|
审核方式: ${methodDesc}
|
|
314
320
|
阈值: ${thresholdInfo}
|
|
315
|
-
提醒消息: ${
|
|
321
|
+
提醒消息: ${reminderStatus}
|
|
322
|
+
自定义消息: ${config2.reminderMessage || "无"}
|
|
316
323
|
创建时间: ${createTime}
|
|
317
324
|
更新时间: ${updateTime}
|
|
318
325
|
创建者: ${config2.createdBy}
|
|
@@ -321,47 +328,89 @@ ${debugInfo}`];
|
|
|
321
328
|
return `群 ${targetGroupId} 无验证配置`;
|
|
322
329
|
}
|
|
323
330
|
}
|
|
324
|
-
|
|
325
|
-
if (
|
|
326
|
-
|
|
331
|
+
let keywordList = keywords ? keywords.split(",").map((k) => k.trim()).filter((k) => k) : [];
|
|
332
|
+
if (!keywords && !options.query && !options.remove) {
|
|
333
|
+
const hasConfigParams = options.method !== void 0 || options.threshold !== void 0 || options.message !== void 0 || options.disableMessage !== void 0;
|
|
334
|
+
if (!hasConfigParams) {
|
|
335
|
+
return `用法:
|
|
336
|
+
gvc 关键词1,关键词2 -m 1 -t 2 # 创建配置
|
|
337
|
+
gvc -m 1 -t 2 # 修改审核参数
|
|
338
|
+
gvc -msg "消息内容" # 修改提醒消息
|
|
339
|
+
gvc -nomsg # 禁用提醒消息
|
|
340
|
+
gvc -? # 查询配置
|
|
341
|
+
gvc -r # 删除配置`;
|
|
342
|
+
}
|
|
343
|
+
const existingConfig2 = await ctx.database.get("group_verification_config", { groupId: targetGroupId });
|
|
344
|
+
if (existingConfig2.length === 0) {
|
|
345
|
+
return "请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置";
|
|
346
|
+
}
|
|
347
|
+
keywordList = existingConfig2[0].keywords;
|
|
348
|
+
}
|
|
349
|
+
let reminderEnabled = true;
|
|
350
|
+
let reminderMessage = config.defaultReminderMessage || `用户 {user}({id}) 申请加入群 {gname}({group})
|
|
351
|
+
申请理由:{question}
|
|
352
|
+
答对情况:{answer}
|
|
353
|
+
阈值要求:{threshold}
|
|
354
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`;
|
|
355
|
+
if (options.disableMessage) {
|
|
356
|
+
reminderEnabled = false;
|
|
357
|
+
reminderMessage = "";
|
|
358
|
+
} else if (options.message !== void 0) {
|
|
359
|
+
reminderEnabled = true;
|
|
360
|
+
reminderMessage = options.message || config.defaultReminderMessage || `用户 {user}({id}) 申请加入群 {gname}({group})
|
|
361
|
+
申请理由:{question}
|
|
362
|
+
答对情况:{answer}
|
|
363
|
+
阈值要求:{threshold}
|
|
364
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`;
|
|
365
|
+
}
|
|
366
|
+
if (reminderEnabled && reminderMessage) {
|
|
367
|
+
reminderMessage = reminderMessage.replace(/\\n/g, "\n");
|
|
327
368
|
}
|
|
328
369
|
let reviewMethod = 0;
|
|
329
370
|
let reviewParameters = {};
|
|
371
|
+
if (!keywords && !options.query && !options.remove) {
|
|
372
|
+
const existingConfig2 = await ctx.database.get("group_verification_config", { groupId: targetGroupId });
|
|
373
|
+
if (existingConfig2.length > 0) {
|
|
374
|
+
reviewMethod = existingConfig2[0].reviewMethod;
|
|
375
|
+
if (existingConfig2[0].reviewParameters?.threshold) {
|
|
376
|
+
reviewParameters.threshold = existingConfig2[0].reviewParameters.threshold;
|
|
377
|
+
}
|
|
378
|
+
if (options.disableMessage === void 0 && options.message === void 0) {
|
|
379
|
+
reminderEnabled = existingConfig2[0].reminderEnabled;
|
|
380
|
+
reminderMessage = existingConfig2[0].reminderMessage;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
330
384
|
if (options.method !== void 0) {
|
|
331
385
|
const methodNum = parseInt(options.method);
|
|
332
386
|
if (isNaN(methodNum) || methodNum < 0 || methodNum > 3) {
|
|
333
387
|
return "审核方式参数错误:0-全部同意, 1-按数量同意, 2-按比例同意, 3-全部拒绝";
|
|
334
388
|
}
|
|
335
389
|
reviewMethod = methodNum;
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
390
|
+
}
|
|
391
|
+
if ((reviewMethod === 1 || reviewMethod === 2) && options.threshold !== void 0) {
|
|
392
|
+
const thresholdNum = parseInt(options.threshold);
|
|
393
|
+
if (isNaN(thresholdNum)) {
|
|
394
|
+
return "阈值参数必须为数字";
|
|
395
|
+
}
|
|
396
|
+
if (reviewMethod === 1) {
|
|
397
|
+
if (thresholdNum <= 0 || thresholdNum > keywordList.length) {
|
|
398
|
+
return `数量阈值必须在1-${keywordList.length}之间`;
|
|
340
399
|
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
reviewParameters.threshold = thresholdNum;
|
|
346
|
-
} else if (reviewMethod === 2) {
|
|
347
|
-
if (thresholdNum <= 0 || thresholdNum > 100) {
|
|
348
|
-
return "比例阈值必须在1-100之间";
|
|
349
|
-
}
|
|
350
|
-
reviewParameters.threshold = thresholdNum;
|
|
400
|
+
reviewParameters.threshold = thresholdNum;
|
|
401
|
+
} else if (reviewMethod === 2) {
|
|
402
|
+
if (thresholdNum <= 0 || thresholdNum > 100) {
|
|
403
|
+
return "比例阈值必须在1-100之间";
|
|
351
404
|
}
|
|
405
|
+
reviewParameters.threshold = thresholdNum;
|
|
352
406
|
}
|
|
353
407
|
}
|
|
354
|
-
let reminderMessage = options.message || config.defaultReminderMessage || `用户 {user}({id}) 申请加入群 {gname}({group})
|
|
355
|
-
申请理由:{question}
|
|
356
|
-
答对情况:{answer}
|
|
357
|
-
阈值要求:{threshold}
|
|
358
|
-
请管理员使用 #同意 或 #拒绝 来处理此申请`;
|
|
359
|
-
reminderMessage = reminderMessage.replace(/\\n/g, "\n");
|
|
360
408
|
const existingConfig = await ctx.database.get("group_verification_config", { groupId: targetGroupId });
|
|
361
409
|
const configData = {
|
|
362
410
|
keywords: keywordList,
|
|
363
411
|
reviewMethod,
|
|
364
412
|
reviewParameters,
|
|
413
|
+
reminderEnabled,
|
|
365
414
|
reminderMessage,
|
|
366
415
|
updatedBy: session.username || session.userId,
|
|
367
416
|
updatedAt: /* @__PURE__ */ new Date()
|
|
@@ -574,28 +623,28 @@ ${debugInfo}`];
|
|
|
574
623
|
});
|
|
575
624
|
return result;
|
|
576
625
|
});
|
|
577
|
-
groupVerify.subcommand(".help", "显示帮助信息").alias(
|
|
578
|
-
"gv.帮助",
|
|
579
|
-
"gverify.帮助",
|
|
580
|
-
"group-verify.帮助"
|
|
581
|
-
).action(() => {
|
|
626
|
+
groupVerify.subcommand(".help", "显示帮助信息").alias("gv.帮助", "gverify.帮助", "group-verify.帮助", "帮助", "hlp", "帮助信息").action(() => {
|
|
582
627
|
return `群组验证命令帮助:
|
|
583
628
|
主指令别名:gv, gverify
|
|
584
629
|
|
|
585
|
-
配置命令 (.config):
|
|
586
|
-
|
|
630
|
+
配置命令 (.config/.cfg):
|
|
631
|
+
用法:
|
|
632
|
+
1. 创建新配置:gv.cfg 关键词1,关键词2 -m 1 -t 2
|
|
633
|
+
2. 修改现有配置:gv.cfg -m 1 -t 2 (不提供关键词)
|
|
634
|
+
3. 启用提醒消息:gv.cfg -msg "消息内容"
|
|
635
|
+
4. 禁用提醒消息:gv.cfg -nomsg
|
|
636
|
+
5. 查询配置:gv.cfg -?
|
|
637
|
+
6. 删除配置:gv.cfg -r
|
|
638
|
+
|
|
639
|
+
参数说明:
|
|
587
640
|
-i <群号> 指定群号(私聊时必需)
|
|
588
641
|
-m <方式> 审核方式 (0=全部同意, 1=按数量, 2=按比例, 3=全部拒绝)
|
|
589
642
|
-t <阈值> 阈值参数(方式1或2时必需)
|
|
590
|
-
-msg
|
|
643
|
+
-msg [消息] 自定义提醒消息(不带参数显示帮助)
|
|
644
|
+
-nomsg 禁用提醒消息
|
|
591
645
|
-? 查询当前配置
|
|
592
646
|
-r 删除配置
|
|
593
647
|
|
|
594
|
-
示例:
|
|
595
|
-
gv.config 关键词1,关键词2 -m 1 -t 2
|
|
596
|
-
gv.config -i 123456789 -?
|
|
597
|
-
gv.config -r -i 123456789
|
|
598
|
-
|
|
599
648
|
提醒消息变量:
|
|
600
649
|
{user} - 用户名
|
|
601
650
|
{id} - 用户ID
|
|
@@ -604,18 +653,23 @@ ${debugInfo}`];
|
|
|
604
653
|
{question} - 申请理由
|
|
605
654
|
{answer} - 答对数量/比例
|
|
606
655
|
{threshold} - 阈值要求
|
|
656
|
+
|
|
657
|
+
消息格式化:
|
|
607
658
|
\\n - 换行符
|
|
659
|
+
可以组合使用变量和换行符创建格式化的消息
|
|
660
|
+
示例:gv.cfg -msg "用户 {user}\\n申请理由:{question}\\n匹配:{answer}/{threshold}"
|
|
661
|
+
|
|
662
|
+
快捷命令:
|
|
663
|
+
gvc - 配置命令快捷方式
|
|
664
|
+
gva - 同意申请快捷命令
|
|
665
|
+
gvr - 拒绝申请快捷命令
|
|
666
|
+
gvp - 查看待审核列表快捷命令
|
|
667
|
+
gvs - 查看统计信息快捷命令
|
|
608
668
|
|
|
609
669
|
权限说明:
|
|
610
670
|
- 群主/管理员权限
|
|
611
671
|
- koishi三级以上权限
|
|
612
|
-
- 私聊时必须指定群号(-i参数)
|
|
613
|
-
|
|
614
|
-
其他命令:
|
|
615
|
-
.approve <用户ID> - 同意加群申请
|
|
616
|
-
.reject <用户ID> - 拒绝加群申请
|
|
617
|
-
.pending - 查看待审核列表
|
|
618
|
-
.stats [群号] - 查看统计信息`;
|
|
672
|
+
- 私聊时必须指定群号(-i参数)`;
|
|
619
673
|
});
|
|
620
674
|
ctx.on("ready", async () => {
|
|
621
675
|
const totalStats = await ctx.database.get("group_verification_stats", { groupId: "TOTAL" });
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -1,151 +1,184 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Koishi 群组验证插件
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
一个功能完整的 Koishi 群组加群验证插件,支持多关键词匹配审核、多种审核方式和详细统计功能。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 🌟 主要特性
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **多关键词匹配**:支持多个关键词的灵活配置
|
|
8
|
+
- **四种审核方式**:全部同意、按数量同意、按比例同意、全部拒绝
|
|
9
|
+
- **完善的权限控制**:群主/管理员权限或 Koishi 三级以上权限
|
|
10
|
+
- **详细的统计功能**:自动记录审核统计和手动入群统计
|
|
11
|
+
- **灵活的消息配置**:支持自定义提醒消息和禁用功能
|
|
12
|
+
- **友好的命令系统**:丰富的别名和快捷命令
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
- ✅ 验证失败时通知管理员审核
|
|
11
|
-
- ✅ 每个群组独立配置
|
|
12
|
-
- ✅ 详细的统计信息(自动通过/手动通过/拒绝)
|
|
13
|
-
- ✅ 管理员指令控制
|
|
14
|
+
## 🚀 安装使用
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
```bash
|
|
17
|
+
# 在 Koishi 控制台中搜索并安装
|
|
18
|
+
koishi-plugin-group-verification
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## 📋 命令说明
|
|
16
22
|
|
|
17
|
-
###
|
|
18
|
-
- `
|
|
19
|
-
- `
|
|
20
|
-
- `
|
|
21
|
-
- `parameters`: 验证参数
|
|
22
|
-
- `reminderMessage`: 提醒消息模板
|
|
23
|
+
### 主指令别名
|
|
24
|
+
- `group-verify` (完整名称)
|
|
25
|
+
- `gv` (快捷别名)
|
|
26
|
+
- `gverify` (中等长度别名)
|
|
23
27
|
|
|
24
|
-
###
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
- `rejected`: 拒绝数量
|
|
28
|
+
### 配置命令
|
|
29
|
+
```
|
|
30
|
+
# 创建新配置
|
|
31
|
+
gvc 关键词1,关键词2,关键词3 -m 1 -t 2
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
-
|
|
32
|
-
- `userId`: 用户ID
|
|
33
|
-
- `userName`: 用户名
|
|
34
|
-
- `requestMessage`: 申请理由
|
|
35
|
-
- `applyTime`: 申请时间
|
|
33
|
+
# 修改审核参数
|
|
34
|
+
gvc -m 2 -t 60
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
# 启用自定义提醒消息
|
|
37
|
+
gvc -msg "用户 {user} 申请入群,匹配 {answer} 个关键词"
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
# 禁用提醒消息
|
|
40
|
+
gvc -nomsg
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
# 查询当前配置
|
|
43
|
+
gvc -?
|
|
42
44
|
|
|
45
|
+
# 删除配置
|
|
46
|
+
gvc -r
|
|
43
47
|
```
|
|
44
|
-
|
|
48
|
+
|
|
49
|
+
### 审核命令
|
|
45
50
|
```
|
|
51
|
+
# 同意申请(处理最近一个)
|
|
52
|
+
gva
|
|
46
53
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- `-m <方式>` 审核方式 (0=全部同意, 1=按数量, 2=按比例, 3=全部拒绝)
|
|
50
|
-
- `-t <阈值>` 阈值参数(方式1或2时必需)
|
|
51
|
-
- `-?` 查询当前配置
|
|
52
|
-
- `-r` 删除配置
|
|
54
|
+
# 同意指定用户
|
|
55
|
+
gva 123456789
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
- **阈值**:当审核方式为1或2时需要指定
|
|
57
|
-
- 方式1(按数量):阈值范围1-关键词总数
|
|
58
|
-
- 方式2(按比例):阈值范围1-100(百分比)
|
|
57
|
+
# 同意所有申请
|
|
58
|
+
gva all
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
# 拒绝申请
|
|
61
|
+
gvr 123456789
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
# 拒绝所有申请
|
|
64
|
+
gvr all
|
|
63
65
|
```
|
|
64
|
-
# 基本配置(全部同意模式)
|
|
65
|
-
group-verify.config 学生,校友,老师
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
### 查询命令
|
|
68
|
+
```
|
|
69
|
+
# 查看待审核列表
|
|
70
|
+
gvp
|
|
69
71
|
|
|
70
|
-
#
|
|
71
|
-
|
|
72
|
+
# 查看统计信息
|
|
73
|
+
gvs
|
|
72
74
|
|
|
73
|
-
#
|
|
74
|
-
|
|
75
|
+
# 查看指定群统计
|
|
76
|
+
gvs 123456789
|
|
75
77
|
|
|
76
|
-
#
|
|
77
|
-
|
|
78
|
+
# 查看总计统计(需要权限)
|
|
79
|
+
gvs total
|
|
80
|
+
```
|
|
78
81
|
|
|
79
|
-
|
|
80
|
-
group-verify.config -i 123456789 -?
|
|
82
|
+
## ⚙️ 参数说明
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
### 审核方式 (-m)
|
|
85
|
+
- `0` - 全部同意(默认)
|
|
86
|
+
- `1` - 按数量同意(需配合 -t 使用)
|
|
87
|
+
- `2` - 按比例同意(需配合 -t 使用)
|
|
88
|
+
- `3` - 全部拒绝
|
|
85
89
|
|
|
86
|
-
###
|
|
90
|
+
### 阈值参数 (-t)
|
|
91
|
+
- 方式1(按数量):需要匹配的关键词数量(1-N)
|
|
92
|
+
- 方式2(按比例):需要达到的百分比(1-100)
|
|
87
93
|
|
|
88
|
-
|
|
94
|
+
### 提醒消息配置
|
|
95
|
+
- `-msg "消息内容"` - 设置自定义提醒消息
|
|
96
|
+
- `-nomsg` - 禁用提醒消息功能
|
|
97
|
+
- 不带参数的 `-msg` 会显示帮助信息
|
|
89
98
|
|
|
90
|
-
|
|
99
|
+
### 提醒消息变量
|
|
91
100
|
```
|
|
92
|
-
|
|
101
|
+
{user} - 用户名
|
|
102
|
+
{id} - 用户ID
|
|
103
|
+
{group} - 群号
|
|
104
|
+
{gname} - 群名称
|
|
105
|
+
{question} - 申请理由
|
|
106
|
+
{answer} - 答对数量/比例
|
|
107
|
+
{threshold} - 阈值要求
|
|
108
|
+
\n - 换行符
|
|
93
109
|
```
|
|
94
110
|
|
|
95
|
-
|
|
111
|
+
## 🔐 权限说明
|
|
96
112
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
113
|
+
### 配置和审核命令
|
|
114
|
+
需要以下任一权限:
|
|
115
|
+
- 群主权限
|
|
116
|
+
- 管理员权限
|
|
117
|
+
- Koishi 三级以上权限
|
|
101
118
|
|
|
102
|
-
|
|
119
|
+
### 统计命令
|
|
120
|
+
- 普通统计:任意用户可查看
|
|
121
|
+
- 总计统计:需要 Koishi 三级以上权限
|
|
103
122
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
123
|
+
## 📊 统计功能
|
|
124
|
+
|
|
125
|
+
插件会自动记录以下统计信息:
|
|
126
|
+
- **自动批准**:通过关键词验证自动入群的用户数
|
|
127
|
+
- **手动批准**:管理员手动同意的用户数
|
|
128
|
+
- **拒绝**:被拒绝的申请数
|
|
129
|
+
- **手动入群**:管理员直接邀请入群的用户数
|
|
130
|
+
|
|
131
|
+
## 🛠️ 开发配置
|
|
108
132
|
|
|
109
|
-
|
|
133
|
+
### 全局配置
|
|
134
|
+
在 Koishi 控制台插件配置页面可以设置:
|
|
135
|
+
- 默认提醒消息模板
|
|
136
|
+
- 日志级别
|
|
110
137
|
|
|
111
|
-
###
|
|
138
|
+
### 数据库结构
|
|
139
|
+
插件使用以下数据表:
|
|
140
|
+
- `group_verification_config` - 群组配置表
|
|
141
|
+
- `group_verification_stats` - 统计信息表
|
|
142
|
+
- `group_verification_pending` - 待审核申请表
|
|
112
143
|
|
|
113
|
-
|
|
144
|
+
## 📝 使用示例
|
|
114
145
|
|
|
146
|
+
### 场景1:学生群验证
|
|
115
147
|
```
|
|
116
|
-
|
|
148
|
+
# 设置学生群验证规则
|
|
149
|
+
gvc 学生,校友,老师 -m 1 -t 2 -msg "欢迎 {user} 加入学习群!"
|
|
117
150
|
```
|
|
118
151
|
|
|
119
|
-
|
|
152
|
+
### 场景2:企业内部群
|
|
153
|
+
```
|
|
154
|
+
# 设置严格的验证规则
|
|
155
|
+
gvc 员工,实习生,部门 -m 2 -t 100 -nomsg
|
|
156
|
+
```
|
|
120
157
|
|
|
121
|
-
|
|
158
|
+
### 场景3:兴趣爱好群
|
|
122
159
|
```
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
group-verify.stats all # 查看总体统计
|
|
160
|
+
# 设置宽松的验证规则
|
|
161
|
+
gvc 兴趣,爱好,交流 -m 0 -msg "欢迎 {user} 加入我们的大家庭!"
|
|
126
162
|
```
|
|
127
163
|
|
|
128
|
-
|
|
164
|
+
## 🐛 常见问题
|
|
129
165
|
|
|
130
|
-
|
|
166
|
+
### Q: 如何禁用提醒消息?
|
|
167
|
+
A: 使用 `gvc -nomsg` 命令禁用提醒功能
|
|
131
168
|
|
|
132
|
-
|
|
133
|
-
group
|
|
134
|
-
|
|
169
|
+
### Q: 提醒消息支持哪些变量?
|
|
170
|
+
A: 支持 {user}, {id}, {group}, {gname}, {question}, {answer}, {threshold} 等变量
|
|
171
|
+
|
|
172
|
+
### Q: 如何查看统计信息?
|
|
173
|
+
A: 使用 `gvs` 查看当前群统计,`gvs total` 查看总计统计
|
|
135
174
|
|
|
136
|
-
|
|
175
|
+
### Q: 权限不够怎么办?
|
|
176
|
+
A: 需要群主/管理员权限或 Koishi 三级以上权限
|
|
137
177
|
|
|
138
|
-
##
|
|
178
|
+
## 📄 许可证
|
|
139
179
|
|
|
140
|
-
|
|
141
|
-
2. 系统检查该群是否配置了验证规则
|
|
142
|
-
3. 如果未配置或验证通过 → 自动同意入群
|
|
143
|
-
4. 如果验证失败 → 将申请加入待审核列表,并在群内发送提醒
|
|
144
|
-
5. 管理员使用指令处理待审核申请
|
|
145
|
-
6. 系统自动更新相关统计信息
|
|
180
|
+
MIT License
|
|
146
181
|
|
|
147
|
-
##
|
|
182
|
+
## 🤝 贡献
|
|
148
183
|
|
|
149
|
-
|
|
150
|
-
- 关键词匹配不区分大小写
|
|
151
|
-
- 统计信息会自动累计,包括每个群和总体数据
|
|
184
|
+
欢迎提交 Issue 和 Pull Request!
|
package/src/index.ts
CHANGED
|
@@ -20,6 +20,7 @@ export interface GroupVerificationConfig {
|
|
|
20
20
|
reviewParameters: {
|
|
21
21
|
threshold?: number // 数量阈值或比例阈值
|
|
22
22
|
}
|
|
23
|
+
reminderEnabled: boolean // 是否启用提醒消息
|
|
23
24
|
reminderMessage: string
|
|
24
25
|
createdBy: string
|
|
25
26
|
updatedBy: string
|
|
@@ -77,6 +78,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
77
78
|
keywords: 'list',
|
|
78
79
|
reviewMethod: 'integer',
|
|
79
80
|
reviewParameters: 'json',
|
|
81
|
+
reminderEnabled: 'boolean',
|
|
80
82
|
reminderMessage: 'string',
|
|
81
83
|
createdBy: 'string',
|
|
82
84
|
updatedBy: 'string',
|
|
@@ -209,6 +211,12 @@ export function apply(ctx: Context, config: Config) {
|
|
|
209
211
|
applyTime: new Date()
|
|
210
212
|
})
|
|
211
213
|
|
|
214
|
+
// 如果提醒消息被禁用,直接返回
|
|
215
|
+
if (!config.reminderEnabled || !config.reminderMessage || config.reminderMessage === '') {
|
|
216
|
+
logger.info(`群 ${guildId} 的提醒消息已被禁用,跳过发送`)
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
|
|
212
220
|
// 替换提醒消息中的变量
|
|
213
221
|
let reminderMsg = config.reminderMessage
|
|
214
222
|
reminderMsg = reminderMsg
|
|
@@ -379,7 +387,8 @@ export function apply(ctx: Context, config: Config) {
|
|
|
379
387
|
.option('groupId', '-i <groupId> 指定群号')
|
|
380
388
|
.option('method', '-m <method> 审核方式 (0-3)')
|
|
381
389
|
.option('threshold', '-t <threshold> 阈值参数')
|
|
382
|
-
.option('message', '-msg
|
|
390
|
+
.option('message', '-msg [message] 自定义提醒消息')
|
|
391
|
+
.option('disableMessage', '-nomsg 禁用提醒消息')
|
|
383
392
|
.option('query', '-? 查询当前配置')
|
|
384
393
|
.option('remove', '-r 删除配置')
|
|
385
394
|
.action(async ({ session, options }, keywords) => {
|
|
@@ -441,12 +450,14 @@ export function apply(ctx: Context, config: Config) {
|
|
|
441
450
|
|
|
442
451
|
const createTime = new Date(config.createdAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
|
|
443
452
|
const updateTime = new Date(config.updatedAt).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
|
|
453
|
+
const reminderStatus = config.reminderEnabled ? '启用' : '禁用'
|
|
444
454
|
|
|
445
455
|
return `群 ${targetGroupId} 配置:
|
|
446
456
|
关键词: ${config.keywords.join(', ')}
|
|
447
457
|
审核方式: ${methodDesc}
|
|
448
458
|
阈值: ${thresholdInfo}
|
|
449
|
-
提醒消息: ${
|
|
459
|
+
提醒消息: ${reminderStatus}
|
|
460
|
+
自定义消息: ${config.reminderMessage || '无'}
|
|
450
461
|
创建时间: ${createTime}
|
|
451
462
|
更新时间: ${updateTime}
|
|
452
463
|
创建者: ${config.createdBy}
|
|
@@ -457,57 +468,117 @@ export function apply(ctx: Context, config: Config) {
|
|
|
457
468
|
}
|
|
458
469
|
|
|
459
470
|
// 处理配置创建/更新
|
|
460
|
-
|
|
471
|
+
let keywordList = keywords ? keywords.split(',').map(k => k.trim()).filter(k => k) : []
|
|
461
472
|
|
|
462
473
|
// 如果没有提供关键词且不是查询/删除操作,则报错
|
|
463
|
-
if (
|
|
464
|
-
|
|
474
|
+
if (!keywords && !options.query && !options.remove) {
|
|
475
|
+
// 检查是否提供了其他配置参数
|
|
476
|
+
const hasConfigParams = options.method !== undefined ||
|
|
477
|
+
options.threshold !== undefined ||
|
|
478
|
+
options.message !== undefined ||
|
|
479
|
+
options.disableMessage !== undefined
|
|
480
|
+
|
|
481
|
+
if (!hasConfigParams) {
|
|
482
|
+
return `用法:
|
|
483
|
+
gvc 关键词1,关键词2 -m 1 -t 2 # 创建配置
|
|
484
|
+
gvc -m 1 -t 2 # 修改审核参数
|
|
485
|
+
gvc -msg "消息内容" # 修改提醒消息
|
|
486
|
+
gvc -nomsg # 禁用提醒消息
|
|
487
|
+
gvc -? # 查询配置
|
|
488
|
+
gvc -r # 删除配置`
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// 如果只提供了参数,检查是否存在现有配置
|
|
492
|
+
const existingConfig = await ctx.database.get('group_verification_config', { groupId: targetGroupId })
|
|
493
|
+
if (existingConfig.length === 0) {
|
|
494
|
+
return '请先提供关键词创建配置,或使用 -? 查询配置,-r 删除配置'
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// 使用现有配置的关键词
|
|
498
|
+
keywordList = existingConfig[0].keywords
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// 处理提醒消息配置
|
|
502
|
+
let reminderEnabled = true
|
|
503
|
+
let reminderMessage = config.defaultReminderMessage ||
|
|
504
|
+
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
505
|
+
申请理由:{question}
|
|
506
|
+
答对情况:{answer}
|
|
507
|
+
阈值要求:{threshold}
|
|
508
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`
|
|
509
|
+
|
|
510
|
+
// 处理 -nomsg 选项
|
|
511
|
+
if (options.disableMessage) {
|
|
512
|
+
reminderEnabled = false
|
|
513
|
+
reminderMessage = ''
|
|
514
|
+
}
|
|
515
|
+
// 处理 -msg 选项
|
|
516
|
+
else if (options.message !== undefined) {
|
|
517
|
+
reminderEnabled = true
|
|
518
|
+
reminderMessage = options.message || config.defaultReminderMessage ||
|
|
519
|
+
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
520
|
+
申请理由:{question}
|
|
521
|
+
答对情况:{answer}
|
|
522
|
+
阈值要求:{threshold}
|
|
523
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
// 替换换行符
|
|
527
|
+
if (reminderEnabled && reminderMessage) {
|
|
528
|
+
reminderMessage = reminderMessage.replace(/\\n/g, '\n')
|
|
465
529
|
}
|
|
466
530
|
|
|
467
531
|
// 解析审核方式和阈值
|
|
468
532
|
let reviewMethod: 0 | 1 | 2 | 3 = 0 // 默认全部同意
|
|
469
533
|
let reviewParameters: { threshold?: number } = {}
|
|
470
534
|
|
|
535
|
+
// 如果是修改现有配置,先获取现有参数
|
|
536
|
+
if (!keywords && !options.query && !options.remove) {
|
|
537
|
+
const existingConfig = await ctx.database.get('group_verification_config', { groupId: targetGroupId })
|
|
538
|
+
if (existingConfig.length > 0) {
|
|
539
|
+
// 使用现有配置的参数作为默认值
|
|
540
|
+
reviewMethod = existingConfig[0].reviewMethod
|
|
541
|
+
if (existingConfig[0].reviewParameters?.threshold) {
|
|
542
|
+
reviewParameters.threshold = existingConfig[0].reviewParameters.threshold
|
|
543
|
+
}
|
|
544
|
+
// 如果没有明确设置提醒相关选项,使用现有配置
|
|
545
|
+
if (options.disableMessage === undefined && options.message === undefined) {
|
|
546
|
+
reminderEnabled = existingConfig[0].reminderEnabled
|
|
547
|
+
reminderMessage = existingConfig[0].reminderMessage
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
// 解析审核方式和阈值
|
|
553
|
+
|
|
471
554
|
if (options.method !== undefined) {
|
|
472
555
|
const methodNum = parseInt(options.method)
|
|
473
556
|
if (isNaN(methodNum) || methodNum < 0 || methodNum > 3) {
|
|
474
557
|
return '审核方式参数错误:0-全部同意, 1-按数量同意, 2-按比例同意, 3-全部拒绝'
|
|
475
558
|
}
|
|
476
559
|
reviewMethod = methodNum as 0 | 1 | 2 | 3
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
// 只有当审核方式需要阈值时才处理阈值参数
|
|
563
|
+
if ((reviewMethod === 1 || reviewMethod === 2) && options.threshold !== undefined) {
|
|
564
|
+
const thresholdNum = parseInt(options.threshold)
|
|
565
|
+
if (isNaN(thresholdNum)) {
|
|
566
|
+
return '阈值参数必须为数字'
|
|
567
|
+
}
|
|
477
568
|
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
if (isNaN(thresholdNum)) {
|
|
482
|
-
return '阈值参数必须为数字'
|
|
569
|
+
if (reviewMethod === 1) { // 按数量同意
|
|
570
|
+
if (thresholdNum <= 0 || thresholdNum > keywordList.length) {
|
|
571
|
+
return `数量阈值必须在1-${keywordList.length}之间`
|
|
483
572
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
reviewParameters.threshold = thresholdNum
|
|
490
|
-
} else if (reviewMethod === 2) { // 按比例同意
|
|
491
|
-
if (thresholdNum <= 0 || thresholdNum > 100) {
|
|
492
|
-
return '比例阈值必须在1-100之间'
|
|
493
|
-
}
|
|
494
|
-
reviewParameters.threshold = thresholdNum
|
|
573
|
+
reviewParameters.threshold = thresholdNum
|
|
574
|
+
} else if (reviewMethod === 2) { // 按比例同意
|
|
575
|
+
if (thresholdNum <= 0 || thresholdNum > 100) {
|
|
576
|
+
return '比例阈值必须在1-100之间'
|
|
495
577
|
}
|
|
578
|
+
reviewParameters.threshold = thresholdNum
|
|
496
579
|
}
|
|
497
580
|
}
|
|
498
581
|
|
|
499
|
-
// 处理提醒消息
|
|
500
|
-
let reminderMessage = options.message ||
|
|
501
|
-
config.defaultReminderMessage ||
|
|
502
|
-
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
503
|
-
申请理由:{question}
|
|
504
|
-
答对情况:{answer}
|
|
505
|
-
阈值要求:{threshold}
|
|
506
|
-
请管理员使用 #同意 或 #拒绝 来处理此申请`
|
|
507
|
-
|
|
508
|
-
// 替换换行符
|
|
509
|
-
reminderMessage = reminderMessage.replace(/\\n/g, '\n')
|
|
510
|
-
|
|
511
582
|
// Check if configuration already exists
|
|
512
583
|
const existingConfig = await ctx.database.get('group_verification_config', { groupId: targetGroupId })
|
|
513
584
|
|
|
@@ -515,6 +586,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
515
586
|
keywords: keywordList,
|
|
516
587
|
reviewMethod: reviewMethod,
|
|
517
588
|
reviewParameters: reviewParameters,
|
|
589
|
+
reminderEnabled: reminderEnabled,
|
|
518
590
|
reminderMessage: reminderMessage,
|
|
519
591
|
updatedBy: session.username || session.userId,
|
|
520
592
|
updatedAt: new Date()
|
|
@@ -794,27 +866,29 @@ export function apply(ctx: Context, config: Config) {
|
|
|
794
866
|
// Subcommand: help information
|
|
795
867
|
groupVerify
|
|
796
868
|
.subcommand('.help', '显示帮助信息')
|
|
797
|
-
.alias(
|
|
798
|
-
'gv.帮助', 'gverify.帮助', 'group-verify.帮助'
|
|
799
|
-
)
|
|
869
|
+
.alias('gv.帮助', 'gverify.帮助', 'group-verify.帮助', '帮助', 'hlp', '帮助信息')
|
|
800
870
|
.action(() => {
|
|
801
871
|
return `群组验证命令帮助:
|
|
802
872
|
主指令别名:gv, gverify
|
|
803
873
|
|
|
804
|
-
配置命令 (.config):
|
|
805
|
-
|
|
874
|
+
配置命令 (.config/.cfg):
|
|
875
|
+
用法:
|
|
876
|
+
1. 创建新配置:gv.cfg 关键词1,关键词2 -m 1 -t 2
|
|
877
|
+
2. 修改现有配置:gv.cfg -m 1 -t 2 (不提供关键词)
|
|
878
|
+
3. 启用提醒消息:gv.cfg -msg "消息内容"
|
|
879
|
+
4. 禁用提醒消息:gv.cfg -nomsg
|
|
880
|
+
5. 查询配置:gv.cfg -?
|
|
881
|
+
6. 删除配置:gv.cfg -r
|
|
882
|
+
|
|
883
|
+
参数说明:
|
|
806
884
|
-i <群号> 指定群号(私聊时必需)
|
|
807
885
|
-m <方式> 审核方式 (0=全部同意, 1=按数量, 2=按比例, 3=全部拒绝)
|
|
808
886
|
-t <阈值> 阈值参数(方式1或2时必需)
|
|
809
|
-
-msg
|
|
887
|
+
-msg [消息] 自定义提醒消息(不带参数显示帮助)
|
|
888
|
+
-nomsg 禁用提醒消息
|
|
810
889
|
-? 查询当前配置
|
|
811
890
|
-r 删除配置
|
|
812
891
|
|
|
813
|
-
示例:
|
|
814
|
-
gv.config 关键词1,关键词2 -m 1 -t 2
|
|
815
|
-
gv.config -i 123456789 -?
|
|
816
|
-
gv.config -r -i 123456789
|
|
817
|
-
|
|
818
892
|
提醒消息变量:
|
|
819
893
|
{user} - 用户名
|
|
820
894
|
{id} - 用户ID
|
|
@@ -823,18 +897,23 @@ export function apply(ctx: Context, config: Config) {
|
|
|
823
897
|
{question} - 申请理由
|
|
824
898
|
{answer} - 答对数量/比例
|
|
825
899
|
{threshold} - 阈值要求
|
|
900
|
+
|
|
901
|
+
消息格式化:
|
|
826
902
|
\\n - 换行符
|
|
903
|
+
可以组合使用变量和换行符创建格式化的消息
|
|
904
|
+
示例:gv.cfg -msg "用户 {user}\\n申请理由:{question}\\n匹配:{answer}/{threshold}"
|
|
905
|
+
|
|
906
|
+
快捷命令:
|
|
907
|
+
gvc - 配置命令快捷方式
|
|
908
|
+
gva - 同意申请快捷命令
|
|
909
|
+
gvr - 拒绝申请快捷命令
|
|
910
|
+
gvp - 查看待审核列表快捷命令
|
|
911
|
+
gvs - 查看统计信息快捷命令
|
|
827
912
|
|
|
828
913
|
权限说明:
|
|
829
914
|
- 群主/管理员权限
|
|
830
915
|
- koishi三级以上权限
|
|
831
|
-
- 私聊时必须指定群号(-i参数)
|
|
832
|
-
|
|
833
|
-
其他命令:
|
|
834
|
-
.approve <用户ID> - 同意加群申请
|
|
835
|
-
.reject <用户ID> - 拒绝加群申请
|
|
836
|
-
.pending - 查看待审核列表
|
|
837
|
-
.stats [群号] - 查看统计信息`
|
|
916
|
+
- 私聊时必须指定群号(-i参数)`
|
|
838
917
|
})
|
|
839
918
|
|
|
840
919
|
// 插件初始化时确保总计统计行存在
|