koishi-plugin-group-control 0.2.9 → 0.2.11
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/database.d.ts +9 -0
- package/lib/index.js +126 -41
- package/lib/state.d.ts +6 -0
- package/package.json +1 -1
package/lib/database.d.ts
CHANGED
|
@@ -19,11 +19,16 @@ export interface GroupBotStatus {
|
|
|
19
19
|
guildId: string;
|
|
20
20
|
botEnabled: boolean;
|
|
21
21
|
}
|
|
22
|
+
export interface SmallGroupWhitelist {
|
|
23
|
+
platform: string;
|
|
24
|
+
guildId: string;
|
|
25
|
+
}
|
|
22
26
|
declare module 'koishi' {
|
|
23
27
|
interface Tables {
|
|
24
28
|
blacklisted_guild: BlacklistedGuild;
|
|
25
29
|
command_frequency_record: CommandFrequencyRecord;
|
|
26
30
|
group_bot_status: GroupBotStatus;
|
|
31
|
+
small_group_whitelist: SmallGroupWhitelist;
|
|
27
32
|
}
|
|
28
33
|
}
|
|
29
34
|
export declare const name = "group-control-database";
|
|
@@ -38,3 +43,7 @@ export declare function getCommandFrequencyRecord(ctx: Context, platform: string
|
|
|
38
43
|
export declare function updateCommandFrequencyRecord(ctx: Context, platform: string, guildId: string, data: Partial<CommandFrequencyRecord>): Promise<void>;
|
|
39
44
|
export declare function getGroupBotStatus(ctx: Context, platform: string, guildId: string): Promise<GroupBotStatus | null>;
|
|
40
45
|
export declare function setGroupBotStatus(ctx: Context, platform: string, guildId: string, botEnabled: boolean): Promise<void>;
|
|
46
|
+
export declare function isInSmallGroupWhitelist(ctx: Context, guildId: string): Promise<boolean>;
|
|
47
|
+
export declare function addToSmallGroupWhitelist(ctx: Context, guildId: string): Promise<void>;
|
|
48
|
+
export declare function removeFromSmallGroupWhitelist(ctx: Context, guildId: string): Promise<void>;
|
|
49
|
+
export declare function getAllSmallGroupWhitelist(ctx: Context): Promise<SmallGroupWhitelist[]>;
|
package/lib/index.js
CHANGED
|
@@ -30,15 +30,19 @@ module.exports = __toCommonJS(src_exports);
|
|
|
30
30
|
var database_exports = {};
|
|
31
31
|
__export(database_exports, {
|
|
32
32
|
BLACKLIST_PLATFORM: () => BLACKLIST_PLATFORM,
|
|
33
|
+
addToSmallGroupWhitelist: () => addToSmallGroupWhitelist,
|
|
33
34
|
apply: () => apply,
|
|
34
35
|
clearBlacklistedGuilds: () => clearBlacklistedGuilds,
|
|
35
36
|
createBlacklistedGuild: () => createBlacklistedGuild,
|
|
36
37
|
getAllBlacklistedGuilds: () => getAllBlacklistedGuilds,
|
|
38
|
+
getAllSmallGroupWhitelist: () => getAllSmallGroupWhitelist,
|
|
37
39
|
getBlacklistedGuild: () => getBlacklistedGuild,
|
|
38
40
|
getCommandFrequencyRecord: () => getCommandFrequencyRecord,
|
|
39
41
|
getGroupBotStatus: () => getGroupBotStatus,
|
|
42
|
+
isInSmallGroupWhitelist: () => isInSmallGroupWhitelist,
|
|
40
43
|
name: () => name,
|
|
41
44
|
removeBlacklistedGuild: () => removeBlacklistedGuild,
|
|
45
|
+
removeFromSmallGroupWhitelist: () => removeFromSmallGroupWhitelist,
|
|
42
46
|
setGroupBotStatus: () => setGroupBotStatus,
|
|
43
47
|
updateCommandFrequencyRecord: () => updateCommandFrequencyRecord
|
|
44
48
|
});
|
|
@@ -64,6 +68,10 @@ function apply(ctx) {
|
|
|
64
68
|
guildId: "string",
|
|
65
69
|
botEnabled: "boolean"
|
|
66
70
|
}, { primary: ["platform", "guildId"] });
|
|
71
|
+
ctx.model.extend("small_group_whitelist", {
|
|
72
|
+
platform: "string",
|
|
73
|
+
guildId: "string"
|
|
74
|
+
}, { primary: ["platform", "guildId"] });
|
|
67
75
|
}
|
|
68
76
|
__name(apply, "apply");
|
|
69
77
|
var BLACKLIST_PLATFORM = "onebot";
|
|
@@ -114,6 +122,23 @@ async function setGroupBotStatus(ctx, platform, guildId, botEnabled) {
|
|
|
114
122
|
await ctx.model.upsert("group_bot_status", [{ platform, guildId, botEnabled }]);
|
|
115
123
|
}
|
|
116
124
|
__name(setGroupBotStatus, "setGroupBotStatus");
|
|
125
|
+
async function isInSmallGroupWhitelist(ctx, guildId) {
|
|
126
|
+
const records = await ctx.model.get("small_group_whitelist", { platform: BLACKLIST_PLATFORM, guildId });
|
|
127
|
+
return records.length > 0;
|
|
128
|
+
}
|
|
129
|
+
__name(isInSmallGroupWhitelist, "isInSmallGroupWhitelist");
|
|
130
|
+
async function addToSmallGroupWhitelist(ctx, guildId) {
|
|
131
|
+
await ctx.model.upsert("small_group_whitelist", [{ platform: BLACKLIST_PLATFORM, guildId }]);
|
|
132
|
+
}
|
|
133
|
+
__name(addToSmallGroupWhitelist, "addToSmallGroupWhitelist");
|
|
134
|
+
async function removeFromSmallGroupWhitelist(ctx, guildId) {
|
|
135
|
+
await ctx.model.remove("small_group_whitelist", { platform: BLACKLIST_PLATFORM, guildId });
|
|
136
|
+
}
|
|
137
|
+
__name(removeFromSmallGroupWhitelist, "removeFromSmallGroupWhitelist");
|
|
138
|
+
async function getAllSmallGroupWhitelist(ctx) {
|
|
139
|
+
return await ctx.model.get("small_group_whitelist", { platform: BLACKLIST_PLATFORM });
|
|
140
|
+
}
|
|
141
|
+
__name(getAllSmallGroupWhitelist, "getAllSmallGroupWhitelist");
|
|
117
142
|
|
|
118
143
|
// src/modules/basic.ts
|
|
119
144
|
var basic_exports = {};
|
|
@@ -208,11 +233,32 @@ var ADMIN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
208
233
|
"clear-blacklist",
|
|
209
234
|
"approve",
|
|
210
235
|
"reject",
|
|
211
|
-
"pending-invites"
|
|
236
|
+
"pending-invites",
|
|
237
|
+
"allow-small-group",
|
|
238
|
+
"disallow-small-group",
|
|
239
|
+
"view-small-group-whitelist"
|
|
212
240
|
]);
|
|
213
241
|
|
|
242
|
+
// src/state.ts
|
|
243
|
+
var approvedGroups = /* @__PURE__ */ new Set();
|
|
244
|
+
|
|
214
245
|
// src/modules/basic.ts
|
|
215
246
|
var name2 = "group-control-basic";
|
|
247
|
+
async function getGroupName(bot, guildId) {
|
|
248
|
+
try {
|
|
249
|
+
const info = await bot.internal?.getGroupInfo?.(parseInt(guildId));
|
|
250
|
+
if (info?.group_name) return info.group_name;
|
|
251
|
+
} catch {
|
|
252
|
+
}
|
|
253
|
+
try {
|
|
254
|
+
const info = await bot.getGuild(guildId);
|
|
255
|
+
if (info?.name) return info.name;
|
|
256
|
+
if (info?.group_name) return info.group_name;
|
|
257
|
+
} catch {
|
|
258
|
+
}
|
|
259
|
+
return "未知";
|
|
260
|
+
}
|
|
261
|
+
__name(getGroupName, "getGroupName");
|
|
216
262
|
function apply2(ctx, config) {
|
|
217
263
|
const quittingGuilds = /* @__PURE__ */ new Map();
|
|
218
264
|
const processedKicks = /* @__PURE__ */ new Map();
|
|
@@ -245,54 +291,67 @@ function apply2(ctx, config) {
|
|
|
245
291
|
}
|
|
246
292
|
}
|
|
247
293
|
if (config.basic.smallGroupAutoQuit) {
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
294
|
+
const inWhitelist = await isInSmallGroupWhitelist(ctx, guildId);
|
|
295
|
+
const wasApproved = approvedGroups.has(guildId);
|
|
296
|
+
if (wasApproved) approvedGroups.delete(guildId);
|
|
297
|
+
if (inWhitelist || wasApproved) {
|
|
298
|
+
} else {
|
|
299
|
+
const delay = config.basic.smallGroupCheckDelay || 3e3;
|
|
300
|
+
setTimeout(async () => {
|
|
252
301
|
try {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
} catch {
|
|
256
|
-
}
|
|
257
|
-
if (memberCount === 0) {
|
|
302
|
+
let memberCount = 0;
|
|
303
|
+
let groupName = "未知";
|
|
258
304
|
try {
|
|
259
|
-
const
|
|
260
|
-
memberCount =
|
|
305
|
+
const groupInfo = await session.bot.internal?.getGroupInfo?.(parseInt(guildId));
|
|
306
|
+
memberCount = groupInfo?.member_count || 0;
|
|
307
|
+
if (groupInfo?.group_name) groupName = groupInfo.group_name;
|
|
261
308
|
} catch {
|
|
262
309
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
310
|
+
if (memberCount === 0) {
|
|
311
|
+
try {
|
|
312
|
+
const guildInfo = await session.bot.getGuild(guildId);
|
|
313
|
+
memberCount = guildInfo?.member_count || guildInfo?.memberCount || 0;
|
|
314
|
+
if (guildInfo?.name) groupName = guildInfo.name;
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
269
317
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
318
|
+
if (memberCount === 0) {
|
|
319
|
+
try {
|
|
320
|
+
const memberList = await session.bot.getGuildMemberList(guildId);
|
|
321
|
+
memberCount = memberList?.data?.length || 0;
|
|
322
|
+
} catch {
|
|
323
|
+
}
|
|
276
324
|
}
|
|
277
|
-
if (
|
|
278
|
-
|
|
325
|
+
if (groupName === "未知") {
|
|
326
|
+
groupName = await getGroupName(session.bot, guildId);
|
|
327
|
+
}
|
|
328
|
+
if (memberCount > 0 && memberCount <= config.basic.smallGroupThreshold) {
|
|
329
|
+
const quitMsg = config.basic.smallGroupQuitMessage.replaceAll("{memberCount}", memberCount.toString()).replaceAll("{threshold}", config.basic.smallGroupThreshold.toString()).replaceAll("{groupName}", groupName).replaceAll("{groupId}", guildId);
|
|
330
|
+
try {
|
|
331
|
+
await session.bot.sendMessage(guildId, quitMsg, platform);
|
|
332
|
+
} catch (e) {
|
|
333
|
+
}
|
|
334
|
+
if (config.basic.smallGroupNotifyAdmin) {
|
|
335
|
+
const adminMsg = `小群自动退群
|
|
336
|
+
群名称:${groupName}
|
|
279
337
|
群号:${guildId}
|
|
280
338
|
群成员数:${memberCount}人(阈值:${config.basic.smallGroupThreshold}人)
|
|
281
339
|
机器人已自动退出该群。`;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
340
|
+
await notifyAdmins(session.bot, config, adminMsg);
|
|
341
|
+
}
|
|
342
|
+
quittingGuilds.set(`${platform}:${guildId}`, Date.now());
|
|
343
|
+
try {
|
|
344
|
+
await session.bot.internal.setGroupLeave(parseInt(guildId));
|
|
345
|
+
} catch (e) {
|
|
346
|
+
console.error(`小群自动退群失败 (群号: ${guildId}):`, e);
|
|
347
|
+
quittingGuilds.delete(`${platform}:${guildId}`);
|
|
348
|
+
}
|
|
290
349
|
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
console.error(`小群自动退群检测失败 (群号: ${guildId}):`, error);
|
|
291
352
|
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
}
|
|
295
|
-
}, delay);
|
|
353
|
+
}, delay);
|
|
354
|
+
}
|
|
296
355
|
}
|
|
297
356
|
if (config.basic.welcomeMessage) {
|
|
298
357
|
try {
|
|
@@ -311,6 +370,7 @@ function apply2(ctx, config) {
|
|
|
311
370
|
return;
|
|
312
371
|
}
|
|
313
372
|
processedKicks.set(quittingKey, Date.now());
|
|
373
|
+
const groupName = await getGroupName(session.bot, guildId);
|
|
314
374
|
if (config.basic.enableBlacklist) {
|
|
315
375
|
await ctx.model.upsert("blacklisted_guild", [{
|
|
316
376
|
platform,
|
|
@@ -320,7 +380,7 @@ function apply2(ctx, config) {
|
|
|
320
380
|
}]);
|
|
321
381
|
}
|
|
322
382
|
if (config.basic.notifyAdminOnKick) {
|
|
323
|
-
const kickMsg = config.basic.kickNotificationMessage.
|
|
383
|
+
const kickMsg = config.basic.kickNotificationMessage.replaceAll("{groupId}", guildId).replaceAll("{groupName}", groupName);
|
|
324
384
|
await notifyAdmins(session.bot, config, kickMsg);
|
|
325
385
|
}
|
|
326
386
|
});
|
|
@@ -336,7 +396,9 @@ function apply2(ctx, config) {
|
|
|
336
396
|
if (!hasPerm) return "权限不足,只有群管理员可以使用此指令。";
|
|
337
397
|
}
|
|
338
398
|
const { guildId, platform, userId } = session;
|
|
399
|
+
const groupName = await getGroupName(session.bot, guildId);
|
|
339
400
|
const adminMsg = `收到来自 ${userId} 的退群指令
|
|
401
|
+
群名称:${groupName}
|
|
340
402
|
群号:${guildId}`;
|
|
341
403
|
await notifyAdmins(session.bot, config, adminMsg);
|
|
342
404
|
quittingGuilds.set(`${platform}:${guildId}`, Date.now());
|
|
@@ -414,6 +476,7 @@ function apply3(ctx, config) {
|
|
|
414
476
|
if (config.invite.autoApprove) {
|
|
415
477
|
try {
|
|
416
478
|
await session.bot.internal.setGroupAddRequest(flag, "invite", true, "");
|
|
479
|
+
approvedGroups.add(rawGroupId);
|
|
417
480
|
if (config.invite.showDetailedLog) {
|
|
418
481
|
console.log(`自动同意群聊邀请: 群号 ${rawGroupId}, 邀请者 ${rawUserId}`);
|
|
419
482
|
}
|
|
@@ -472,6 +535,7 @@ function apply3(ctx, config) {
|
|
|
472
535
|
}
|
|
473
536
|
try {
|
|
474
537
|
await session.bot.internal.setGroupAddRequest(inviteData.flag, "invite", true, "");
|
|
538
|
+
approvedGroups.add(groupId);
|
|
475
539
|
try {
|
|
476
540
|
await session.bot.sendPrivateMessage(inviteData.userId, `您的群聊邀请已通过管理员审核,机器人已加入群聊。`);
|
|
477
541
|
} catch (error) {
|
|
@@ -650,6 +714,27 @@ function apply5(ctx, config) {
|
|
|
650
714
|
}
|
|
651
715
|
__name(clearBlacklist, "clearBlacklist");
|
|
652
716
|
ctx.command("clear-blacklist", "清空黑名单", { authority: 4 }).action(clearBlacklist);
|
|
717
|
+
ctx.command("allow-small-group <groupId:text>", "解除指定群聊的小群人数限制", { authority: 4 }).action(async ({}, input) => {
|
|
718
|
+
const guildId = parseGuildId(input);
|
|
719
|
+
if (!guildId) return "输入格式错误,请输入群号。";
|
|
720
|
+
const exists = await isInSmallGroupWhitelist(ctx, guildId);
|
|
721
|
+
if (exists) return `群聊 ${guildId} 已在小群白名单中。`;
|
|
722
|
+
await addToSmallGroupWhitelist(ctx, guildId);
|
|
723
|
+
return `已将群聊 ${guildId} 加入小群白名单,该群不再受小群人数限制。`;
|
|
724
|
+
});
|
|
725
|
+
ctx.command("disallow-small-group <groupId:text>", "恢复指定群聊的小群人数限制", { authority: 4 }).action(async ({}, input) => {
|
|
726
|
+
const guildId = parseGuildId(input);
|
|
727
|
+
if (!guildId) return "输入格式错误,请输入群号。";
|
|
728
|
+
const exists = await isInSmallGroupWhitelist(ctx, guildId);
|
|
729
|
+
if (!exists) return `群聊 ${guildId} 不在小群白名单中。`;
|
|
730
|
+
await removeFromSmallGroupWhitelist(ctx, guildId);
|
|
731
|
+
return `已将群聊 ${guildId} 从小群白名单移除,该群将恢复小群人数限制。`;
|
|
732
|
+
});
|
|
733
|
+
ctx.command("view-small-group-whitelist", "查看小群白名单", { authority: 4 }).action(async () => {
|
|
734
|
+
const records = await getAllSmallGroupWhitelist(ctx);
|
|
735
|
+
if (records.length === 0) return "小群白名单为空。";
|
|
736
|
+
return "小群白名单列表(以下群不受小群人数限制):\n" + records.map((r) => `- ${r.guildId}`).join("\n");
|
|
737
|
+
});
|
|
653
738
|
}
|
|
654
739
|
__name(apply5, "apply");
|
|
655
740
|
|
|
@@ -757,10 +842,10 @@ var Config = import_koishi.Schema.intersect([
|
|
|
757
842
|
enableBlacklist: import_koishi.Schema.boolean().default(true).description('启用"被踢出自动拉黑"功能'),
|
|
758
843
|
quitCommandEnabled: import_koishi.Schema.boolean().default(true).description("启用quit"),
|
|
759
844
|
notifyAdminOnKick: import_koishi.Schema.boolean().default(true).description("被踢出群时通知管理员(需要在群聊邀请审核中配置管理员QQ)"),
|
|
760
|
-
kickNotificationMessage: import_koishi.Schema.string().default("机器人已被踢出群聊\n群号:{groupId}\n该群已被自动加入黑名单。").description("被踢出群通知消息模板,支持变量{groupId}"),
|
|
845
|
+
kickNotificationMessage: import_koishi.Schema.string().default("机器人已被踢出群聊\n群名称:{groupName}\n群号:{groupId}\n该群已被自动加入黑名单。").description("被踢出群通知消息模板,支持变量{groupId}, {groupName}"),
|
|
761
846
|
smallGroupAutoQuit: import_koishi.Schema.boolean().default(false).description("启用小群自动退群功能"),
|
|
762
847
|
smallGroupThreshold: import_koishi.Schema.number().default(30).description("小群人数阈值(群成员数小于等于此值时自动退群)"),
|
|
763
|
-
smallGroupQuitMessage: import_koishi.Schema.string().default("该群人数过少({memberCount}人),不满足最低人数要求({threshold}人),机器人将自动退出。").description("小群自动退群时在群内发送的提示,支持变量{memberCount}, {threshold}"),
|
|
848
|
+
smallGroupQuitMessage: import_koishi.Schema.string().default("该群人数过少({memberCount}人),不满足最低人数要求({threshold}人),机器人将自动退出。").description("小群自动退群时在群内发送的提示,支持变量{memberCount}, {threshold}, {groupName}, {groupId}"),
|
|
764
849
|
smallGroupNotifyAdmin: import_koishi.Schema.boolean().default(true).description("小群自动退群时通知管理员"),
|
|
765
850
|
smallGroupCheckDelay: import_koishi.Schema.number().default(3e3).description("小群检测延迟(毫秒),加入群聊后等待一段时间再获取群信息以确保数据准确")
|
|
766
851
|
}).description("基础群组管理")
|
package/lib/state.d.ts
ADDED
package/package.json
CHANGED