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 CHANGED
@@ -21,6 +21,7 @@ export interface GroupInviteConfig {
21
21
  inviteRequestMessage: string;
22
22
  autoApprove: boolean;
23
23
  showDetailedLog: boolean;
24
+ inviteExpireDays: number;
24
25
  }
25
26
  export interface FrequencyConfig {
26
27
  enabled: boolean;
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
- "view-blacklist",
206
- "remove-from-blacklist",
207
- "add-to-blacklist",
208
- "clear-blacklist",
282
+ "banlist",
283
+ "unban",
284
+ "ban",
285
+ "clearban",
209
286
  "approve",
210
287
  "reject",
211
- "pending-invites"
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
- if (approvedGroups.has(guildId)) {
267
- approvedGroups.delete(guildId);
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
- const pendingInvites = /* @__PURE__ */ new Map();
401
- const INVITE_TIMEOUT = 10 * 60 * 1e3;
402
- setInterval(() => {
403
- const now = Date.now();
404
- for (const [key, invite] of pendingInvites) {
405
- if (now - invite.time > INVITE_TIMEOUT) {
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
- pendingInvites.set(rawGroupId, {
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>", "同意群聊邀请", { authority: 4 }).action(async ({ session }, groupId) => {
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 = pendingInvites.get(groupId);
582
+ const inviteData = await getPendingInvite(ctx, groupId);
503
583
  if (!inviteData) {
504
- return `未找到群号 ${groupId} 的待处理邀请。当前待处理邀请:${pendingInvites.size > 0 ? Array.from(pendingInvites.values()).map((i) => `${i.groupId}(${i.groupName})`).join(", ") : "无"}`;
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
- pendingInvites.delete(groupId);
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>", "拒绝群聊邀请", { authority: 4 }).action(async ({ session }, groupId) => {
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 = pendingInvites.get(groupId);
607
+ const inviteData = await getPendingInvite(ctx, groupId);
527
608
  if (!inviteData) {
528
- return `未找到群号 ${groupId} 的待处理邀请。当前待处理邀请:${pendingInvites.size > 0 ? Array.from(pendingInvites.values()).map((i) => `${i.groupId}(${i.groupName})`).join(", ") : "无"}`;
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
- pendingInvites.delete(groupId);
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-invites", "查看待处理的群聊邀请", { authority: 4 }).action(async ({ session }) => {
626
+ ctx.command("pending", "查看待处理的群聊邀请").action(async ({ session }) => {
545
627
  if (!config.invite.adminQQs.includes(session.userId)) {
546
628
  return "权限不足,只有管理员可以查看待处理邀请。";
547
629
  }
548
- if (pendingInvites.size === 0) {
630
+ const allInvites = await getAllPendingInvites(ctx);
631
+ if (allInvites.length === 0) {
549
632
  return "当前没有待处理的群聊邀请。";
550
633
  }
551
634
  const lines = ["待处理的群聊邀请列表:"];
552
- for (const [, invite] of pendingInvites) {
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("view-blacklist", "查看被拉黑的群聊列表", { authority: 4 }).action(viewBlacklist);
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("remove-from-blacklist <groupId:text>", "从黑名单移除指定群聊", { authority: 4 }).action(removeFromBlacklist);
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("add-to-blacklist <groupId:text>", "手动添加群聊到黑名单", { authority: 4 }).action(addToBlacklist);
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("clear-blacklist", "清空黑名单", { authority: 4 }).action(clearBlacklist);
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-group-control",
3
3
  "description": "Koishi 插件,一个多功能的群聊自管理工具。支持被踢出自动拉黑、刷屏自动屏蔽、开关控制等功能。(仅支持 OneBot 适配器)",
4
- "version": "0.2.10",
4
+ "version": "0.2.12",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [