koishi-plugin-group-control 0.2.10 → 0.2.12
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/config.d.ts +1 -0
- package/lib/database.d.ts +24 -0
- package/lib/index.js +154 -42
- package/lib/utils.d.ts +5 -0
- package/package.json +1 -1
package/lib/config.d.ts
CHANGED
package/lib/database.d.ts
CHANGED
|
@@ -19,11 +19,26 @@ export interface GroupBotStatus {
|
|
|
19
19
|
guildId: string;
|
|
20
20
|
botEnabled: boolean;
|
|
21
21
|
}
|
|
22
|
+
export interface SmallGroupWhitelist {
|
|
23
|
+
platform: string;
|
|
24
|
+
guildId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface PendingInvite {
|
|
27
|
+
platform: string;
|
|
28
|
+
groupId: string;
|
|
29
|
+
userId: string;
|
|
30
|
+
userName: string;
|
|
31
|
+
groupName: string;
|
|
32
|
+
time: number;
|
|
33
|
+
flag: string;
|
|
34
|
+
}
|
|
22
35
|
declare module 'koishi' {
|
|
23
36
|
interface Tables {
|
|
24
37
|
blacklisted_guild: BlacklistedGuild;
|
|
25
38
|
command_frequency_record: CommandFrequencyRecord;
|
|
26
39
|
group_bot_status: GroupBotStatus;
|
|
40
|
+
small_group_whitelist: SmallGroupWhitelist;
|
|
41
|
+
pending_invite: PendingInvite;
|
|
27
42
|
}
|
|
28
43
|
}
|
|
29
44
|
export declare const name = "group-control-database";
|
|
@@ -38,3 +53,12 @@ export declare function getCommandFrequencyRecord(ctx: Context, platform: string
|
|
|
38
53
|
export declare function updateCommandFrequencyRecord(ctx: Context, platform: string, guildId: string, data: Partial<CommandFrequencyRecord>): Promise<void>;
|
|
39
54
|
export declare function getGroupBotStatus(ctx: Context, platform: string, guildId: string): Promise<GroupBotStatus | null>;
|
|
40
55
|
export declare function setGroupBotStatus(ctx: Context, platform: string, guildId: string, botEnabled: boolean): Promise<void>;
|
|
56
|
+
export declare function isInSmallGroupWhitelist(ctx: Context, guildId: string): Promise<boolean>;
|
|
57
|
+
export declare function addToSmallGroupWhitelist(ctx: Context, guildId: string): Promise<void>;
|
|
58
|
+
export declare function removeFromSmallGroupWhitelist(ctx: Context, guildId: string): Promise<void>;
|
|
59
|
+
export declare function getAllSmallGroupWhitelist(ctx: Context): Promise<SmallGroupWhitelist[]>;
|
|
60
|
+
export declare function getPendingInvite(ctx: Context, groupId: string): Promise<PendingInvite>;
|
|
61
|
+
export declare function addPendingInvite(ctx: Context, inviteUser: Omit<PendingInvite, 'platform'>): Promise<void>;
|
|
62
|
+
export declare function removePendingInvite(ctx: Context, groupId: string): Promise<void>;
|
|
63
|
+
export declare function getAllPendingInvites(ctx: Context): Promise<PendingInvite[]>;
|
|
64
|
+
export declare function clearExpiredPendingInvites(ctx: Context, expireTimeMs: number): Promise<number>;
|
package/lib/index.js
CHANGED
|
@@ -30,15 +30,24 @@ module.exports = __toCommonJS(src_exports);
|
|
|
30
30
|
var database_exports = {};
|
|
31
31
|
__export(database_exports, {
|
|
32
32
|
BLACKLIST_PLATFORM: () => BLACKLIST_PLATFORM,
|
|
33
|
+
addPendingInvite: () => addPendingInvite,
|
|
34
|
+
addToSmallGroupWhitelist: () => addToSmallGroupWhitelist,
|
|
33
35
|
apply: () => apply,
|
|
34
36
|
clearBlacklistedGuilds: () => clearBlacklistedGuilds,
|
|
37
|
+
clearExpiredPendingInvites: () => clearExpiredPendingInvites,
|
|
35
38
|
createBlacklistedGuild: () => createBlacklistedGuild,
|
|
36
39
|
getAllBlacklistedGuilds: () => getAllBlacklistedGuilds,
|
|
40
|
+
getAllPendingInvites: () => getAllPendingInvites,
|
|
41
|
+
getAllSmallGroupWhitelist: () => getAllSmallGroupWhitelist,
|
|
37
42
|
getBlacklistedGuild: () => getBlacklistedGuild,
|
|
38
43
|
getCommandFrequencyRecord: () => getCommandFrequencyRecord,
|
|
39
44
|
getGroupBotStatus: () => getGroupBotStatus,
|
|
45
|
+
getPendingInvite: () => getPendingInvite,
|
|
46
|
+
isInSmallGroupWhitelist: () => isInSmallGroupWhitelist,
|
|
40
47
|
name: () => name,
|
|
41
48
|
removeBlacklistedGuild: () => removeBlacklistedGuild,
|
|
49
|
+
removeFromSmallGroupWhitelist: () => removeFromSmallGroupWhitelist,
|
|
50
|
+
removePendingInvite: () => removePendingInvite,
|
|
42
51
|
setGroupBotStatus: () => setGroupBotStatus,
|
|
43
52
|
updateCommandFrequencyRecord: () => updateCommandFrequencyRecord
|
|
44
53
|
});
|
|
@@ -64,6 +73,19 @@ function apply(ctx) {
|
|
|
64
73
|
guildId: "string",
|
|
65
74
|
botEnabled: "boolean"
|
|
66
75
|
}, { primary: ["platform", "guildId"] });
|
|
76
|
+
ctx.model.extend("small_group_whitelist", {
|
|
77
|
+
platform: "string",
|
|
78
|
+
guildId: "string"
|
|
79
|
+
}, { primary: ["platform", "guildId"] });
|
|
80
|
+
ctx.model.extend("pending_invite", {
|
|
81
|
+
platform: "string",
|
|
82
|
+
groupId: "string",
|
|
83
|
+
userId: "string",
|
|
84
|
+
userName: "string",
|
|
85
|
+
groupName: "string",
|
|
86
|
+
time: "integer",
|
|
87
|
+
flag: "string"
|
|
88
|
+
}, { primary: ["platform", "groupId"] });
|
|
67
89
|
}
|
|
68
90
|
__name(apply, "apply");
|
|
69
91
|
var BLACKLIST_PLATFORM = "onebot";
|
|
@@ -114,6 +136,50 @@ async function setGroupBotStatus(ctx, platform, guildId, botEnabled) {
|
|
|
114
136
|
await ctx.model.upsert("group_bot_status", [{ platform, guildId, botEnabled }]);
|
|
115
137
|
}
|
|
116
138
|
__name(setGroupBotStatus, "setGroupBotStatus");
|
|
139
|
+
async function isInSmallGroupWhitelist(ctx, guildId) {
|
|
140
|
+
const records = await ctx.model.get("small_group_whitelist", { platform: BLACKLIST_PLATFORM, guildId });
|
|
141
|
+
return records.length > 0;
|
|
142
|
+
}
|
|
143
|
+
__name(isInSmallGroupWhitelist, "isInSmallGroupWhitelist");
|
|
144
|
+
async function addToSmallGroupWhitelist(ctx, guildId) {
|
|
145
|
+
await ctx.model.upsert("small_group_whitelist", [{ platform: BLACKLIST_PLATFORM, guildId }]);
|
|
146
|
+
}
|
|
147
|
+
__name(addToSmallGroupWhitelist, "addToSmallGroupWhitelist");
|
|
148
|
+
async function removeFromSmallGroupWhitelist(ctx, guildId) {
|
|
149
|
+
await ctx.model.remove("small_group_whitelist", { platform: BLACKLIST_PLATFORM, guildId });
|
|
150
|
+
}
|
|
151
|
+
__name(removeFromSmallGroupWhitelist, "removeFromSmallGroupWhitelist");
|
|
152
|
+
async function getAllSmallGroupWhitelist(ctx) {
|
|
153
|
+
return await ctx.model.get("small_group_whitelist", { platform: BLACKLIST_PLATFORM });
|
|
154
|
+
}
|
|
155
|
+
__name(getAllSmallGroupWhitelist, "getAllSmallGroupWhitelist");
|
|
156
|
+
async function getPendingInvite(ctx, groupId) {
|
|
157
|
+
const records = await ctx.model.get("pending_invite", { platform: BLACKLIST_PLATFORM, groupId });
|
|
158
|
+
return records.length > 0 ? records[0] : null;
|
|
159
|
+
}
|
|
160
|
+
__name(getPendingInvite, "getPendingInvite");
|
|
161
|
+
async function addPendingInvite(ctx, inviteUser) {
|
|
162
|
+
await ctx.model.upsert("pending_invite", [{ platform: BLACKLIST_PLATFORM, ...inviteUser }]);
|
|
163
|
+
}
|
|
164
|
+
__name(addPendingInvite, "addPendingInvite");
|
|
165
|
+
async function removePendingInvite(ctx, groupId) {
|
|
166
|
+
await ctx.model.remove("pending_invite", { platform: BLACKLIST_PLATFORM, groupId });
|
|
167
|
+
}
|
|
168
|
+
__name(removePendingInvite, "removePendingInvite");
|
|
169
|
+
async function getAllPendingInvites(ctx) {
|
|
170
|
+
return await ctx.model.get("pending_invite", { platform: BLACKLIST_PLATFORM });
|
|
171
|
+
}
|
|
172
|
+
__name(getAllPendingInvites, "getAllPendingInvites");
|
|
173
|
+
async function clearExpiredPendingInvites(ctx, expireTimeMs) {
|
|
174
|
+
const cutoff = Date.now() - expireTimeMs;
|
|
175
|
+
const all = await ctx.model.get("pending_invite", { platform: BLACKLIST_PLATFORM });
|
|
176
|
+
const expired = all.filter((r) => r.time < cutoff);
|
|
177
|
+
for (const record of expired) {
|
|
178
|
+
await ctx.model.remove("pending_invite", { platform: BLACKLIST_PLATFORM, groupId: record.groupId });
|
|
179
|
+
}
|
|
180
|
+
return expired.length;
|
|
181
|
+
}
|
|
182
|
+
__name(clearExpiredPendingInvites, "clearExpiredPendingInvites");
|
|
117
183
|
|
|
118
184
|
// src/modules/basic.ts
|
|
119
185
|
var basic_exports = {};
|
|
@@ -158,6 +224,9 @@ async function notifyAdmins(bot, config, message) {
|
|
|
158
224
|
}
|
|
159
225
|
__name(notifyAdmins, "notifyAdmins");
|
|
160
226
|
async function hasPermission(session, config) {
|
|
227
|
+
if (config.invite.adminQQs?.includes(session.userId)) {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
161
230
|
if (config.permission.mode === "koishi") {
|
|
162
231
|
try {
|
|
163
232
|
const user = session.user;
|
|
@@ -169,9 +238,6 @@ async function hasPermission(session, config) {
|
|
|
169
238
|
return false;
|
|
170
239
|
}
|
|
171
240
|
const userId = session.userId;
|
|
172
|
-
if (config.invite.adminQQs?.includes(userId)) {
|
|
173
|
-
return true;
|
|
174
|
-
}
|
|
175
241
|
try {
|
|
176
242
|
const member = await session.bot.getGuildMember(session.guildId, userId);
|
|
177
243
|
const roles = member?.roles || member?.role;
|
|
@@ -198,17 +264,31 @@ async function hasPermission(session, config) {
|
|
|
198
264
|
return false;
|
|
199
265
|
}
|
|
200
266
|
__name(hasPermission, "hasPermission");
|
|
267
|
+
function isGlobalAdmin(session, config) {
|
|
268
|
+
if (config.invite.adminQQs?.includes(session.userId)) {
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
const user = session.user;
|
|
272
|
+
if (config.permission.mode === "koishi" && user && typeof user.authority === "number") {
|
|
273
|
+
return user.authority >= 4;
|
|
274
|
+
}
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
__name(isGlobalAdmin, "isGlobalAdmin");
|
|
201
278
|
var ADMIN_COMMANDS = /* @__PURE__ */ new Set([
|
|
202
279
|
"bot-on",
|
|
203
280
|
"bot-off",
|
|
204
281
|
"quit",
|
|
205
|
-
"
|
|
206
|
-
"
|
|
207
|
-
"
|
|
208
|
-
"
|
|
282
|
+
"banlist",
|
|
283
|
+
"unban",
|
|
284
|
+
"ban",
|
|
285
|
+
"clearban",
|
|
209
286
|
"approve",
|
|
210
287
|
"reject",
|
|
211
|
-
"pending
|
|
288
|
+
"pending",
|
|
289
|
+
"sg-add",
|
|
290
|
+
"sg-rm",
|
|
291
|
+
"sg-list"
|
|
212
292
|
]);
|
|
213
293
|
|
|
214
294
|
// src/state.ts
|
|
@@ -263,8 +343,10 @@ function apply2(ctx, config) {
|
|
|
263
343
|
}
|
|
264
344
|
}
|
|
265
345
|
if (config.basic.smallGroupAutoQuit) {
|
|
266
|
-
|
|
267
|
-
|
|
346
|
+
const inWhitelist = await isInSmallGroupWhitelist(ctx, guildId);
|
|
347
|
+
const wasApproved = approvedGroups.has(guildId);
|
|
348
|
+
if (wasApproved) approvedGroups.delete(guildId);
|
|
349
|
+
if (inWhitelist || wasApproved) {
|
|
268
350
|
} else {
|
|
269
351
|
const delay = config.basic.smallGroupCheckDelay || 3e3;
|
|
270
352
|
setTimeout(async () => {
|
|
@@ -397,19 +479,17 @@ __export(invite_exports, {
|
|
|
397
479
|
var name3 = "group-control-invite";
|
|
398
480
|
function apply3(ctx, config) {
|
|
399
481
|
if (!config.invite.enabled) return;
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
pendingInvites.delete(key);
|
|
407
|
-
if (config.invite.showDetailedLog) {
|
|
408
|
-
console.log(`邀请超时已清理: 群号=${invite.groupId}, 邀请者=${invite.userId}`);
|
|
409
|
-
}
|
|
482
|
+
setInterval(async () => {
|
|
483
|
+
const expireMs = config.invite.inviteExpireDays * 24 * 60 * 60 * 1e3;
|
|
484
|
+
try {
|
|
485
|
+
const count = await clearExpiredPendingInvites(ctx, expireMs);
|
|
486
|
+
if (count > 0 && config.invite.showDetailedLog) {
|
|
487
|
+
console.log(`已自动清理 ${count} 个过期邀请`);
|
|
410
488
|
}
|
|
489
|
+
} catch (error) {
|
|
490
|
+
console.error("清理过期邀请失败:", error);
|
|
411
491
|
}
|
|
412
|
-
}, 60 * 1e3);
|
|
492
|
+
}, 60 * 60 * 1e3);
|
|
413
493
|
ctx.on("guild-request", async (session) => {
|
|
414
494
|
const raw = session.original || session.raw || session.event?._data || {};
|
|
415
495
|
const flag = raw.flag || session.flag || session.messageId;
|
|
@@ -456,7 +536,7 @@ function apply3(ctx, config) {
|
|
|
456
536
|
}
|
|
457
537
|
return;
|
|
458
538
|
}
|
|
459
|
-
|
|
539
|
+
await addPendingInvite(ctx, {
|
|
460
540
|
groupId: rawGroupId,
|
|
461
541
|
userId: rawUserId,
|
|
462
542
|
userName,
|
|
@@ -494,14 +574,15 @@ function apply3(ctx, config) {
|
|
|
494
574
|
console.warn("群邀请请求发送失败:未配置通知群且管理员私聊发送失败");
|
|
495
575
|
}
|
|
496
576
|
});
|
|
497
|
-
ctx.command("approve <groupId:string>", "同意群聊邀请"
|
|
577
|
+
ctx.command("approve <groupId:string>", "同意群聊邀请").action(async ({ session }, groupId) => {
|
|
498
578
|
if (!groupId) return "请指定群号。用法:approve <群号>";
|
|
499
579
|
if (!config.invite.adminQQs.includes(session.userId)) {
|
|
500
580
|
return "权限不足,只有管理员可以审核邀请。";
|
|
501
581
|
}
|
|
502
|
-
const inviteData =
|
|
582
|
+
const inviteData = await getPendingInvite(ctx, groupId);
|
|
503
583
|
if (!inviteData) {
|
|
504
|
-
|
|
584
|
+
const allInvites = await getAllPendingInvites(ctx);
|
|
585
|
+
return `未找到群号 ${groupId} 的待处理邀请。当前待处理邀请:${allInvites.length > 0 ? allInvites.map((i) => `${i.groupId}(${i.groupName})`).join(", ") : "无"}`;
|
|
505
586
|
}
|
|
506
587
|
try {
|
|
507
588
|
await session.bot.internal.setGroupAddRequest(inviteData.flag, "invite", true, "");
|
|
@@ -511,21 +592,22 @@ function apply3(ctx, config) {
|
|
|
511
592
|
} catch (error) {
|
|
512
593
|
console.error("通知邀请者失败:", error);
|
|
513
594
|
}
|
|
514
|
-
|
|
595
|
+
await removePendingInvite(ctx, groupId);
|
|
515
596
|
return `已同意加入群 ${groupId}(${inviteData.groupName}),邀请者:${inviteData.userName}`;
|
|
516
597
|
} catch (error) {
|
|
517
598
|
console.error("处理同意邀请失败:", error);
|
|
518
599
|
return `处理同意邀请失败: ${error.message}`;
|
|
519
600
|
}
|
|
520
601
|
});
|
|
521
|
-
ctx.command("reject <groupId:string>", "拒绝群聊邀请"
|
|
602
|
+
ctx.command("reject <groupId:string>", "拒绝群聊邀请").action(async ({ session }, groupId) => {
|
|
522
603
|
if (!groupId) return "请指定群号。用法:reject <群号>";
|
|
523
604
|
if (!config.invite.adminQQs.includes(session.userId)) {
|
|
524
605
|
return "权限不足,只有管理员可以审核邀请。";
|
|
525
606
|
}
|
|
526
|
-
const inviteData =
|
|
607
|
+
const inviteData = await getPendingInvite(ctx, groupId);
|
|
527
608
|
if (!inviteData) {
|
|
528
|
-
|
|
609
|
+
const allInvites = await getAllPendingInvites(ctx);
|
|
610
|
+
return `未找到群号 ${groupId} 的待处理邀请。当前待处理邀请:${allInvites.length > 0 ? allInvites.map((i) => `${i.groupId}(${i.groupName})`).join(", ") : "无"}`;
|
|
529
611
|
}
|
|
530
612
|
try {
|
|
531
613
|
await session.bot.internal.setGroupAddRequest(inviteData.flag, "invite", false, "已拒绝");
|
|
@@ -534,22 +616,23 @@ function apply3(ctx, config) {
|
|
|
534
616
|
} catch (error) {
|
|
535
617
|
console.error("通知邀请者失败:", error);
|
|
536
618
|
}
|
|
537
|
-
|
|
619
|
+
await removePendingInvite(ctx, groupId);
|
|
538
620
|
return `已拒绝加入群 ${groupId}(${inviteData.groupName}),邀请者:${inviteData.userName}`;
|
|
539
621
|
} catch (error) {
|
|
540
622
|
console.error("处理拒绝邀请失败:", error);
|
|
541
623
|
return `处理拒绝邀请失败: ${error.message}`;
|
|
542
624
|
}
|
|
543
625
|
});
|
|
544
|
-
ctx.command("pending
|
|
626
|
+
ctx.command("pending", "查看待处理的群聊邀请").action(async ({ session }) => {
|
|
545
627
|
if (!config.invite.adminQQs.includes(session.userId)) {
|
|
546
628
|
return "权限不足,只有管理员可以查看待处理邀请。";
|
|
547
629
|
}
|
|
548
|
-
|
|
630
|
+
const allInvites = await getAllPendingInvites(ctx);
|
|
631
|
+
if (allInvites.length === 0) {
|
|
549
632
|
return "当前没有待处理的群聊邀请。";
|
|
550
633
|
}
|
|
551
634
|
const lines = ["待处理的群聊邀请列表:"];
|
|
552
|
-
for (const
|
|
635
|
+
for (const invite of allInvites) {
|
|
553
636
|
const elapsed = Math.floor((Date.now() - invite.time) / 1e3 / 60);
|
|
554
637
|
lines.push(`- 群:${invite.groupName}(${invite.groupId})`);
|
|
555
638
|
lines.push(` 邀请者:${invite.userName}(${invite.userId})`);
|
|
@@ -643,7 +726,8 @@ __export(commands_exports, {
|
|
|
643
726
|
});
|
|
644
727
|
var name5 = "group-control-commands";
|
|
645
728
|
function apply5(ctx, config) {
|
|
646
|
-
async function viewBlacklist() {
|
|
729
|
+
async function viewBlacklist({ session }) {
|
|
730
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
647
731
|
const errorMsg = isBlacklistEnabled(config.basic);
|
|
648
732
|
if (errorMsg) return errorMsg;
|
|
649
733
|
const records = await getAllBlacklistedGuilds(ctx);
|
|
@@ -651,8 +735,9 @@ function apply5(ctx, config) {
|
|
|
651
735
|
return "黑名单列表:\n" + records.map((r) => `- ${r.guildId} (时间: ${formatDate(r.timestamp)})`).join("\n");
|
|
652
736
|
}
|
|
653
737
|
__name(viewBlacklist, "viewBlacklist");
|
|
654
|
-
ctx.command("
|
|
655
|
-
async function removeFromBlacklist({}, input) {
|
|
738
|
+
ctx.command("banlist", "查看被拉黑的群聊列表").action(viewBlacklist);
|
|
739
|
+
async function removeFromBlacklist({ session }, input) {
|
|
740
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
656
741
|
const errorMsg = isBlacklistEnabled(config.basic);
|
|
657
742
|
if (errorMsg) return errorMsg;
|
|
658
743
|
const guildId = parseGuildId(input);
|
|
@@ -661,8 +746,9 @@ function apply5(ctx, config) {
|
|
|
661
746
|
return removed ? `已移除群聊 ${guildId}` : `群聊 ${guildId} 不在黑名单中。`;
|
|
662
747
|
}
|
|
663
748
|
__name(removeFromBlacklist, "removeFromBlacklist");
|
|
664
|
-
ctx.command("
|
|
665
|
-
async function addToBlacklist({}, input) {
|
|
749
|
+
ctx.command("unban <groupId:text>", "从黑名单移除指定群聊").action(removeFromBlacklist);
|
|
750
|
+
async function addToBlacklist({ session }, input) {
|
|
751
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
666
752
|
const errorMsg = isBlacklistEnabled(config.basic);
|
|
667
753
|
if (errorMsg) return errorMsg;
|
|
668
754
|
const guildId = parseGuildId(input);
|
|
@@ -673,8 +759,9 @@ function apply5(ctx, config) {
|
|
|
673
759
|
return `已添加群聊 ${guildId} 到黑名单。`;
|
|
674
760
|
}
|
|
675
761
|
__name(addToBlacklist, "addToBlacklist");
|
|
676
|
-
ctx.command("
|
|
677
|
-
async function clearBlacklist() {
|
|
762
|
+
ctx.command("ban <groupId:text>", "手动添加群聊到黑名单").action(addToBlacklist);
|
|
763
|
+
async function clearBlacklist({ session }) {
|
|
764
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
678
765
|
const errorMsg = isBlacklistEnabled(config.basic);
|
|
679
766
|
if (errorMsg) return errorMsg;
|
|
680
767
|
const records = await getAllBlacklistedGuilds(ctx);
|
|
@@ -683,7 +770,31 @@ function apply5(ctx, config) {
|
|
|
683
770
|
return `已清空黑名单,共移除 ${records.length} 个群聊。`;
|
|
684
771
|
}
|
|
685
772
|
__name(clearBlacklist, "clearBlacklist");
|
|
686
|
-
ctx.command("
|
|
773
|
+
ctx.command("clearban", "清空黑名单").action(clearBlacklist);
|
|
774
|
+
ctx.command("sg-add <groupId:text>", "解除指定群聊的小群人数限制").action(async ({ session }, input) => {
|
|
775
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
776
|
+
const guildId = parseGuildId(input);
|
|
777
|
+
if (!guildId) return "输入格式错误,请输入群号。";
|
|
778
|
+
const exists = await isInSmallGroupWhitelist(ctx, guildId);
|
|
779
|
+
if (exists) return `群聊 ${guildId} 已在小群白名单中。`;
|
|
780
|
+
await addToSmallGroupWhitelist(ctx, guildId);
|
|
781
|
+
return `已将群聊 ${guildId} 加入小群白名单,该群不再受小群人数限制。`;
|
|
782
|
+
});
|
|
783
|
+
ctx.command("sg-rm <groupId:text>", "恢复指定群聊的小群人数限制").action(async ({ session }, input) => {
|
|
784
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
785
|
+
const guildId = parseGuildId(input);
|
|
786
|
+
if (!guildId) return "输入格式错误,请输入群号。";
|
|
787
|
+
const exists = await isInSmallGroupWhitelist(ctx, guildId);
|
|
788
|
+
if (!exists) return `群聊 ${guildId} 不在小群白名单中。`;
|
|
789
|
+
await removeFromSmallGroupWhitelist(ctx, guildId);
|
|
790
|
+
return `已将群聊 ${guildId} 从小群白名单移除,该群将恢复小群人数限制。`;
|
|
791
|
+
});
|
|
792
|
+
ctx.command("sg-list", "查看小群白名单").action(async ({ session }) => {
|
|
793
|
+
if (!isGlobalAdmin(session, config)) return "权限不足,只有全局管理员可以执行此操作。";
|
|
794
|
+
const records = await getAllSmallGroupWhitelist(ctx);
|
|
795
|
+
if (records.length === 0) return "小群白名单为空。";
|
|
796
|
+
return "小群白名单列表(以下群不受小群人数限制):\n" + records.map((r) => `- ${r.guildId}`).join("\n");
|
|
797
|
+
});
|
|
687
798
|
}
|
|
688
799
|
__name(apply5, "apply");
|
|
689
800
|
|
|
@@ -820,7 +931,8 @@ var Config = import_koishi.Schema.intersect([
|
|
|
820
931
|
inviteWaitMessage: import_koishi.Schema.string().default("已收到您的群聊邀请,正在等待管理员审核,请耐心等待。").description("发送给邀请者的等待审核提示消息"),
|
|
821
932
|
inviteRequestMessage: import_koishi.Schema.string().default("收到新的群聊邀请请求:\n群名称:{groupName}\n群号:{groupId}\n邀请者:{userName} (QQ: {userId})\n\n请管理员使用指令 approve {groupId} 同意或 reject {groupId} 拒绝。").description("发送给管理员的邀请请求消息模板,支持变量{groupName}, {groupId}, {userName}, {userId}"),
|
|
822
933
|
autoApprove: import_koishi.Schema.boolean().default(false).description("是否自动同意邀请(仅在没有指定管理员时)"),
|
|
823
|
-
showDetailedLog: import_koishi.Schema.boolean().default(false).description("是否显示详细日志")
|
|
934
|
+
showDetailedLog: import_koishi.Schema.boolean().default(false).description("是否显示详细日志"),
|
|
935
|
+
inviteExpireDays: import_koishi.Schema.number().default(3).description("邀请记录过期时间(天),超过此时间未处理的邀请将被自动清理")
|
|
824
936
|
}).description("群聊邀请审核")
|
|
825
937
|
}),
|
|
826
938
|
import_koishi.Schema.object({
|
package/lib/utils.d.ts
CHANGED
|
@@ -10,5 +10,10 @@ export declare function notifyAdmins(bot: any, config: Config, message: string):
|
|
|
10
10
|
* - builtin 模式: 检查用户是否为群管理员/群主,或在管理员QQ列表中
|
|
11
11
|
*/
|
|
12
12
|
export declare function hasPermission(session: Session, config: Config): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* 检查当前用户是否拥有全局管理权限
|
|
15
|
+
* (供独立于群聊的全局指令(如黑名单、白名单)使用)
|
|
16
|
+
*/
|
|
17
|
+
export declare function isGlobalAdmin(session: Session, config: Config): boolean;
|
|
13
18
|
/** 管理指令列表 - 这些指令始终不受 bot-off 影响 */
|
|
14
19
|
export declare const ADMIN_COMMANDS: Set<string>;
|
package/package.json
CHANGED