@starhikari/koishi-plugin-group-whitelist 1.0.0 → 1.0.1
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 +26 -1
- package/lib/index.js +29 -5
- package/package.json +2 -1
- package/readme.md +30 -0
package/lib/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Context, Schema } from 'koishi';
|
|
1
|
+
import { Context, Session, Schema } from 'koishi';
|
|
2
2
|
export declare const name = "group-whitelist";
|
|
3
3
|
/**
|
|
4
4
|
* 数据库为可选依赖:
|
|
@@ -49,7 +49,32 @@ declare module 'koishi' {
|
|
|
49
49
|
interface Events {
|
|
50
50
|
/** 手动刷新白名单缓存(可选传入平台名,只刷新该平台) */
|
|
51
51
|
'group-whitelist/refresh'(platform?: string): void;
|
|
52
|
+
/**
|
|
53
|
+
* onebot 适配器把戳一戳、撤回、表情回应等通知类事件派发为 notice / onebot 事件。
|
|
54
|
+
* 适配器自身没有声明这些事件类型,这里补上声明,好让本插件能监听它们做拦截与日志。
|
|
55
|
+
*/
|
|
56
|
+
'notice'(session: Session): void;
|
|
57
|
+
'onebot'(session: Session): void;
|
|
52
58
|
}
|
|
59
|
+
interface Context {
|
|
60
|
+
/** 由本插件提供的群白名单服务,其他插件可用它判断某个会话是否被允许 */
|
|
61
|
+
groupWhitelist: WhitelistService;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 群白名单服务接口。
|
|
66
|
+
*
|
|
67
|
+
* 必须 **导出**:它被 `declare module 'koishi'` 里的 `Context` 增强引用,
|
|
68
|
+
* 若声明为模块内私有接口,tsc 会认为无法命名而在生成的 .d.ts 中**静默丢弃整个增强块**,
|
|
69
|
+
* 导致其他插件(如 bot-poke)编译时报 `Property 'groupWhitelist' does not exist on type 'Context'`。
|
|
70
|
+
*/
|
|
71
|
+
export interface WhitelistService {
|
|
72
|
+
/** 当前会话所在群是否在白名单内;私聊按 privateChat 策略判定 */
|
|
73
|
+
isAllowed(session: Session): boolean;
|
|
74
|
+
/** 直接按平台 + 群号判定 */
|
|
75
|
+
isAllowedGroup(platform: string, groupId: string): boolean;
|
|
76
|
+
/** 强制重新载入判定表 */
|
|
77
|
+
refresh(platform?: string): Promise<void>;
|
|
53
78
|
}
|
|
54
79
|
export interface GroupWhitelistEntry {
|
|
55
80
|
/** 平台名,如 onebot / qq */
|
package/lib/index.js
CHANGED
|
@@ -476,25 +476,34 @@ function apply(ctx, config) {
|
|
|
476
476
|
return "";
|
|
477
477
|
}
|
|
478
478
|
__name(resolveBlockSync, "resolveBlockSync");
|
|
479
|
-
|
|
480
|
-
for (const platform of new Set(ctx.bots.map((bot) => bot.platform))) {
|
|
481
|
-
await ensurePlatformLoaded(platform);
|
|
482
|
-
}
|
|
483
|
-
});
|
|
479
|
+
const GATED_EVENTS = /* @__PURE__ */ new Set(["message", "message-created", "notice", "onebot"]);
|
|
484
480
|
ctx.before("attach", (session) => {
|
|
485
481
|
if (!session.userId || !session.event) return;
|
|
486
482
|
if (!session.guildId) return;
|
|
483
|
+
if (!GATED_EVENTS.has(session.event.type)) return;
|
|
487
484
|
ensurePlatformLoaded(session.platform).catch((error) => {
|
|
488
485
|
logger.warn("载入白名单失败:%s", error instanceof Error ? error.message : error);
|
|
489
486
|
});
|
|
490
487
|
});
|
|
491
488
|
ctx.on("message", (session) => {
|
|
492
489
|
if (!session.userId || !session.event) return;
|
|
490
|
+
if (!GATED_EVENTS.has(session.event.type)) return;
|
|
493
491
|
const blocked = resolveBlockSync(session);
|
|
494
492
|
if (blocked === null) return;
|
|
495
493
|
blockedMap.set(session, blocked);
|
|
496
494
|
session.response = async () => blockedMap.get(session) ?? "";
|
|
497
495
|
}, { prepend: true });
|
|
496
|
+
ctx.on("notice", (session) => logBlockedEvent(session), { prepend: true });
|
|
497
|
+
ctx.on("onebot", (session) => logBlockedEvent(session), { prepend: true });
|
|
498
|
+
function logBlockedEvent(session) {
|
|
499
|
+
if (!session.userId || !session.event) return;
|
|
500
|
+
if (!session.guildId) return;
|
|
501
|
+
if (resolveBlockSync(session) === null) return;
|
|
502
|
+
if (config.enableLog) {
|
|
503
|
+
logger.debug("已拦截非白名单群的非消息事件:%s / %s / %s", session.platform, session.guildId, session.event.type);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
__name(logBlockedEvent, "logBlockedEvent");
|
|
498
507
|
const sample = ctx.bots[0]?.session({ type: "message" });
|
|
499
508
|
const prototype = sample ? Object.getPrototypeOf(sample) : null;
|
|
500
509
|
if (prototype && typeof prototype.execute === "function") {
|
|
@@ -705,6 +714,21 @@ function apply(ctx, config) {
|
|
|
705
714
|
logger.info("数据库服务已卸载,白名单回落到配置模式(fallbackGroups)");
|
|
706
715
|
});
|
|
707
716
|
});
|
|
717
|
+
const service = {
|
|
718
|
+
isAllowed(session) {
|
|
719
|
+
if (!session.guildId) {
|
|
720
|
+
if (config.privateChat === "all") return true;
|
|
721
|
+
if (config.privateChat === "whitelist") {
|
|
722
|
+
return !!session.userId && config.privateWhitelist.includes(session.userId);
|
|
723
|
+
}
|
|
724
|
+
return false;
|
|
725
|
+
}
|
|
726
|
+
return isGroupAllowedSync(session.platform, session.guildId);
|
|
727
|
+
},
|
|
728
|
+
isAllowedGroup: /* @__PURE__ */ __name((platform, groupId) => isGroupAllowedSync(platform, groupId), "isAllowedGroup"),
|
|
729
|
+
refresh
|
|
730
|
+
};
|
|
731
|
+
ctx.set("groupWhitelist", service);
|
|
708
732
|
async function refresh(platform) {
|
|
709
733
|
if (platform) {
|
|
710
734
|
platformLoaded.delete(platform);
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starhikari/koishi-plugin-group-whitelist",
|
|
3
3
|
"description": "实现koishi全局白名单,群聊不在白名单内时bot将不再处理该群的任何消息与指令",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
7
8
|
"files": [
|
|
8
9
|
"lib",
|
|
9
10
|
"dist"
|
package/readme.md
CHANGED
|
@@ -154,6 +154,36 @@ OneBot 的群消息事件里**没有群名**(事件只带 `group_id`),群
|
|
|
154
154
|
取不到名称时**保留原有值**,不会把已有数据清空;名称相同也不会产生多余的写库操作。
|
|
155
155
|
未注册数据库(配置模式)时没有可持久化的位置,群名改为列表展示时按需查询并缓存在内存中。
|
|
156
156
|
|
|
157
|
+
## 给其他插件用的服务
|
|
158
|
+
|
|
159
|
+
总闸能**自动**拦下的只有消息事件:`Processor.attach` 只挂在消息事件上,所以 `session.response`
|
|
160
|
+
这套机制对 notice / onebot 事件无效。必须自己查一下白名单:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
// 1) 声明可选依赖
|
|
164
|
+
export const inject = { optional: ['groupWhitelist'] }
|
|
165
|
+
|
|
166
|
+
// 2) tsconfig 里让类型可见(模块增强只有被引入才会生效)
|
|
167
|
+
// "types": ["node", "@starhikari/koishi-plugin-group-whitelist"]
|
|
168
|
+
|
|
169
|
+
// 3) 用可选链,未装白名单插件时自动退化为「不受限制」
|
|
170
|
+
ctx.on('notice', async (session) => {
|
|
171
|
+
if (!ctx.groupWhitelist?.isAllowed(session)) return
|
|
172
|
+
|
|
173
|
+
})
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
服务接口:
|
|
177
|
+
|
|
178
|
+
| 成员 | 说明 |
|
|
179
|
+
|------|------|
|
|
180
|
+
| `isAllowed(session)` | 当前会话所在群是否在白名单内;私聊按 `privateChat` 策略判定 |
|
|
181
|
+
| `isAllowedGroup(platform, groupId)` | 直接按平台 + 群号判定 |
|
|
182
|
+
| `refresh(platform?)` | 强制重新载入判定表 |
|
|
183
|
+
|
|
184
|
+
**总闸覆盖的事件类型**:`message`、`notice`、`onebot`。入群、好友请求等管理类事件不在其中,
|
|
185
|
+
否则入群提示、加好友审核会被误伤。
|
|
186
|
+
|
|
157
187
|
## 权限模型
|
|
158
188
|
|
|
159
189
|
管理指令的裁决**完全由插件自己完成**(`ensureAdmin`),Koishi 内置的 `authority` 权限被刻意设为 0
|