@zhin.js/adapter-kook 7.0.3 → 7.0.5
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/CHANGELOG.md +79 -0
- package/adapters/kook.js +2 -2
- package/adapters/kook.ts +2 -2
- package/lib/endpoint.js +35 -24
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/kook-agent-deps.d.ts +2 -2
- package/lib/kook-agent-deps.js +7 -7
- package/lib/platform-permit.d.ts +2 -3
- package/lib/platform-permit.js +3 -20
- package/lib/protocol.d.ts +5 -5
- package/lib/protocol.js +6 -6
- package/package.json +17 -16
- package/plugin.js +6 -4
- package/schema.json +41 -5
- package/src/endpoint.ts +37 -25
- package/src/index.ts +0 -1
- package/src/kook-agent-deps.ts +8 -8
- package/src/platform-permit.ts +4 -15
- package/src/protocol.ts +10 -10
- /package/commands/endpoint/add/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/add/{[name].ts → [id].ts} +0 -0
- /package/commands/endpoint/remove/{[name].js → [id].js} +0 -0
- /package/commands/endpoint/remove/{[name].ts → [id].ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,84 @@
|
|
|
1
1
|
# @zhin.js/adapter-kook
|
|
2
2
|
|
|
3
|
+
## 7.0.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 51015d6: refactor(adapters): migrate platform-permit to PermissionSubject
|
|
8
|
+
|
|
9
|
+
All adapter platform-permit checkers now accept PermissionSubject
|
|
10
|
+
(duck-typed from Message/CommandSession) instead of Message directly.
|
|
11
|
+
registerPlatformPermitChecker is replaced by host.registerPlatform in
|
|
12
|
+
the adapter plugin setup. activity-feedback service updated for new
|
|
13
|
+
PermissionHost integration.
|
|
14
|
+
|
|
15
|
+
- Updated dependencies [6f9c366]
|
|
16
|
+
- Updated dependencies [373a56b]
|
|
17
|
+
- Updated dependencies [0de46a8]
|
|
18
|
+
- Updated dependencies [c106ecc]
|
|
19
|
+
- Updated dependencies [ca92e03]
|
|
20
|
+
- Updated dependencies [b0f37ae]
|
|
21
|
+
- Updated dependencies [ba08a2f]
|
|
22
|
+
- Updated dependencies [b08f7fe]
|
|
23
|
+
- Updated dependencies [daffd4c]
|
|
24
|
+
- Updated dependencies [36c7400]
|
|
25
|
+
- Updated dependencies [a9fa72e]
|
|
26
|
+
- Updated dependencies [c8de3ef]
|
|
27
|
+
- Updated dependencies [60f0fc8]
|
|
28
|
+
- Updated dependencies [574c990]
|
|
29
|
+
- Updated dependencies [d096f16]
|
|
30
|
+
- Updated dependencies [3f29623]
|
|
31
|
+
- Updated dependencies [2916852]
|
|
32
|
+
- Updated dependencies [d047869]
|
|
33
|
+
- Updated dependencies [162fa34]
|
|
34
|
+
- Updated dependencies [e62561e]
|
|
35
|
+
- Updated dependencies [3eeeb46]
|
|
36
|
+
- Updated dependencies [85d0f82]
|
|
37
|
+
- Updated dependencies [61bfc1c]
|
|
38
|
+
- Updated dependencies [04bad47]
|
|
39
|
+
- Updated dependencies [e40b048]
|
|
40
|
+
- Updated dependencies [5a5b1bb]
|
|
41
|
+
- Updated dependencies [f1708c3]
|
|
42
|
+
- Updated dependencies [d254a81]
|
|
43
|
+
- Updated dependencies [7123c47]
|
|
44
|
+
- Updated dependencies [05befc1]
|
|
45
|
+
- Updated dependencies [0663b6a]
|
|
46
|
+
- Updated dependencies [f28f9b3]
|
|
47
|
+
- Updated dependencies [9f340f7]
|
|
48
|
+
- Updated dependencies [e53444f]
|
|
49
|
+
- Updated dependencies [5eedd26]
|
|
50
|
+
- Updated dependencies [92b0dd7]
|
|
51
|
+
- Updated dependencies [f919b6f]
|
|
52
|
+
- Updated dependencies [098e411]
|
|
53
|
+
- Updated dependencies [e1b7c01]
|
|
54
|
+
- Updated dependencies [9b94f87]
|
|
55
|
+
- Updated dependencies [a7df753]
|
|
56
|
+
- @zhin.js/agent@1.1.5
|
|
57
|
+
- @zhin.js/host-http@1.0.8
|
|
58
|
+
- @zhin.js/permission@1.0.1
|
|
59
|
+
- @zhin.js/im-contract@1.0.3
|
|
60
|
+
- @zhin.js/adapter@1.1.7
|
|
61
|
+
- @zhin.js/plugin-runtime@1.1.5
|
|
62
|
+
- @zhin.js/command@1.0.9
|
|
63
|
+
- @zhin.js/core@1.5.4
|
|
64
|
+
- zhin.js@6.0.4
|
|
65
|
+
|
|
66
|
+
## 7.0.4
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- f8c7a54: fix: im
|
|
71
|
+
- Updated dependencies [f8c7a54]
|
|
72
|
+
- @zhin.js/logger@1.0.76
|
|
73
|
+
- @zhin.js/host-http@1.0.7
|
|
74
|
+
- @zhin.js/adapter@1.1.6
|
|
75
|
+
- @zhin.js/agent@1.1.4
|
|
76
|
+
- @zhin.js/command@1.0.8
|
|
77
|
+
- @zhin.js/core@1.5.3
|
|
78
|
+
- @zhin.js/im-contract@1.0.2
|
|
79
|
+
- @zhin.js/plugin-runtime@1.1.4
|
|
80
|
+
- zhin.js@6.0.3
|
|
81
|
+
|
|
3
82
|
## 7.0.3
|
|
4
83
|
|
|
5
84
|
### Patch Changes
|
package/adapters/kook.js
CHANGED
|
@@ -21,8 +21,8 @@ export default defineAdapter({
|
|
|
21
21
|
const config = resolveKookConfig(context.config);
|
|
22
22
|
const gateway = context.use(messageGatewayToken);
|
|
23
23
|
// 注册到插件运行时状态(kook.endpoint list 的"运行中"数据源)
|
|
24
|
-
context.use(kookRuntimeStateToken).endpoints.set(config.
|
|
25
|
-
|
|
24
|
+
context.use(kookRuntimeStateToken).endpoints.set(config.id, {
|
|
25
|
+
id: config.id,
|
|
26
26
|
mode: config.connection,
|
|
27
27
|
});
|
|
28
28
|
if (config.connection === 'webhook') {
|
package/adapters/kook.ts
CHANGED
|
@@ -36,8 +36,8 @@ export default defineAdapter<KookAdapterConfig>({
|
|
|
36
36
|
const config = resolveKookConfig(context.config);
|
|
37
37
|
const gateway = context.use(messageGatewayToken);
|
|
38
38
|
// 注册到插件运行时状态(kook.endpoint list 的"运行中"数据源)
|
|
39
|
-
context.use(kookRuntimeStateToken).endpoints.set(config.
|
|
40
|
-
|
|
39
|
+
context.use(kookRuntimeStateToken).endpoints.set(config.id, {
|
|
40
|
+
id: config.id,
|
|
41
41
|
mode: config.connection,
|
|
42
42
|
});
|
|
43
43
|
if (config.connection === 'webhook') {
|
package/lib/endpoint.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { formatCompact,
|
|
1
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
2
2
|
import { registerKookAgentEndpoint } from './kook-agent-deps.js';
|
|
3
3
|
import { formatInboundContent, formatOutboundKmarkdown, isKookBotMentioned, kookInboundConversation, senderDisplayName, } from './protocol.js';
|
|
4
4
|
import { registerKookWebhookRoutes } from './webhook.js';
|
|
5
5
|
import { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, } from './ws.js';
|
|
6
|
-
const logger = getLogger('kook');
|
|
7
6
|
export class KookWebsocketEndpoint {
|
|
7
|
+
#logger;
|
|
8
8
|
#options;
|
|
9
9
|
#createClient;
|
|
10
10
|
#client = null;
|
|
@@ -13,6 +13,7 @@ export class KookWebsocketEndpoint {
|
|
|
13
13
|
#unregisterAgent;
|
|
14
14
|
management = createKookEndpointManagement(() => this.#requireClient());
|
|
15
15
|
constructor(options) {
|
|
16
|
+
this.#logger = getAdapterLogger('kook', options.config.id);
|
|
16
17
|
this.#options = options;
|
|
17
18
|
this.#createClient = options.createClient ?? defaultCreateClient;
|
|
18
19
|
}
|
|
@@ -21,20 +22,20 @@ export class KookWebsocketEndpoint {
|
|
|
21
22
|
return;
|
|
22
23
|
this.#started = true;
|
|
23
24
|
try {
|
|
24
|
-
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.
|
|
25
|
+
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
|
|
25
26
|
this.#client = this.#createClient(this.#options.config);
|
|
26
27
|
this.#bindClient(this.#client);
|
|
27
28
|
await this.#client.connect();
|
|
28
|
-
logger.info(formatCompact({
|
|
29
|
+
this.#logger.info(formatCompact({
|
|
29
30
|
op: 'connect',
|
|
30
|
-
endpoint: this.#options.config.
|
|
31
|
+
endpoint: this.#options.config.id,
|
|
31
32
|
mode: 'websocket',
|
|
32
33
|
self_id: this.#client.self_id != null ? String(this.#client.self_id) : undefined,
|
|
33
34
|
}));
|
|
34
35
|
}
|
|
35
36
|
catch (error) {
|
|
36
37
|
await this.stop();
|
|
37
|
-
logger.error('Failed to connect KOOK websocket:', error);
|
|
38
|
+
this.#logger.error('Failed to connect KOOK websocket:', error);
|
|
38
39
|
throw error;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
@@ -59,7 +60,7 @@ export class KookWebsocketEndpoint {
|
|
|
59
60
|
this.#client = null;
|
|
60
61
|
}
|
|
61
62
|
this.#started = false;
|
|
62
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
63
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
63
64
|
}
|
|
64
65
|
async send({ conversation, payload }) {
|
|
65
66
|
const body = formatOutboundKmarkdown(payload);
|
|
@@ -68,9 +69,9 @@ export class KookWebsocketEndpoint {
|
|
|
68
69
|
? await client.sendPrivateMsg(conversation.id, body)
|
|
69
70
|
: await client.sendChannelMsg(conversation.id, body);
|
|
70
71
|
const messageId = result?.msg_id != null ? String(result.msg_id) : '';
|
|
71
|
-
logger.debug(formatCompact({
|
|
72
|
+
this.#logger.debug(formatCompact({
|
|
72
73
|
op: 'kook_send',
|
|
73
|
-
endpoint: this.#options.config.
|
|
74
|
+
endpoint: this.#options.config.id,
|
|
74
75
|
target: `${conversation.kind}:${conversation.id}`,
|
|
75
76
|
messageId,
|
|
76
77
|
}));
|
|
@@ -88,17 +89,21 @@ export class KookWebsocketEndpoint {
|
|
|
88
89
|
conversation,
|
|
89
90
|
message: { conversation, id: msg.id },
|
|
90
91
|
content: formatInboundContent(msg),
|
|
91
|
-
sender:
|
|
92
|
+
sender: {
|
|
93
|
+
id: msg.authorId,
|
|
94
|
+
name: senderDisplayName(msg) || undefined,
|
|
95
|
+
...(msg.authorRoles?.length ? { roles: msg.authorRoles.map(String) } : {}),
|
|
96
|
+
},
|
|
97
|
+
endpointId: this.#options.config.id,
|
|
98
|
+
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
92
99
|
metadata: Object.freeze({
|
|
93
|
-
endpoint: this.#options.config.name,
|
|
94
100
|
channelKind: msg.channelKind,
|
|
95
101
|
userId: msg.authorId,
|
|
96
102
|
guildId: msg.guildId,
|
|
97
103
|
roles: msg.authorRoles,
|
|
98
|
-
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
99
104
|
}),
|
|
100
105
|
}).catch((err) => {
|
|
101
|
-
logger.warn(formatCompact({
|
|
106
|
+
this.#logger.warn(formatCompact({
|
|
102
107
|
op: 'kook_gateway_receive_failed',
|
|
103
108
|
target: `${conversation.kind}:${conversation.id}`,
|
|
104
109
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -146,6 +151,7 @@ export class KookWebsocketEndpoint {
|
|
|
146
151
|
}
|
|
147
152
|
}
|
|
148
153
|
export class KookWebhookEndpoint {
|
|
154
|
+
#logger;
|
|
149
155
|
#options;
|
|
150
156
|
#createClient;
|
|
151
157
|
#client = null;
|
|
@@ -156,6 +162,7 @@ export class KookWebhookEndpoint {
|
|
|
156
162
|
#unregisterAgent;
|
|
157
163
|
management = createKookEndpointManagement(() => this.#requireClient());
|
|
158
164
|
constructor(options) {
|
|
165
|
+
this.#logger = getAdapterLogger('kook', options.config.id);
|
|
159
166
|
this.#options = options;
|
|
160
167
|
this.#createClient = options.createClient ?? defaultCreateWebhookClient;
|
|
161
168
|
}
|
|
@@ -174,13 +181,13 @@ export class KookWebhookEndpoint {
|
|
|
174
181
|
return;
|
|
175
182
|
this.#started = true;
|
|
176
183
|
try {
|
|
177
|
-
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.
|
|
184
|
+
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
|
|
178
185
|
this.#client = this.#createClient(this.#options.config);
|
|
179
186
|
await this.#client.init();
|
|
180
187
|
this.#routeReleases.push(...registerKookWebhookRoutes(this.#options.http, this));
|
|
181
|
-
logger.info(formatCompact({
|
|
188
|
+
this.#logger.info(formatCompact({
|
|
182
189
|
op: 'connect',
|
|
183
|
-
endpoint: this.#options.config.
|
|
190
|
+
endpoint: this.#options.config.id,
|
|
184
191
|
mode: 'webhook',
|
|
185
192
|
path: this.#options.config.webhookPath,
|
|
186
193
|
self_id: this.#client.self_id != null ? String(this.#client.self_id) : undefined,
|
|
@@ -188,7 +195,7 @@ export class KookWebhookEndpoint {
|
|
|
188
195
|
}
|
|
189
196
|
catch (error) {
|
|
190
197
|
await this.stop();
|
|
191
|
-
logger.error('Failed to connect KOOK webhook:', error);
|
|
198
|
+
this.#logger.error('Failed to connect KOOK webhook:', error);
|
|
192
199
|
throw error;
|
|
193
200
|
}
|
|
194
201
|
}
|
|
@@ -216,7 +223,7 @@ export class KookWebhookEndpoint {
|
|
|
216
223
|
this.#client = null;
|
|
217
224
|
}
|
|
218
225
|
this.#started = false;
|
|
219
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
226
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
220
227
|
}
|
|
221
228
|
async send({ conversation, payload }) {
|
|
222
229
|
const body = formatOutboundKmarkdown(payload);
|
|
@@ -225,9 +232,9 @@ export class KookWebhookEndpoint {
|
|
|
225
232
|
? await client.sendPrivateMsg(conversation.id, body)
|
|
226
233
|
: await client.sendChannelMsg(conversation.id, body);
|
|
227
234
|
const messageId = result?.msg_id != null ? String(result.msg_id) : '';
|
|
228
|
-
logger.debug(formatCompact({
|
|
235
|
+
this.#logger.debug(formatCompact({
|
|
229
236
|
op: 'kook_send',
|
|
230
|
-
endpoint: this.#options.config.
|
|
237
|
+
endpoint: this.#options.config.id,
|
|
231
238
|
target: `${conversation.kind}:${conversation.id}`,
|
|
232
239
|
messageId,
|
|
233
240
|
}));
|
|
@@ -245,17 +252,21 @@ export class KookWebhookEndpoint {
|
|
|
245
252
|
conversation,
|
|
246
253
|
message: { conversation, id: msg.id },
|
|
247
254
|
content: formatInboundContent(msg),
|
|
248
|
-
sender:
|
|
255
|
+
sender: {
|
|
256
|
+
id: msg.authorId,
|
|
257
|
+
name: senderDisplayName(msg) || undefined,
|
|
258
|
+
...(msg.authorRoles?.length ? { roles: msg.authorRoles.map(String) } : {}),
|
|
259
|
+
},
|
|
260
|
+
endpointId: this.#options.config.id,
|
|
261
|
+
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
249
262
|
metadata: Object.freeze({
|
|
250
|
-
endpoint: this.#options.config.name,
|
|
251
263
|
channelKind: msg.channelKind,
|
|
252
264
|
userId: msg.authorId,
|
|
253
265
|
guildId: msg.guildId,
|
|
254
266
|
roles: msg.authorRoles,
|
|
255
|
-
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
256
267
|
}),
|
|
257
268
|
}).catch((err) => {
|
|
258
|
-
logger.warn(formatCompact({
|
|
269
|
+
this.#logger.warn(formatCompact({
|
|
259
270
|
op: 'kook_gateway_receive_failed',
|
|
260
271
|
target: `${conversation.kind}:${conversation.id}`,
|
|
261
272
|
error: err instanceof Error ? err.message : String(err),
|
package/lib/index.d.ts
CHANGED
|
@@ -3,4 +3,4 @@ export { KookWebhookEndpoint, KookWebsocketEndpoint, type KookEndpointOptions, t
|
|
|
3
3
|
export { registerKookWebhookRoutes, handleKookWebhookRequest, type KookWebhookHandler, } from './webhook.js';
|
|
4
4
|
export { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, type CreateKookClient, type KookClientTransport, } from './ws.js';
|
|
5
5
|
export { getKookAgentDeps, registerKookAgentEndpoint, setKookAgentDeps, type KookAgentDeps, type KookAgentEndpoint, } from './kook-agent-deps.js';
|
|
6
|
-
export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit,
|
|
6
|
+
export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, type KookSenderInfo, } from './platform-permit.js';
|
package/lib/index.js
CHANGED
|
@@ -3,4 +3,4 @@ export { KookWebhookEndpoint, KookWebsocketEndpoint, } from './endpoint.js';
|
|
|
3
3
|
export { registerKookWebhookRoutes, handleKookWebhookRequest, } from './webhook.js';
|
|
4
4
|
export { defaultCreateClient, defaultCreateWebhookClient, normalizeKookMessage, } from './ws.js';
|
|
5
5
|
export { getKookAgentDeps, registerKookAgentEndpoint, setKookAgentDeps, } from './kook-agent-deps.js';
|
|
6
|
-
export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit,
|
|
6
|
+
export { checkKookPlatformPermit, kookGroupPermitResolver, normalizeKookSenderForPermit, platformPermit, } from './platform-permit.js';
|
package/lib/kook-agent-deps.d.ts
CHANGED
|
@@ -21,9 +21,9 @@ export interface KookAgentEndpoint {
|
|
|
21
21
|
removeFromBlacklist(guildId: string, userId: string): Promise<boolean>;
|
|
22
22
|
}
|
|
23
23
|
export interface KookAgentDeps {
|
|
24
|
-
getEndpoint: (
|
|
24
|
+
getEndpoint: (endpointKey: string) => KookAgentEndpoint;
|
|
25
25
|
}
|
|
26
|
-
export declare function registerKookAgentEndpoint(
|
|
26
|
+
export declare function registerKookAgentEndpoint(endpointKey: string, endpoint: KookAgentEndpoint): () => void;
|
|
27
27
|
/** Optional override used by tests / transitional callers. Pass `null` to clear. */
|
|
28
28
|
export declare function setKookAgentDeps(deps: KookAgentDeps | null): void;
|
|
29
29
|
export declare function getKookAgentDeps(): KookAgentDeps;
|
package/lib/kook-agent-deps.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const endpoints = new Map();
|
|
6
6
|
let override = null;
|
|
7
|
-
export function registerKookAgentEndpoint(
|
|
8
|
-
endpoints.set(
|
|
7
|
+
export function registerKookAgentEndpoint(endpointKey, endpoint) {
|
|
8
|
+
endpoints.set(endpointKey, endpoint);
|
|
9
9
|
return () => {
|
|
10
|
-
if (endpoints.get(
|
|
11
|
-
endpoints.delete(
|
|
10
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
11
|
+
endpoints.delete(endpointKey);
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
}
|
|
@@ -20,10 +20,10 @@ export function getKookAgentDeps() {
|
|
|
20
20
|
if (override)
|
|
21
21
|
return override;
|
|
22
22
|
return {
|
|
23
|
-
getEndpoint(
|
|
24
|
-
const registered = endpoints.get(
|
|
23
|
+
getEndpoint(endpointKey) {
|
|
24
|
+
const registered = endpoints.get(endpointKey);
|
|
25
25
|
if (!registered)
|
|
26
|
-
throw new Error(`Endpoint ${
|
|
26
|
+
throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
27
27
|
return registered;
|
|
28
28
|
},
|
|
29
29
|
};
|
package/lib/platform-permit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* KOOK platform permit — guild / channel 差异化门禁
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
import { KookPermission } from './protocol.js';
|
|
6
6
|
export declare function platformPermit(perm: string): string;
|
|
7
7
|
export declare function kookGroupPermitResolver(logicalPerm: string): string;
|
|
@@ -19,5 +19,4 @@ export declare function normalizeKookSenderForPermit(info: KookSenderInfo, isCha
|
|
|
19
19
|
role?: string;
|
|
20
20
|
permissions?: string[];
|
|
21
21
|
};
|
|
22
|
-
export declare function checkKookPlatformPermit(perm: string,
|
|
23
|
-
export declare function registerKookPlatformPermitChecker(): () => void;
|
|
22
|
+
export declare function checkKookPlatformPermit(perm: string, subject: PermissionSubject): boolean;
|
package/lib/platform-permit.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* KOOK platform permit — guild / channel 差异化门禁
|
|
3
|
-
*/
|
|
4
|
-
import { registerPlatformPermitChecker } from '@zhin.js/core';
|
|
5
1
|
import { KookPermission } from './protocol.js';
|
|
6
2
|
const ADAPTER = 'kook';
|
|
7
3
|
export function platformPermit(perm) {
|
|
@@ -33,19 +29,9 @@ export function normalizeKookSenderForPermit(info, isChannel) {
|
|
|
33
29
|
}
|
|
34
30
|
return { role: 'member', permissions };
|
|
35
31
|
}
|
|
36
|
-
function
|
|
37
|
-
const
|
|
38
|
-
const permissions =
|
|
39
|
-
if (sender.isGuildOwner)
|
|
40
|
-
permissions.push('guild_owner');
|
|
41
|
-
if (sender.isAdmin)
|
|
42
|
-
permissions.push('guild_admin');
|
|
43
|
-
if (sender.permission === KookPermission.ChannelAdmin)
|
|
44
|
-
permissions.push('channel_admin');
|
|
45
|
-
return { role: sender.role, permissions };
|
|
46
|
-
}
|
|
47
|
-
export function checkKookPlatformPermit(perm, message) {
|
|
48
|
-
const { role, permissions } = senderPermits(message);
|
|
32
|
+
export function checkKookPlatformPermit(perm, subject) {
|
|
33
|
+
const role = subject.sender?.role?.[0];
|
|
34
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
49
35
|
const has = (t) => permissions.includes(t);
|
|
50
36
|
switch (perm) {
|
|
51
37
|
case 'guild_owner':
|
|
@@ -60,6 +46,3 @@ export function checkKookPlatformPermit(perm, message) {
|
|
|
60
46
|
return false;
|
|
61
47
|
}
|
|
62
48
|
}
|
|
63
|
-
export function registerKookPlatformPermitChecker() {
|
|
64
|
-
return registerPlatformPermitChecker(ADAPTER, checkKookPlatformPermit);
|
|
65
|
-
}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare enum KookPermission {
|
|
|
13
13
|
}
|
|
14
14
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
15
15
|
export interface KookAdapterConfig {
|
|
16
|
-
readonly
|
|
16
|
+
readonly id?: string;
|
|
17
17
|
readonly token?: string;
|
|
18
18
|
/** Default `websocket`. `webhook` requires httpHostToken + verify_token. */
|
|
19
19
|
readonly connection?: 'websocket' | 'webhook';
|
|
@@ -28,7 +28,7 @@ export interface KookAdapterConfig {
|
|
|
28
28
|
/** Transitional: legacy root `endpoints[]` with `context: kook`. */
|
|
29
29
|
readonly endpoints?: ReadonlyArray<{
|
|
30
30
|
readonly context?: string;
|
|
31
|
-
readonly
|
|
31
|
+
readonly id?: string;
|
|
32
32
|
readonly token?: string;
|
|
33
33
|
readonly connection?: 'websocket' | 'webhook';
|
|
34
34
|
readonly webhookPath?: string;
|
|
@@ -44,7 +44,7 @@ export interface KookAdapterConfig {
|
|
|
44
44
|
export interface ResolvedKookWebsocketConfig {
|
|
45
45
|
readonly context: 'kook';
|
|
46
46
|
readonly connection: 'websocket';
|
|
47
|
-
readonly
|
|
47
|
+
readonly id: string;
|
|
48
48
|
readonly token: string;
|
|
49
49
|
readonly data_dir?: string;
|
|
50
50
|
readonly timeout: number;
|
|
@@ -55,7 +55,7 @@ export interface ResolvedKookWebsocketConfig {
|
|
|
55
55
|
export interface ResolvedKookWebhookConfig {
|
|
56
56
|
readonly context: 'kook';
|
|
57
57
|
readonly connection: 'webhook';
|
|
58
|
-
readonly
|
|
58
|
+
readonly id: string;
|
|
59
59
|
readonly token: string;
|
|
60
60
|
readonly webhookPath: string;
|
|
61
61
|
readonly verifyToken: string;
|
|
@@ -112,7 +112,7 @@ export declare function resolveKookConfig(config?: KookAdapterConfig): ResolvedK
|
|
|
112
112
|
* 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
|
|
113
113
|
* 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
|
|
114
114
|
*/
|
|
115
|
-
export declare function kookInboundConversation(
|
|
115
|
+
export declare function kookInboundConversation(endpointKey: string, msg: KookInboundMessage): ConversationRef;
|
|
116
116
|
export declare function senderDisplayName(msg: KookInboundMessage): string;
|
|
117
117
|
/** Build inbound text for MessageGateway.receive */
|
|
118
118
|
export declare function formatInboundContent(msg: KookInboundMessage): string;
|
package/lib/protocol.js
CHANGED
|
@@ -21,8 +21,8 @@ export function resolveKookConfig(config = {}) {
|
|
|
21
21
|
if (!token) {
|
|
22
22
|
throw new TypeError('KOOK adapter requires token (plugins.<key>.token or endpoints with context: kook)');
|
|
23
23
|
}
|
|
24
|
-
const
|
|
25
|
-
|| (typeof entry?.
|
|
24
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
25
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
26
26
|
|| process.env.KOOK_BOT_NAME
|
|
27
27
|
|| 'kook-bot';
|
|
28
28
|
const connection = config.connection
|
|
@@ -40,7 +40,7 @@ export function resolveKookConfig(config = {}) {
|
|
|
40
40
|
return {
|
|
41
41
|
context: 'kook',
|
|
42
42
|
connection: 'webhook',
|
|
43
|
-
|
|
43
|
+
id,
|
|
44
44
|
token,
|
|
45
45
|
webhookPath: normalizeWebhookPath(config.webhookPath ?? entry?.webhookPath ?? process.env.KOOK_WEBHOOK_PATH ?? '/kook/webhook'),
|
|
46
46
|
verifyToken,
|
|
@@ -52,7 +52,7 @@ export function resolveKookConfig(config = {}) {
|
|
|
52
52
|
return {
|
|
53
53
|
context: 'kook',
|
|
54
54
|
connection: 'websocket',
|
|
55
|
-
|
|
55
|
+
id,
|
|
56
56
|
token,
|
|
57
57
|
data_dir: config.data_dir ?? entry?.data_dir,
|
|
58
58
|
timeout: config.timeout ?? entry?.timeout ?? 10_000,
|
|
@@ -65,9 +65,9 @@ export function resolveKookConfig(config = {}) {
|
|
|
65
65
|
* 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
|
|
66
66
|
* 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
|
|
67
67
|
*/
|
|
68
|
-
export function kookInboundConversation(
|
|
68
|
+
export function kookInboundConversation(endpointKey, msg) {
|
|
69
69
|
return {
|
|
70
|
-
endpoint: { id:
|
|
70
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
71
71
|
kind: msg.channelKind,
|
|
72
72
|
id: msg.channelId,
|
|
73
73
|
...(msg.guildId && msg.channelKind === 'channel'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-kook",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.5",
|
|
4
4
|
"description": "Zhin.js KOOK adapter for Plugin Runtime (WebSocket gateway or Webhook)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -34,21 +34,22 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"kook-client": "^1.0.4",
|
|
37
|
-
"@zhin.js/adapter": "1.1.
|
|
38
|
-
"@zhin.js/command": "1.0.
|
|
39
|
-
"@zhin.js/core": "1.5.
|
|
40
|
-
"@zhin.js/host-http": "1.0.
|
|
41
|
-
"@zhin.js/im-contract": "1.0.
|
|
42
|
-
"@zhin.js/logger": "1.0.
|
|
43
|
-
"@zhin.js/
|
|
37
|
+
"@zhin.js/adapter": "1.1.7",
|
|
38
|
+
"@zhin.js/command": "1.0.9",
|
|
39
|
+
"@zhin.js/core": "1.5.4",
|
|
40
|
+
"@zhin.js/host-http": "1.0.8",
|
|
41
|
+
"@zhin.js/im-contract": "1.0.3",
|
|
42
|
+
"@zhin.js/logger": "1.0.76",
|
|
43
|
+
"@zhin.js/permission": "1.0.1",
|
|
44
|
+
"@zhin.js/plugin-runtime": "1.1.5"
|
|
44
45
|
},
|
|
45
46
|
"peerDependencies": {
|
|
46
47
|
"zod": "^4.0.0",
|
|
47
|
-
"@zhin.js/adapter": "1.1.
|
|
48
|
-
"@zhin.js/agent": "1.1.
|
|
49
|
-
"@zhin.js/core": "1.5.
|
|
50
|
-
"@zhin.js/plugin-runtime": "1.1.
|
|
51
|
-
"zhin.js": "6.0.
|
|
48
|
+
"@zhin.js/adapter": "1.1.7",
|
|
49
|
+
"@zhin.js/agent": "1.1.5",
|
|
50
|
+
"@zhin.js/core": "1.5.4",
|
|
51
|
+
"@zhin.js/plugin-runtime": "1.1.5",
|
|
52
|
+
"zhin.js": "6.0.4"
|
|
52
53
|
},
|
|
53
54
|
"peerDependenciesMeta": {
|
|
54
55
|
"zhin.js": {
|
|
@@ -66,9 +67,9 @@
|
|
|
66
67
|
"typescript": "^6.0.3",
|
|
67
68
|
"vitest": "^4.1.10",
|
|
68
69
|
"zod": "^4.4.3",
|
|
69
|
-
"@zhin.js/agent": "1.1.
|
|
70
|
-
"@zhin.js/host-http": "1.0.
|
|
71
|
-
"zhin.js": "6.0.
|
|
70
|
+
"@zhin.js/agent": "1.1.5",
|
|
71
|
+
"@zhin.js/host-http": "1.0.8",
|
|
72
|
+
"zhin.js": "6.0.4"
|
|
72
73
|
},
|
|
73
74
|
"files": [
|
|
74
75
|
"adapters",
|
package/plugin.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { createEndpointRuntimeState } from '@zhin.js/adapter';
|
|
3
3
|
import { definePlugin } from '@zhin.js/plugin-runtime';
|
|
4
|
-
import {
|
|
4
|
+
import { permissionHostToken } from '@zhin.js/permission';
|
|
5
|
+
import { checkKookPlatformPermit } from "./lib/platform-permit.js";
|
|
5
6
|
import { kookRuntimeStateToken } from "./lib/kook-runtime-state.js";
|
|
6
7
|
export default definePlugin({
|
|
7
8
|
name: 'kook',
|
|
@@ -9,9 +10,10 @@ export default definePlugin({
|
|
|
9
10
|
displayName: 'KOOK WebSocket Adapter',
|
|
10
11
|
},
|
|
11
12
|
setup(context) {
|
|
12
|
-
// 运行中 endpoint 注册表(kook.endpoint list 的"运行中"数据源)
|
|
13
13
|
context.resources.provide(kookRuntimeStateToken, createEndpointRuntimeState());
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
if (context.resources.has(permissionHostToken)) {
|
|
15
|
+
const host = context.resources.use(permissionHostToken);
|
|
16
|
+
return host.registerPlatform('kook', checkKookPlatformPermit);
|
|
17
|
+
}
|
|
16
18
|
},
|
|
17
19
|
});
|
package/schema.json
CHANGED
|
@@ -50,16 +50,48 @@
|
|
|
50
50
|
],
|
|
51
51
|
"default": "info"
|
|
52
52
|
},
|
|
53
|
+
"master": {
|
|
54
|
+
"type": [
|
|
55
|
+
"string",
|
|
56
|
+
"number"
|
|
57
|
+
],
|
|
58
|
+
"description": "框架 master(KOOK user id;AI/工具权限、endpoint 管理)。endpoints[i].master 可逐项覆盖"
|
|
59
|
+
},
|
|
60
|
+
"trusted": {
|
|
61
|
+
"type": "array",
|
|
62
|
+
"items": {
|
|
63
|
+
"type": [
|
|
64
|
+
"string",
|
|
65
|
+
"number"
|
|
66
|
+
],
|
|
67
|
+
"description": "Trusted KOOK user id"
|
|
68
|
+
},
|
|
69
|
+
"description": "框架 trusted 用户列表(弱于 master)。endpoints[i].trusted 可逐项追加"
|
|
70
|
+
},
|
|
53
71
|
"endpoints": {
|
|
54
72
|
"type": "array",
|
|
55
|
-
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(
|
|
73
|
+
"description": "多账号:一个插件实例挂多个 endpoint。每项与顶层字段同构(id 必填,其余覆盖顶层)",
|
|
56
74
|
"items": {
|
|
57
75
|
"type": "object",
|
|
58
76
|
"additionalProperties": true,
|
|
59
77
|
"properties": {
|
|
60
|
-
"
|
|
61
|
-
"type":
|
|
62
|
-
|
|
78
|
+
"master": {
|
|
79
|
+
"type": [
|
|
80
|
+
"string",
|
|
81
|
+
"number"
|
|
82
|
+
],
|
|
83
|
+
"description": "本 endpoint 的框架 master(KOOK user id);覆盖顶层 master"
|
|
84
|
+
},
|
|
85
|
+
"trusted": {
|
|
86
|
+
"type": "array",
|
|
87
|
+
"items": {
|
|
88
|
+
"type": [
|
|
89
|
+
"string",
|
|
90
|
+
"number"
|
|
91
|
+
],
|
|
92
|
+
"description": "Trusted KOOK user id"
|
|
93
|
+
},
|
|
94
|
+
"description": "本 endpoint 的 trusted 列表"
|
|
63
95
|
},
|
|
64
96
|
"token": {
|
|
65
97
|
"type": "string",
|
|
@@ -72,10 +104,14 @@
|
|
|
72
104
|
"encrypt_key": {
|
|
73
105
|
"type": "string",
|
|
74
106
|
"description": "Optional Encrypt Key when message encryption is enabled in KOOK console."
|
|
107
|
+
},
|
|
108
|
+
"id": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"description": "KOOK bot name"
|
|
75
111
|
}
|
|
76
112
|
},
|
|
77
113
|
"required": [
|
|
78
|
-
"
|
|
114
|
+
"id",
|
|
79
115
|
"token"
|
|
80
116
|
]
|
|
81
117
|
}
|
package/src/endpoint.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
} from '@zhin.js/adapter';
|
|
12
12
|
import type { MessageGateway } from '@zhin.js/core/runtime';
|
|
13
13
|
import type { HttpHost, HttpRouteRegistration } from '@zhin.js/host-http';
|
|
14
|
-
import { formatCompact,
|
|
14
|
+
import { formatCompact, getAdapterLogger } from '@zhin.js/logger';
|
|
15
15
|
import type { CapabilityId } from '@zhin.js/plugin-runtime';
|
|
16
16
|
import { registerKookAgentEndpoint } from './kook-agent-deps.js';
|
|
17
17
|
import {
|
|
@@ -33,8 +33,6 @@ import {
|
|
|
33
33
|
type KookClientTransport,
|
|
34
34
|
} from './ws.js';
|
|
35
35
|
|
|
36
|
-
const logger = getLogger('kook');
|
|
37
|
-
|
|
38
36
|
export interface KookEndpointOptions {
|
|
39
37
|
readonly id: CapabilityId;
|
|
40
38
|
readonly gateway: MessageGateway;
|
|
@@ -43,6 +41,8 @@ export interface KookEndpointOptions {
|
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
export class KookWebsocketEndpoint implements EndpointInstance {
|
|
44
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
45
|
+
|
|
46
46
|
readonly #options: KookEndpointOptions;
|
|
47
47
|
readonly #createClient: CreateKookClient;
|
|
48
48
|
#client: KookClientTransport | null = null;
|
|
@@ -52,6 +52,7 @@ export class KookWebsocketEndpoint implements EndpointInstance {
|
|
|
52
52
|
readonly management: EndpointManagement = createKookEndpointManagement(() => this.#requireClient());
|
|
53
53
|
|
|
54
54
|
constructor(options: KookEndpointOptions) {
|
|
55
|
+
this.#logger = getAdapterLogger('kook', options.config.id);
|
|
55
56
|
this.#options = options;
|
|
56
57
|
this.#createClient = options.createClient ?? (defaultCreateClient as CreateKookClient);
|
|
57
58
|
}
|
|
@@ -60,19 +61,19 @@ export class KookWebsocketEndpoint implements EndpointInstance {
|
|
|
60
61
|
if (this.#started) return;
|
|
61
62
|
this.#started = true;
|
|
62
63
|
try {
|
|
63
|
-
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.
|
|
64
|
+
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
|
|
64
65
|
this.#client = this.#createClient(this.#options.config);
|
|
65
66
|
this.#bindClient(this.#client);
|
|
66
67
|
await this.#client.connect();
|
|
67
|
-
logger.info(formatCompact({
|
|
68
|
+
this.#logger.info(formatCompact({
|
|
68
69
|
op: 'connect',
|
|
69
|
-
endpoint: this.#options.config.
|
|
70
|
+
endpoint: this.#options.config.id,
|
|
70
71
|
mode: 'websocket',
|
|
71
72
|
self_id: this.#client.self_id != null ? String(this.#client.self_id) : undefined,
|
|
72
73
|
}));
|
|
73
74
|
} catch (error) {
|
|
74
75
|
await this.stop();
|
|
75
|
-
logger.error('Failed to connect KOOK websocket:', error);
|
|
76
|
+
this.#logger.error('Failed to connect KOOK websocket:', error);
|
|
76
77
|
throw error;
|
|
77
78
|
}
|
|
78
79
|
}
|
|
@@ -99,7 +100,7 @@ export class KookWebsocketEndpoint implements EndpointInstance {
|
|
|
99
100
|
this.#client = null;
|
|
100
101
|
}
|
|
101
102
|
this.#started = false;
|
|
102
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
103
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -109,9 +110,9 @@ export class KookWebsocketEndpoint implements EndpointInstance {
|
|
|
109
110
|
? await client.sendPrivateMsg(conversation.id, body)
|
|
110
111
|
: await client.sendChannelMsg(conversation.id, body);
|
|
111
112
|
const messageId = result?.msg_id != null ? String(result.msg_id) : '';
|
|
112
|
-
logger.debug(formatCompact({
|
|
113
|
+
this.#logger.debug(formatCompact({
|
|
113
114
|
op: 'kook_send',
|
|
114
|
-
endpoint: this.#options.config.
|
|
115
|
+
endpoint: this.#options.config.id,
|
|
115
116
|
target: `${conversation.kind}:${conversation.id}`,
|
|
116
117
|
messageId,
|
|
117
118
|
}));
|
|
@@ -128,17 +129,21 @@ export class KookWebsocketEndpoint implements EndpointInstance {
|
|
|
128
129
|
conversation,
|
|
129
130
|
message: { conversation, id: msg.id },
|
|
130
131
|
content: formatInboundContent(msg),
|
|
131
|
-
sender:
|
|
132
|
+
sender: {
|
|
133
|
+
id: msg.authorId,
|
|
134
|
+
name: senderDisplayName(msg) || undefined,
|
|
135
|
+
...(msg.authorRoles?.length ? { roles: msg.authorRoles.map(String) } : {}),
|
|
136
|
+
},
|
|
137
|
+
endpointId: this.#options.config.id,
|
|
138
|
+
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
132
139
|
metadata: Object.freeze({
|
|
133
|
-
endpoint: this.#options.config.name,
|
|
134
140
|
channelKind: msg.channelKind,
|
|
135
141
|
userId: msg.authorId,
|
|
136
142
|
guildId: msg.guildId,
|
|
137
143
|
roles: msg.authorRoles,
|
|
138
|
-
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
139
144
|
}),
|
|
140
145
|
}).catch((err) => {
|
|
141
|
-
logger.warn(formatCompact({
|
|
146
|
+
this.#logger.warn(formatCompact({
|
|
142
147
|
op: 'kook_gateway_receive_failed',
|
|
143
148
|
target: `${conversation.kind}:${conversation.id}`,
|
|
144
149
|
error: err instanceof Error ? err.message : String(err),
|
|
@@ -203,6 +208,8 @@ export interface KookWebhookEndpointOptions {
|
|
|
203
208
|
}
|
|
204
209
|
|
|
205
210
|
export class KookWebhookEndpoint implements EndpointInstance {
|
|
211
|
+
readonly #logger!: ReturnType<typeof getAdapterLogger>;
|
|
212
|
+
|
|
206
213
|
readonly #options: KookWebhookEndpointOptions;
|
|
207
214
|
readonly #createClient: CreateKookClient;
|
|
208
215
|
#client: KookClientTransport | null = null;
|
|
@@ -214,6 +221,7 @@ export class KookWebhookEndpoint implements EndpointInstance {
|
|
|
214
221
|
readonly management: EndpointManagement = createKookEndpointManagement(() => this.#requireClient());
|
|
215
222
|
|
|
216
223
|
constructor(options: KookWebhookEndpointOptions) {
|
|
224
|
+
this.#logger = getAdapterLogger('kook', options.config.id);
|
|
217
225
|
this.#options = options;
|
|
218
226
|
this.#createClient = options.createClient ?? (defaultCreateWebhookClient as CreateKookClient);
|
|
219
227
|
}
|
|
@@ -235,20 +243,20 @@ export class KookWebhookEndpoint implements EndpointInstance {
|
|
|
235
243
|
if (this.#started) return;
|
|
236
244
|
this.#started = true;
|
|
237
245
|
try {
|
|
238
|
-
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.
|
|
246
|
+
this.#unregisterAgent = registerKookAgentEndpoint(this.#options.config.id, this);
|
|
239
247
|
this.#client = this.#createClient(this.#options.config);
|
|
240
248
|
await (this.#client as Client).init();
|
|
241
249
|
this.#routeReleases.push(...registerKookWebhookRoutes(this.#options.http, this));
|
|
242
|
-
logger.info(formatCompact({
|
|
250
|
+
this.#logger.info(formatCompact({
|
|
243
251
|
op: 'connect',
|
|
244
|
-
endpoint: this.#options.config.
|
|
252
|
+
endpoint: this.#options.config.id,
|
|
245
253
|
mode: 'webhook',
|
|
246
254
|
path: this.#options.config.webhookPath,
|
|
247
255
|
self_id: this.#client.self_id != null ? String(this.#client.self_id) : undefined,
|
|
248
256
|
}));
|
|
249
257
|
} catch (error) {
|
|
250
258
|
await this.stop();
|
|
251
|
-
logger.error('Failed to connect KOOK webhook:', error);
|
|
259
|
+
this.#logger.error('Failed to connect KOOK webhook:', error);
|
|
252
260
|
throw error;
|
|
253
261
|
}
|
|
254
262
|
}
|
|
@@ -277,7 +285,7 @@ export class KookWebhookEndpoint implements EndpointInstance {
|
|
|
277
285
|
this.#client = null;
|
|
278
286
|
}
|
|
279
287
|
this.#started = false;
|
|
280
|
-
logger.debug(formatCompact({ op: 'disconnect'
|
|
288
|
+
this.#logger.debug(formatCompact({ op: 'disconnect' }));
|
|
281
289
|
}
|
|
282
290
|
|
|
283
291
|
async send({ conversation, payload }: EndpointSendRequest): Promise<string> {
|
|
@@ -287,9 +295,9 @@ export class KookWebhookEndpoint implements EndpointInstance {
|
|
|
287
295
|
? await client.sendPrivateMsg(conversation.id, body)
|
|
288
296
|
: await client.sendChannelMsg(conversation.id, body);
|
|
289
297
|
const messageId = result?.msg_id != null ? String(result.msg_id) : '';
|
|
290
|
-
logger.debug(formatCompact({
|
|
298
|
+
this.#logger.debug(formatCompact({
|
|
291
299
|
op: 'kook_send',
|
|
292
|
-
endpoint: this.#options.config.
|
|
300
|
+
endpoint: this.#options.config.id,
|
|
293
301
|
target: `${conversation.kind}:${conversation.id}`,
|
|
294
302
|
messageId,
|
|
295
303
|
}));
|
|
@@ -306,17 +314,21 @@ export class KookWebhookEndpoint implements EndpointInstance {
|
|
|
306
314
|
conversation,
|
|
307
315
|
message: { conversation, id: msg.id },
|
|
308
316
|
content: formatInboundContent(msg),
|
|
309
|
-
sender:
|
|
317
|
+
sender: {
|
|
318
|
+
id: msg.authorId,
|
|
319
|
+
name: senderDisplayName(msg) || undefined,
|
|
320
|
+
...(msg.authorRoles?.length ? { roles: msg.authorRoles.map(String) } : {}),
|
|
321
|
+
},
|
|
322
|
+
endpointId: this.#options.config.id,
|
|
323
|
+
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
310
324
|
metadata: Object.freeze({
|
|
311
|
-
endpoint: this.#options.config.name,
|
|
312
325
|
channelKind: msg.channelKind,
|
|
313
326
|
userId: msg.authorId,
|
|
314
327
|
guildId: msg.guildId,
|
|
315
328
|
roles: msg.authorRoles,
|
|
316
|
-
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
317
329
|
}),
|
|
318
330
|
}).catch((err) => {
|
|
319
|
-
logger.warn(formatCompact({
|
|
331
|
+
this.#logger.warn(formatCompact({
|
|
320
332
|
op: 'kook_gateway_receive_failed',
|
|
321
333
|
target: `${conversation.kind}:${conversation.id}`,
|
|
322
334
|
error: err instanceof Error ? err.message : String(err),
|
package/src/index.ts
CHANGED
package/src/kook-agent-deps.ts
CHANGED
|
@@ -20,20 +20,20 @@ export interface KookAgentEndpoint {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface KookAgentDeps {
|
|
23
|
-
getEndpoint: (
|
|
23
|
+
getEndpoint: (endpointKey: string) => KookAgentEndpoint;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const endpoints = new Map<string, KookAgentEndpoint>();
|
|
27
27
|
let override: KookAgentDeps | null = null;
|
|
28
28
|
|
|
29
29
|
export function registerKookAgentEndpoint(
|
|
30
|
-
|
|
30
|
+
endpointKey: string,
|
|
31
31
|
endpoint: KookAgentEndpoint,
|
|
32
32
|
): () => void {
|
|
33
|
-
endpoints.set(
|
|
33
|
+
endpoints.set(endpointKey, endpoint);
|
|
34
34
|
return () => {
|
|
35
|
-
if (endpoints.get(
|
|
36
|
-
endpoints.delete(
|
|
35
|
+
if (endpoints.get(endpointKey) === endpoint) {
|
|
36
|
+
endpoints.delete(endpointKey);
|
|
37
37
|
}
|
|
38
38
|
};
|
|
39
39
|
}
|
|
@@ -46,9 +46,9 @@ export function setKookAgentDeps(deps: KookAgentDeps | null): void {
|
|
|
46
46
|
export function getKookAgentDeps(): KookAgentDeps {
|
|
47
47
|
if (override) return override;
|
|
48
48
|
return {
|
|
49
|
-
getEndpoint(
|
|
50
|
-
const registered = endpoints.get(
|
|
51
|
-
if (!registered) throw new Error(`Endpoint ${
|
|
49
|
+
getEndpoint(endpointKey: string): KookAgentEndpoint {
|
|
50
|
+
const registered = endpoints.get(endpointKey);
|
|
51
|
+
if (!registered) throw new Error(`Endpoint ${endpointKey} 不存在`);
|
|
52
52
|
return registered;
|
|
53
53
|
},
|
|
54
54
|
};
|
package/src/platform-permit.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* KOOK platform permit — guild / channel 差异化门禁
|
|
3
3
|
*/
|
|
4
|
-
import {
|
|
4
|
+
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
5
|
import { KookPermission } from './protocol.js';
|
|
6
6
|
|
|
7
7
|
const ADAPTER = 'kook';
|
|
@@ -54,17 +54,9 @@ export function normalizeKookSenderForPermit(
|
|
|
54
54
|
return { role: 'member', permissions };
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function
|
|
58
|
-
const
|
|
59
|
-
const permissions =
|
|
60
|
-
if (sender.isGuildOwner) permissions.push('guild_owner');
|
|
61
|
-
if (sender.isAdmin) permissions.push('guild_admin');
|
|
62
|
-
if (sender.permission === KookPermission.ChannelAdmin) permissions.push('channel_admin');
|
|
63
|
-
return { role: sender.role, permissions };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export function checkKookPlatformPermit(perm: string, message: Message<any>): boolean {
|
|
67
|
-
const { role, permissions } = senderPermits(message);
|
|
57
|
+
export function checkKookPlatformPermit(perm: string, subject: PermissionSubject): boolean {
|
|
58
|
+
const role = subject.sender?.role?.[0];
|
|
59
|
+
const permissions = subject.sender?.permissions ?? [];
|
|
68
60
|
const has = (t: string) => permissions.includes(t);
|
|
69
61
|
|
|
70
62
|
switch (perm) {
|
|
@@ -81,6 +73,3 @@ export function checkKookPlatformPermit(perm: string, message: Message<any>): bo
|
|
|
81
73
|
}
|
|
82
74
|
}
|
|
83
75
|
|
|
84
|
-
export function registerKookPlatformPermitChecker(): () => void {
|
|
85
|
-
return registerPlatformPermitChecker(ADAPTER, checkKookPlatformPermit);
|
|
86
|
-
}
|
package/src/protocol.ts
CHANGED
|
@@ -32,7 +32,7 @@ export enum KookPermission {
|
|
|
32
32
|
|
|
33
33
|
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
34
34
|
export interface KookAdapterConfig {
|
|
35
|
-
readonly
|
|
35
|
+
readonly id?: string;
|
|
36
36
|
readonly token?: string;
|
|
37
37
|
/** Default `websocket`. `webhook` requires httpHostToken + verify_token. */
|
|
38
38
|
readonly connection?: 'websocket' | 'webhook';
|
|
@@ -47,7 +47,7 @@ export interface KookAdapterConfig {
|
|
|
47
47
|
/** Transitional: legacy root `endpoints[]` with `context: kook`. */
|
|
48
48
|
readonly endpoints?: ReadonlyArray<{
|
|
49
49
|
readonly context?: string;
|
|
50
|
-
readonly
|
|
50
|
+
readonly id?: string;
|
|
51
51
|
readonly token?: string;
|
|
52
52
|
readonly connection?: 'websocket' | 'webhook';
|
|
53
53
|
readonly webhookPath?: string;
|
|
@@ -64,7 +64,7 @@ export interface KookAdapterConfig {
|
|
|
64
64
|
export interface ResolvedKookWebsocketConfig {
|
|
65
65
|
readonly context: 'kook';
|
|
66
66
|
readonly connection: 'websocket';
|
|
67
|
-
readonly
|
|
67
|
+
readonly id: string;
|
|
68
68
|
readonly token: string;
|
|
69
69
|
readonly data_dir?: string;
|
|
70
70
|
readonly timeout: number;
|
|
@@ -76,7 +76,7 @@ export interface ResolvedKookWebsocketConfig {
|
|
|
76
76
|
export interface ResolvedKookWebhookConfig {
|
|
77
77
|
readonly context: 'kook';
|
|
78
78
|
readonly connection: 'webhook';
|
|
79
|
-
readonly
|
|
79
|
+
readonly id: string;
|
|
80
80
|
readonly token: string;
|
|
81
81
|
readonly webhookPath: string;
|
|
82
82
|
readonly verifyToken: string;
|
|
@@ -142,8 +142,8 @@ export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookC
|
|
|
142
142
|
'KOOK adapter requires token (plugins.<key>.token or endpoints with context: kook)',
|
|
143
143
|
);
|
|
144
144
|
}
|
|
145
|
-
const
|
|
146
|
-
|| (typeof entry?.
|
|
145
|
+
const id = (typeof config.id === 'string' && config.id)
|
|
146
|
+
|| (typeof entry?.id === 'string' && entry.id)
|
|
147
147
|
|| process.env.KOOK_BOT_NAME
|
|
148
148
|
|| 'kook-bot';
|
|
149
149
|
const connection = config.connection
|
|
@@ -164,7 +164,7 @@ export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookC
|
|
|
164
164
|
return {
|
|
165
165
|
context: 'kook',
|
|
166
166
|
connection: 'webhook',
|
|
167
|
-
|
|
167
|
+
id,
|
|
168
168
|
token,
|
|
169
169
|
webhookPath: normalizeWebhookPath(
|
|
170
170
|
config.webhookPath ?? entry?.webhookPath ?? process.env.KOOK_WEBHOOK_PATH ?? '/kook/webhook',
|
|
@@ -179,7 +179,7 @@ export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookC
|
|
|
179
179
|
return {
|
|
180
180
|
context: 'kook',
|
|
181
181
|
connection: 'websocket',
|
|
182
|
-
|
|
182
|
+
id,
|
|
183
183
|
token,
|
|
184
184
|
data_dir: config.data_dir ?? entry?.data_dir,
|
|
185
185
|
timeout: config.timeout ?? entry?.timeout ?? 10_000,
|
|
@@ -193,9 +193,9 @@ export function resolveKookConfig(config: KookAdapterConfig = {}): ResolvedKookC
|
|
|
193
193
|
* 入站归一化 → ConversationRef:频道消息的所属 guild 进 `parent`(guild 容器
|
|
194
194
|
* 映射为 channel 容器);私聊(PERSON)无容器,直接 kind 'private'。
|
|
195
195
|
*/
|
|
196
|
-
export function kookInboundConversation(
|
|
196
|
+
export function kookInboundConversation(endpointKey: string, msg: KookInboundMessage): ConversationRef {
|
|
197
197
|
return {
|
|
198
|
-
endpoint: { id:
|
|
198
|
+
endpoint: { id: endpointKey, adapter: endpointKey.split('\0')[0] ?? endpointKey },
|
|
199
199
|
kind: msg.channelKind,
|
|
200
200
|
id: msg.channelId,
|
|
201
201
|
...(msg.guildId && msg.channelKind === 'channel'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|