koishi-plugin-group-verification 1.0.8 → 1.0.10
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 +3 -0
- package/lib/index.js +118 -43
- package/package.json +1 -1
- package/src/index.ts +163 -41
package/lib/index.d.ts
CHANGED
|
@@ -38,6 +38,9 @@ export interface PendingVerification {
|
|
|
38
38
|
applyTime: Date;
|
|
39
39
|
}
|
|
40
40
|
export interface Config {
|
|
41
|
+
defaultReminderMessage?: string;
|
|
42
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error';
|
|
41
43
|
}
|
|
42
44
|
export declare const Config: Schema<Config>;
|
|
45
|
+
export declare const inject: string[];
|
|
43
46
|
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -22,12 +22,23 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
Config: () => Config,
|
|
24
24
|
apply: () => apply,
|
|
25
|
+
inject: () => inject,
|
|
25
26
|
name: () => name
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(src_exports);
|
|
28
29
|
var import_koishi = require("koishi");
|
|
29
30
|
var name = "group-verification";
|
|
30
|
-
var Config = import_koishi.Schema.object({
|
|
31
|
+
var Config = import_koishi.Schema.object({
|
|
32
|
+
defaultReminderMessage: import_koishi.Schema.string().default(
|
|
33
|
+
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
34
|
+
申请理由:{question}
|
|
35
|
+
答对情况:{answer}
|
|
36
|
+
阈值要求:{threshold}
|
|
37
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`
|
|
38
|
+
).description("默认提醒消息模板"),
|
|
39
|
+
logLevel: import_koishi.Schema.union(["debug", "info", "warn", "error"]).default("info").description("日志级别")
|
|
40
|
+
}).description("群组验证插件配置");
|
|
41
|
+
var inject = ["database"];
|
|
31
42
|
function apply(ctx, config) {
|
|
32
43
|
ctx.model.extend("group_verification_config", {
|
|
33
44
|
id: "unsigned",
|
|
@@ -45,6 +56,9 @@ function apply(ctx, config) {
|
|
|
45
56
|
autoInc: true
|
|
46
57
|
});
|
|
47
58
|
const logger = ctx.logger("group-verification");
|
|
59
|
+
logger.info("群组验证插件已启动");
|
|
60
|
+
logger.info(`默认提醒消息: ${config.defaultReminderMessage}`);
|
|
61
|
+
logger.info(`日志级别: ${config.logLevel}`);
|
|
48
62
|
ctx.model.extend("group_verification_stats", {
|
|
49
63
|
id: "unsigned",
|
|
50
64
|
groupId: "string",
|
|
@@ -85,6 +99,22 @@ function apply(ctx, config) {
|
|
|
85
99
|
await handleFailedVerification(ctx, session, config2);
|
|
86
100
|
}
|
|
87
101
|
});
|
|
102
|
+
ctx.on("guild-member-added", async (session) => {
|
|
103
|
+
const groupId = session.guildId;
|
|
104
|
+
const userId = session.userId;
|
|
105
|
+
const pendingRecords = await ctx.database.get("group_verification_pending", {
|
|
106
|
+
groupId,
|
|
107
|
+
userId
|
|
108
|
+
});
|
|
109
|
+
if (pendingRecords.length > 0) {
|
|
110
|
+
await updateStats(groupId, "autoApproved");
|
|
111
|
+
await ctx.database.remove("group_verification_pending", { id: pendingRecords[0].id });
|
|
112
|
+
logger.info(`用户 ${userId} 通过验证加入群 ${groupId},统计已更新`);
|
|
113
|
+
} else {
|
|
114
|
+
await updateStats(groupId, "manuallyApproved");
|
|
115
|
+
logger.info(`用户 ${userId} 被手动邀请加入群 ${groupId},手动批准统计已更新`);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
88
118
|
async function handleFailedVerification(ctx2, session, config2) {
|
|
89
119
|
const guildId = session.guildId;
|
|
90
120
|
const userId = session.userId;
|
|
@@ -141,39 +171,24 @@ function apply(ctx, config) {
|
|
|
141
171
|
return { isValid, matchedCount, requiredThreshold };
|
|
142
172
|
}
|
|
143
173
|
__name(verifyApplication, "verifyApplication");
|
|
144
|
-
async function updateStats(groupId,
|
|
145
|
-
const
|
|
146
|
-
if (
|
|
147
|
-
const stats =
|
|
174
|
+
async function updateStats(groupId, action) {
|
|
175
|
+
const existingStats = await ctx.database.get("group_verification_stats", { groupId });
|
|
176
|
+
if (existingStats.length > 0) {
|
|
177
|
+
const stats = existingStats[0];
|
|
148
178
|
await ctx.database.set("group_verification_stats", { id: stats.id }, {
|
|
149
|
-
[
|
|
179
|
+
[action]: stats[action] + 1,
|
|
150
180
|
lastUpdated: /* @__PURE__ */ new Date()
|
|
151
181
|
});
|
|
152
182
|
} else {
|
|
153
183
|
await ctx.database.create("group_verification_stats", {
|
|
154
184
|
groupId,
|
|
155
|
-
autoApproved:
|
|
156
|
-
manuallyApproved:
|
|
157
|
-
rejected:
|
|
158
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
const totalStats = await ctx.database.get("group_verification_stats", { groupId: "all" });
|
|
162
|
-
if (totalStats.length > 0) {
|
|
163
|
-
const stats = totalStats[0];
|
|
164
|
-
await ctx.database.set("group_verification_stats", { id: stats.id }, {
|
|
165
|
-
[statType]: stats[statType] + 1,
|
|
166
|
-
lastUpdated: /* @__PURE__ */ new Date()
|
|
167
|
-
});
|
|
168
|
-
} else {
|
|
169
|
-
await ctx.database.create("group_verification_stats", {
|
|
170
|
-
groupId: "all",
|
|
171
|
-
autoApproved: statType === "autoApproved" ? 1 : 0,
|
|
172
|
-
manuallyApproved: statType === "manuallyApproved" ? 1 : 0,
|
|
173
|
-
rejected: statType === "rejected" ? 1 : 0,
|
|
185
|
+
autoApproved: action === "autoApproved" ? 1 : 0,
|
|
186
|
+
manuallyApproved: action === "manuallyApproved" ? 1 : 0,
|
|
187
|
+
rejected: action === "rejected" ? 1 : 0,
|
|
174
188
|
lastUpdated: /* @__PURE__ */ new Date()
|
|
175
189
|
});
|
|
176
190
|
}
|
|
191
|
+
await syncTotalStats(ctx);
|
|
177
192
|
}
|
|
178
193
|
__name(updateStats, "updateStats");
|
|
179
194
|
async function checkPermission(session, targetGroupId) {
|
|
@@ -328,7 +343,7 @@ ${debugInfo}`];
|
|
|
328
343
|
}
|
|
329
344
|
}
|
|
330
345
|
}
|
|
331
|
-
let reminderMessage = options.message || `用户 {user}({id}) 申请加入群 {gname}({group})
|
|
346
|
+
let reminderMessage = options.message || config.defaultReminderMessage || `用户 {user}({id}) 申请加入群 {gname}({group})
|
|
332
347
|
申请理由:{question}
|
|
333
348
|
答对情况:{answer}
|
|
334
349
|
阈值要求:{threshold}
|
|
@@ -402,24 +417,45 @@ ${debugInfo}`];
|
|
|
402
417
|
await updateStats(session.guildId, "rejected");
|
|
403
418
|
return `已拒绝用户 ${application.userName}(${userId}) 的加群申请`;
|
|
404
419
|
});
|
|
405
|
-
groupVerify.subcommand(".stats [groupId]", "
|
|
406
|
-
const targetGroupId = groupId || session.guildId
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
420
|
+
groupVerify.subcommand(".stats [groupId]", "查看群组验证统计信息").alias("统计", "stat", "statistics").option("total", "-t 显示总计统计").action(async ({ session, options }, groupId) => {
|
|
421
|
+
const targetGroupId = groupId || session.guildId;
|
|
422
|
+
if (!targetGroupId && !options.total) {
|
|
423
|
+
return "请在群聊中使用此命令或指定群号,或使用 -t 参数查看总计统计";
|
|
424
|
+
}
|
|
425
|
+
let statsList = [];
|
|
426
|
+
if (options.total) {
|
|
427
|
+
const totalStats = await ctx.database.get("group_verification_stats", { groupId: "TOTAL" });
|
|
428
|
+
if (totalStats.length > 0) {
|
|
429
|
+
statsList.push(totalStats[0]);
|
|
430
|
+
}
|
|
431
|
+
if (targetGroupId && targetGroupId !== "TOTAL") {
|
|
432
|
+
const groupStats = await ctx.database.get("group_verification_stats", { groupId: targetGroupId });
|
|
433
|
+
statsList = statsList.concat(groupStats);
|
|
434
|
+
}
|
|
417
435
|
} else {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
436
|
+
const groupStats = await ctx.database.get("group_verification_stats", { groupId: targetGroupId });
|
|
437
|
+
statsList = groupStats;
|
|
438
|
+
}
|
|
439
|
+
if (statsList.length === 0) {
|
|
440
|
+
if (options.total) {
|
|
441
|
+
return "暂无统计信息";
|
|
442
|
+
} else {
|
|
443
|
+
return `群 ${targetGroupId} 暂无验证统计信息`;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
let result = "";
|
|
447
|
+
for (const stats of statsList) {
|
|
448
|
+
const groupName = stats.groupId === "TOTAL" ? "总计" : `群 ${stats.groupId}`;
|
|
449
|
+
const lastUpdated = new Date(stats.lastUpdated).toLocaleString("zh-CN", { timeZone: "Asia/Shanghai" });
|
|
450
|
+
result += `${groupName} 验证统计:
|
|
451
|
+
自动批准: ${stats.autoApproved}
|
|
452
|
+
手动批准: ${stats.manuallyApproved}
|
|
453
|
+
拒绝: ${stats.rejected}
|
|
454
|
+
最后更新: ${lastUpdated}
|
|
455
|
+
|
|
456
|
+
`;
|
|
422
457
|
}
|
|
458
|
+
return result.trim();
|
|
423
459
|
});
|
|
424
460
|
groupVerify.subcommand(".pending", "查看待审核加群申请").alias("list", "待审", "pend", "待处理").action(async ({ session }) => {
|
|
425
461
|
if (!session.guildId) {
|
|
@@ -476,15 +512,54 @@ ${debugInfo}`];
|
|
|
476
512
|
|
|
477
513
|
其他命令:
|
|
478
514
|
.approve <用户ID> - 同意加群申请
|
|
479
|
-
.reject <用户ID> - 拒绝加群申请
|
|
515
|
+
.reject <用户ID> - 拒绝加群申请
|
|
480
516
|
.pending - 查看待审核列表
|
|
481
517
|
.stats [群号] - 查看统计信息`;
|
|
482
518
|
});
|
|
519
|
+
ctx.on("ready", async () => {
|
|
520
|
+
const totalStats = await ctx.database.get("group_verification_stats", { groupId: "TOTAL" });
|
|
521
|
+
if (totalStats.length === 0) {
|
|
522
|
+
await ctx.database.create("group_verification_stats", {
|
|
523
|
+
groupId: "TOTAL",
|
|
524
|
+
autoApproved: 0,
|
|
525
|
+
manuallyApproved: 0,
|
|
526
|
+
rejected: 0,
|
|
527
|
+
lastUpdated: /* @__PURE__ */ new Date()
|
|
528
|
+
});
|
|
529
|
+
logger.info("已创建总计统计行");
|
|
530
|
+
} else {
|
|
531
|
+
logger.info("总计统计行已存在");
|
|
532
|
+
}
|
|
533
|
+
await syncTotalStats(ctx);
|
|
534
|
+
});
|
|
535
|
+
async function syncTotalStats(ctx2) {
|
|
536
|
+
try {
|
|
537
|
+
const allStats = await ctx2.database.get("group_verification_stats", {
|
|
538
|
+
groupId: { $ne: "TOTAL" }
|
|
539
|
+
});
|
|
540
|
+
if (allStats.length > 0) {
|
|
541
|
+
const totalAutoApproved = allStats.reduce((sum, stat) => sum + (stat.autoApproved || 0), 0);
|
|
542
|
+
const totalManuallyApproved = allStats.reduce((sum, stat) => sum + (stat.manuallyApproved || 0), 0);
|
|
543
|
+
const totalRejected = allStats.reduce((sum, stat) => sum + (stat.rejected || 0), 0);
|
|
544
|
+
await ctx2.database.set("group_verification_stats", { groupId: "TOTAL" }, {
|
|
545
|
+
autoApproved: totalAutoApproved,
|
|
546
|
+
manuallyApproved: totalManuallyApproved,
|
|
547
|
+
rejected: totalRejected,
|
|
548
|
+
lastUpdated: /* @__PURE__ */ new Date()
|
|
549
|
+
});
|
|
550
|
+
logger.info(`总计统计已同步: 自动批准${totalAutoApproved}, 手动批准${totalManuallyApproved}, 拒绝${totalRejected}`);
|
|
551
|
+
}
|
|
552
|
+
} catch (error) {
|
|
553
|
+
logger.error("同步总计统计时出错:", error);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
__name(syncTotalStats, "syncTotalStats");
|
|
483
557
|
}
|
|
484
558
|
__name(apply, "apply");
|
|
485
559
|
// Annotate the CommonJS export names for ESM import in node:
|
|
486
560
|
0 && (module.exports = {
|
|
487
561
|
Config,
|
|
488
562
|
apply,
|
|
563
|
+
inject,
|
|
489
564
|
name
|
|
490
565
|
});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -47,9 +47,27 @@ export interface PendingVerification {
|
|
|
47
47
|
applyTime: Date
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
export interface Config {
|
|
50
|
+
export interface Config {
|
|
51
|
+
// 全局默认配置
|
|
52
|
+
defaultReminderMessage?: string
|
|
53
|
+
logLevel?: 'debug' | 'info' | 'warn' | 'error'
|
|
54
|
+
// 其他配置项...
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const Config: Schema<Config> = Schema.object({
|
|
58
|
+
defaultReminderMessage: Schema.string().default(
|
|
59
|
+
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
60
|
+
申请理由:{question}
|
|
61
|
+
答对情况:{answer}
|
|
62
|
+
阈值要求:{threshold}
|
|
63
|
+
请管理员使用 #同意 或 #拒绝 来处理此申请`
|
|
64
|
+
).description('默认提醒消息模板'),
|
|
65
|
+
|
|
66
|
+
logLevel: Schema.union(['debug', 'info', 'warn', 'error']).default('info')
|
|
67
|
+
.description('日志级别')
|
|
68
|
+
}).description('群组验证插件配置')
|
|
51
69
|
|
|
52
|
-
export const
|
|
70
|
+
export const inject = ['database']
|
|
53
71
|
|
|
54
72
|
export function apply(ctx: Context, config: Config) {
|
|
55
73
|
// 创建数据库表
|
|
@@ -71,6 +89,14 @@ export function apply(ctx: Context, config: Config) {
|
|
|
71
89
|
|
|
72
90
|
// 获取logger实例
|
|
73
91
|
const logger = ctx.logger('group-verification')
|
|
92
|
+
|
|
93
|
+
// 设置日志级别
|
|
94
|
+
// 注意:Koishi logger的level设置可能需要不同的方式
|
|
95
|
+
|
|
96
|
+
// 记录插件启动信息
|
|
97
|
+
logger.info('群组验证插件已启动')
|
|
98
|
+
logger.info(`默认提醒消息: ${config.defaultReminderMessage}`)
|
|
99
|
+
logger.info(`日志级别: ${config.logLevel}`)
|
|
74
100
|
|
|
75
101
|
ctx.model.extend('group_verification_stats', {
|
|
76
102
|
id: 'unsigned',
|
|
@@ -131,6 +157,30 @@ export function apply(ctx: Context, config: Config) {
|
|
|
131
157
|
}
|
|
132
158
|
})
|
|
133
159
|
|
|
160
|
+
// 监听群成员增加事件(包括手动邀请入群)
|
|
161
|
+
ctx.on('guild-member-added', async (session) => {
|
|
162
|
+
const groupId = session.guildId
|
|
163
|
+
const userId = session.userId
|
|
164
|
+
|
|
165
|
+
// 检查是否有待审核记录
|
|
166
|
+
const pendingRecords = await ctx.database.get('group_verification_pending', {
|
|
167
|
+
groupId: groupId,
|
|
168
|
+
userId: userId
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
if (pendingRecords.length > 0) {
|
|
172
|
+
// 通过验证的用户入群,更新统计
|
|
173
|
+
await updateStats(groupId, 'autoApproved')
|
|
174
|
+
// 清除待审核记录
|
|
175
|
+
await ctx.database.remove('group_verification_pending', { id: pendingRecords[0].id })
|
|
176
|
+
logger.info(`用户 ${userId} 通过验证加入群 ${groupId},统计已更新`)
|
|
177
|
+
} else {
|
|
178
|
+
// 手动邀请入群,记录到手动批准统计
|
|
179
|
+
await updateStats(groupId, 'manuallyApproved')
|
|
180
|
+
logger.info(`用户 ${userId} 被手动邀请加入群 ${groupId},手动批准统计已更新`)
|
|
181
|
+
}
|
|
182
|
+
})
|
|
183
|
+
|
|
134
184
|
// 处理验证失败的情况
|
|
135
185
|
async function handleFailedVerification(ctx: Context, session: any, config: GroupVerificationConfig) {
|
|
136
186
|
const guildId = session.guildId
|
|
@@ -212,44 +262,28 @@ export function apply(ctx: Context, config: Config) {
|
|
|
212
262
|
}
|
|
213
263
|
|
|
214
264
|
// 更新统计信息
|
|
215
|
-
async function updateStats(groupId: string,
|
|
265
|
+
async function updateStats(groupId: string, action: 'autoApproved' | 'manuallyApproved' | 'rejected') {
|
|
216
266
|
// 更新群组统计
|
|
217
|
-
const
|
|
267
|
+
const existingStats = await ctx.database.get('group_verification_stats', { groupId })
|
|
218
268
|
|
|
219
|
-
if (
|
|
220
|
-
const stats =
|
|
269
|
+
if (existingStats.length > 0) {
|
|
270
|
+
const stats = existingStats[0]
|
|
221
271
|
await ctx.database.set('group_verification_stats', { id: stats.id }, {
|
|
222
|
-
[
|
|
272
|
+
[action]: stats[action] + 1,
|
|
223
273
|
lastUpdated: new Date()
|
|
224
274
|
})
|
|
225
275
|
} else {
|
|
226
|
-
// 创建新的统计记录
|
|
227
276
|
await ctx.database.create('group_verification_stats', {
|
|
228
277
|
groupId,
|
|
229
|
-
autoApproved:
|
|
230
|
-
manuallyApproved:
|
|
231
|
-
rejected:
|
|
278
|
+
autoApproved: action === 'autoApproved' ? 1 : 0,
|
|
279
|
+
manuallyApproved: action === 'manuallyApproved' ? 1 : 0,
|
|
280
|
+
rejected: action === 'rejected' ? 1 : 0,
|
|
232
281
|
lastUpdated: new Date()
|
|
233
282
|
})
|
|
234
283
|
}
|
|
235
284
|
|
|
236
|
-
//
|
|
237
|
-
|
|
238
|
-
if (totalStats.length > 0) {
|
|
239
|
-
const stats = totalStats[0]
|
|
240
|
-
await ctx.database.set('group_verification_stats', { id: stats.id }, {
|
|
241
|
-
[statType]: stats[statType] + 1,
|
|
242
|
-
lastUpdated: new Date()
|
|
243
|
-
})
|
|
244
|
-
} else {
|
|
245
|
-
await ctx.database.create('group_verification_stats', {
|
|
246
|
-
groupId: 'all',
|
|
247
|
-
autoApproved: statType === 'autoApproved' ? 1 : 0,
|
|
248
|
-
manuallyApproved: statType === 'manuallyApproved' ? 1 : 0,
|
|
249
|
-
rejected: statType === 'rejected' ? 1 : 0,
|
|
250
|
-
lastUpdated: new Date()
|
|
251
|
-
})
|
|
252
|
-
}
|
|
285
|
+
// 同步更新总计统计
|
|
286
|
+
await syncTotalStats(ctx)
|
|
253
287
|
}
|
|
254
288
|
|
|
255
289
|
// 权限检查函数
|
|
@@ -460,6 +494,7 @@ export function apply(ctx: Context, config: Config) {
|
|
|
460
494
|
|
|
461
495
|
// 处理提醒消息
|
|
462
496
|
let reminderMessage = options.message ||
|
|
497
|
+
config.defaultReminderMessage ||
|
|
463
498
|
`用户 {user}({id}) 申请加入群 {gname}({group})
|
|
464
499
|
申请理由:{question}
|
|
465
500
|
答对情况:{answer}
|
|
@@ -575,23 +610,58 @@ export function apply(ctx: Context, config: Config) {
|
|
|
575
610
|
|
|
576
611
|
// Subcommand: view statistics
|
|
577
612
|
groupVerify
|
|
578
|
-
.subcommand('.stats [groupId]', '
|
|
579
|
-
.alias('
|
|
580
|
-
.
|
|
581
|
-
|
|
613
|
+
.subcommand('.stats [groupId]', '查看群组验证统计信息')
|
|
614
|
+
.alias('统计', 'stat', 'statistics')
|
|
615
|
+
.option('total', '-t 显示总计统计')
|
|
616
|
+
.action(async ({ session, options }, groupId) => {
|
|
617
|
+
// 权限检查(统计命令相对宽松,任意用户可查看)
|
|
618
|
+
const targetGroupId = groupId || session.guildId
|
|
619
|
+
|
|
620
|
+
if (!targetGroupId && !options.total) {
|
|
621
|
+
return '请在群聊中使用此命令或指定群号,或使用 -t 参数查看总计统计'
|
|
622
|
+
}
|
|
582
623
|
|
|
583
|
-
|
|
624
|
+
let statsList: GroupVerificationStats[] = []
|
|
584
625
|
|
|
585
|
-
if (
|
|
586
|
-
|
|
626
|
+
if (options.total) {
|
|
627
|
+
// 显示总计统计
|
|
628
|
+
const totalStats = await ctx.database.get('group_verification_stats', { groupId: 'TOTAL' })
|
|
629
|
+
if (totalStats.length > 0) {
|
|
630
|
+
statsList.push(totalStats[0])
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// 如果同时指定了具体群号,也显示该群统计
|
|
634
|
+
if (targetGroupId && targetGroupId !== 'TOTAL') {
|
|
635
|
+
const groupStats = await ctx.database.get('group_verification_stats', { groupId: targetGroupId })
|
|
636
|
+
statsList = statsList.concat(groupStats)
|
|
637
|
+
}
|
|
638
|
+
} else {
|
|
639
|
+
// 显示指定群统计
|
|
640
|
+
const groupStats = await ctx.database.get('group_verification_stats', { groupId: targetGroupId })
|
|
641
|
+
statsList = groupStats
|
|
587
642
|
}
|
|
588
643
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
644
|
+
if (statsList.length === 0) {
|
|
645
|
+
if (options.total) {
|
|
646
|
+
return '暂无统计信息'
|
|
647
|
+
} else {
|
|
648
|
+
return `群 ${targetGroupId} 暂无验证统计信息`
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
let result = ''
|
|
653
|
+
for (const stats of statsList) {
|
|
654
|
+
const groupName = stats.groupId === 'TOTAL' ? '总计' : `群 ${stats.groupId}`
|
|
655
|
+
const lastUpdated = new Date(stats.lastUpdated).toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })
|
|
656
|
+
|
|
657
|
+
result += `${groupName} 验证统计:
|
|
658
|
+
自动批准: ${stats.autoApproved}
|
|
659
|
+
手动批准: ${stats.manuallyApproved}
|
|
660
|
+
拒绝: ${stats.rejected}
|
|
661
|
+
最后更新: ${lastUpdated}\n\n`
|
|
594
662
|
}
|
|
663
|
+
|
|
664
|
+
return result.trim()
|
|
595
665
|
})
|
|
596
666
|
|
|
597
667
|
// Subcommand: view pending requests
|
|
@@ -662,8 +732,60 @@ export function apply(ctx: Context, config: Config) {
|
|
|
662
732
|
|
|
663
733
|
其他命令:
|
|
664
734
|
.approve <用户ID> - 同意加群申请
|
|
665
|
-
.reject <用户ID> - 拒绝加群申请
|
|
735
|
+
.reject <用户ID> - 拒绝加群申请
|
|
666
736
|
.pending - 查看待审核列表
|
|
667
737
|
.stats [群号] - 查看统计信息`
|
|
668
738
|
})
|
|
739
|
+
|
|
740
|
+
// 插件初始化时确保总计统计行存在
|
|
741
|
+
ctx.on('ready', async () => {
|
|
742
|
+
// 检查是否已存在总计行(groupId为'TOTAL')
|
|
743
|
+
const totalStats = await ctx.database.get('group_verification_stats', { groupId: 'TOTAL' })
|
|
744
|
+
|
|
745
|
+
if (totalStats.length === 0) {
|
|
746
|
+
// 创建总计统计行
|
|
747
|
+
await ctx.database.create('group_verification_stats', {
|
|
748
|
+
groupId: 'TOTAL',
|
|
749
|
+
autoApproved: 0,
|
|
750
|
+
manuallyApproved: 0,
|
|
751
|
+
rejected: 0,
|
|
752
|
+
lastUpdated: new Date()
|
|
753
|
+
})
|
|
754
|
+
logger.info('已创建总计统计行')
|
|
755
|
+
} else {
|
|
756
|
+
logger.info('总计统计行已存在')
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
// 同步现有统计数据到总计行
|
|
760
|
+
await syncTotalStats(ctx)
|
|
761
|
+
})
|
|
762
|
+
|
|
763
|
+
// 同步统计数据到总计行的函数
|
|
764
|
+
async function syncTotalStats(ctx: Context) {
|
|
765
|
+
try {
|
|
766
|
+
// 获取所有群组统计(排除TOTAL行)
|
|
767
|
+
const allStats = await ctx.database.get('group_verification_stats', {
|
|
768
|
+
groupId: { $ne: 'TOTAL' }
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
if (allStats.length > 0) {
|
|
772
|
+
// 计算总计
|
|
773
|
+
const totalAutoApproved = allStats.reduce((sum, stat) => sum + (stat.autoApproved || 0), 0)
|
|
774
|
+
const totalManuallyApproved = allStats.reduce((sum, stat) => sum + (stat.manuallyApproved || 0), 0)
|
|
775
|
+
const totalRejected = allStats.reduce((sum, stat) => sum + (stat.rejected || 0), 0)
|
|
776
|
+
|
|
777
|
+
// 更新总计行
|
|
778
|
+
await ctx.database.set('group_verification_stats', { groupId: 'TOTAL' }, {
|
|
779
|
+
autoApproved: totalAutoApproved,
|
|
780
|
+
manuallyApproved: totalManuallyApproved,
|
|
781
|
+
rejected: totalRejected,
|
|
782
|
+
lastUpdated: new Date()
|
|
783
|
+
})
|
|
784
|
+
|
|
785
|
+
logger.info(`总计统计已同步: 自动批准${totalAutoApproved}, 手动批准${totalManuallyApproved}, 拒绝${totalRejected}`)
|
|
786
|
+
}
|
|
787
|
+
} catch (error) {
|
|
788
|
+
logger.error('同步总计统计时出错:', error)
|
|
789
|
+
}
|
|
790
|
+
}
|
|
669
791
|
}
|