@zhin.js/adapter-kook 1.1.26 → 1.1.28
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 +178 -0
- package/LICENSE +21 -0
- package/PERMITS.md +20 -14
- package/README.md +6 -2
- package/adapters/kook/index.js +3 -0
- package/adapters/kook/index.ts +3 -0
- package/agents/kook/conversation.js +88 -0
- package/agents/kook/conversation.ts +99 -0
- package/agents/kook/messages.js +16 -0
- package/agents/kook/messages.ts +16 -0
- package/agents/kook/skills/kook/tools/blacklist/index.js +9 -6
- package/agents/kook/skills/kook/tools/blacklist/index.ts +9 -7
- package/agents/kook/skills/kook/tools/create_role/index.js +5 -6
- package/agents/kook/skills/kook/tools/create_role/index.ts +6 -7
- package/agents/kook/skills/kook/tools/delete_role/index.js +5 -6
- package/agents/kook/skills/kook/tools/delete_role/index.ts +6 -7
- package/agents/kook/skills/kook/tools/grant_role/index.js +9 -7
- package/agents/kook/skills/kook/tools/grant_role/index.ts +9 -8
- package/agents/kook/skills/kook/tools/list_roles/index.js +5 -7
- package/agents/kook/skills/kook/tools/list_roles/index.ts +6 -8
- package/agents/kook/skills/kook/tools/revoke_role/index.js +9 -7
- package/agents/kook/skills/kook/tools/revoke_role/index.ts +9 -8
- package/lib/endpoint.d.ts +2 -1
- package/lib/endpoint.js +27 -12
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/platform-permit.d.ts +4 -19
- package/lib/platform-permit.js +7 -46
- package/lib/protocol.d.ts +1 -5
- package/lib/protocol.js +3 -28
- package/lib/sender-roles.d.ts +6 -6
- package/lib/sender-roles.js +55 -21
- package/lib/webhook.d.ts +1 -2
- package/lib/webhook.js +13 -33
- package/package.json +23 -26
- package/plugin.js +0 -6
- package/schema.json +0 -56
- package/src/endpoint.ts +27 -13
- package/src/index.ts +1 -7
- package/src/platform-permit.ts +5 -70
- package/src/protocol.ts +4 -33
- package/src/sender-roles.ts +59 -27
- package/src/webhook.ts +14 -36
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
7
|
+
description: '在当前 KOOK 服务器中创建新角色',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
name: z.string().describe('角色名称'),
|
|
11
10
|
}),
|
|
12
11
|
adapter: 'kook',
|
|
13
12
|
scopes: ["channel"],
|
|
14
13
|
tags: ['kook'],
|
|
15
|
-
permissions: [
|
|
16
|
-
async execute({
|
|
14
|
+
permissions: ['platform:owner', 'bot-permission:manage_roles'],
|
|
15
|
+
async execute({ name }, context) {
|
|
17
16
|
const client = context.$client;
|
|
18
|
-
const role = await client.pickGuild(
|
|
17
|
+
const role = await client.pickGuild(currentGuild(context)).createRole(name);
|
|
19
18
|
return {
|
|
20
19
|
success: true,
|
|
21
20
|
message: t(context.locale, 'roleCreated', { p0: name }),
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<{
|
|
7
|
-
description: '
|
|
6
|
+
export default defineAgentTool<{ name: string }>({
|
|
7
|
+
description: '在当前 KOOK 服务器中创建新角色',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
name: z.string().describe('角色名称'),
|
|
11
10
|
}),
|
|
12
11
|
adapter: 'kook',
|
|
13
12
|
scopes: ["channel"],
|
|
14
13
|
tags: ['kook'],
|
|
15
|
-
permissions: [
|
|
16
|
-
async execute({
|
|
14
|
+
permissions: ['platform:owner', 'bot-permission:manage_roles'],
|
|
15
|
+
async execute({ name }, context) {
|
|
17
16
|
const client = context.$client;
|
|
18
|
-
const role = await client.pickGuild(
|
|
17
|
+
const role = await client.pickGuild(currentGuild(context)).createRole(name);
|
|
19
18
|
return {
|
|
20
19
|
success: true,
|
|
21
20
|
message: t(context.locale, 'roleCreated', { p0: name }),
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
7
|
+
description: '删除当前 KOOK 服务器中的角色',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
role_id: z.string().describe('角色 ID'),
|
|
11
10
|
}),
|
|
12
11
|
adapter: 'kook',
|
|
13
12
|
scopes: ["channel"],
|
|
14
13
|
tags: ['kook'],
|
|
15
|
-
permissions: [
|
|
16
|
-
async execute({
|
|
14
|
+
permissions: ['platform:owner', 'bot-permission:manage_roles'],
|
|
15
|
+
async execute({ role_id }, context) {
|
|
17
16
|
const client = context.$client;
|
|
18
|
-
const success = await client.pickGuild(
|
|
17
|
+
const success = await client.pickGuild(currentGuild(context)).deleteRole(role_id);
|
|
19
18
|
return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
|
|
20
19
|
},
|
|
21
20
|
});
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<{
|
|
7
|
-
description: '
|
|
6
|
+
export default defineAgentTool<{ role_id: string }>({
|
|
7
|
+
description: '删除当前 KOOK 服务器中的角色',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
role_id: z.string().describe('角色 ID'),
|
|
11
10
|
}),
|
|
12
11
|
adapter: 'kook',
|
|
13
12
|
scopes: ["channel"],
|
|
14
13
|
tags: ['kook'],
|
|
15
|
-
permissions: [
|
|
16
|
-
async execute({
|
|
14
|
+
permissions: ['platform:owner', 'bot-permission:manage_roles'],
|
|
15
|
+
async execute({ role_id }, context) {
|
|
17
16
|
const client = context.$client;
|
|
18
|
-
const success = await client.pickGuild(
|
|
17
|
+
const success = await client.pickGuild(currentGuild(context)).deleteRole(role_id);
|
|
19
18
|
return { success, message: success ? t(context.locale, 'roleDeleted', { p0: role_id }) : t(context.locale, 'roleDeleteFailed') };
|
|
20
19
|
},
|
|
21
20
|
});
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
7
|
+
description: '在当前 KOOK 服务器给用户授予角色(只能是低于你最高角色的角色)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
user_id: z.string().describe('用户 ID'),
|
|
11
10
|
role_id: z.string().describe('角色 ID'),
|
|
12
11
|
}),
|
|
13
12
|
adapter: 'kook',
|
|
14
13
|
scopes: ["channel"],
|
|
15
14
|
tags: ['kook'],
|
|
16
|
-
permissions: [
|
|
17
|
-
async execute({
|
|
18
|
-
const
|
|
19
|
-
const
|
|
15
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
16
|
+
async execute({ user_id, role_id }, context) {
|
|
17
|
+
const guildId = currentGuild(context);
|
|
18
|
+
const denied = await requireRoleBelowRequester(context, guildId, role_id);
|
|
19
|
+
if (denied)
|
|
20
|
+
return { success: false, message: denied };
|
|
21
|
+
const success = await context.$client.pickGuildMember(guildId, user_id).grant(role_id);
|
|
20
22
|
return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
|
|
21
23
|
},
|
|
22
24
|
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<{
|
|
7
|
-
description: '
|
|
6
|
+
export default defineAgentTool<{ user_id: string; role_id: string }>({
|
|
7
|
+
description: '在当前 KOOK 服务器给用户授予角色(只能是低于你最高角色的角色)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
user_id: z.string().describe('用户 ID'),
|
|
11
10
|
role_id: z.string().describe('角色 ID'),
|
|
12
11
|
}),
|
|
13
12
|
adapter: 'kook',
|
|
14
13
|
scopes: ["channel"],
|
|
15
14
|
tags: ['kook'],
|
|
16
|
-
permissions: [
|
|
17
|
-
async execute({
|
|
18
|
-
const
|
|
19
|
-
const
|
|
15
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
16
|
+
async execute({ user_id, role_id }, context) {
|
|
17
|
+
const guildId = currentGuild(context);
|
|
18
|
+
const denied = await requireRoleBelowRequester(context, guildId, role_id);
|
|
19
|
+
if (denied) return { success: false, message: denied };
|
|
20
|
+
const success = await context.$client.pickGuildMember(guildId, user_id).grant(role_id);
|
|
20
21
|
return { success, message: success ? t(context.locale, 'roleGranted', { p0: user_id, p1: role_id }) : t(context.locale, 'roleGrantFailed') };
|
|
21
22
|
},
|
|
22
23
|
});
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
export default defineAgentTool({
|
|
5
|
-
description: '
|
|
6
|
-
inputSchema: z.object({
|
|
7
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
8
|
-
}),
|
|
6
|
+
description: '获取当前 KOOK 服务器的角色列表(position 越小优先级越高)',
|
|
7
|
+
inputSchema: z.object({}),
|
|
9
8
|
adapter: 'kook',
|
|
10
9
|
scopes: ["channel"],
|
|
11
10
|
tags: ['kook'],
|
|
12
|
-
async execute(
|
|
13
|
-
const
|
|
14
|
-
const roles = await client.pickGuild(guild_id).getRoleList();
|
|
11
|
+
async execute(_args, context) {
|
|
12
|
+
const roles = await context.$client.pickGuild(currentGuild(context)).getRoleList();
|
|
15
13
|
return {
|
|
16
14
|
roles: roles.map((r) => ({
|
|
17
15
|
id: String(r.role_id),
|
|
@@ -1,17 +1,15 @@
|
|
|
1
|
+
import { currentGuild } from "../../../../conversation.js";
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
|
|
4
|
-
export default defineAgentTool<
|
|
5
|
-
description: '
|
|
6
|
-
inputSchema: z.object({
|
|
7
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
8
|
-
}),
|
|
5
|
+
export default defineAgentTool<Record<string, never>>({
|
|
6
|
+
description: '获取当前 KOOK 服务器的角色列表(position 越小优先级越高)',
|
|
7
|
+
inputSchema: z.object({}),
|
|
9
8
|
adapter: 'kook',
|
|
10
9
|
scopes: ["channel"],
|
|
11
10
|
tags: ['kook'],
|
|
12
|
-
async execute(
|
|
13
|
-
const
|
|
14
|
-
const roles = await client.pickGuild(guild_id).getRoleList();
|
|
11
|
+
async execute(_args, context) {
|
|
12
|
+
const roles = await context.$client.pickGuild(currentGuild(context)).getRoleList();
|
|
15
13
|
return {
|
|
16
14
|
roles: roles.map((r) => ({
|
|
17
15
|
id: String(r.role_id),
|
|
@@ -1,22 +1,24 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
7
|
+
description: '撤销当前 KOOK 服务器中用户的角色(只能是低于你最高角色的角色)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
user_id: z.string().describe('用户 ID'),
|
|
11
10
|
role_id: z.string().describe('角色 ID'),
|
|
12
11
|
}),
|
|
13
12
|
adapter: 'kook',
|
|
14
13
|
scopes: ["channel"],
|
|
15
14
|
tags: ['kook'],
|
|
16
|
-
permissions: [
|
|
17
|
-
async execute({
|
|
18
|
-
const
|
|
19
|
-
const
|
|
15
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
16
|
+
async execute({ user_id, role_id }, context) {
|
|
17
|
+
const guildId = currentGuild(context);
|
|
18
|
+
const denied = await requireRoleBelowRequester(context, guildId, role_id);
|
|
19
|
+
if (denied)
|
|
20
|
+
return { success: false, message: denied };
|
|
21
|
+
const success = await context.$client.pickGuildMember(guildId, user_id).revoke(role_id);
|
|
20
22
|
return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
|
|
21
23
|
},
|
|
22
24
|
});
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuild, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<{
|
|
7
|
-
description: '
|
|
6
|
+
export default defineAgentTool<{ user_id: string; role_id: string }>({
|
|
7
|
+
description: '撤销当前 KOOK 服务器中用户的角色(只能是低于你最高角色的角色)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
9
|
user_id: z.string().describe('用户 ID'),
|
|
11
10
|
role_id: z.string().describe('角色 ID'),
|
|
12
11
|
}),
|
|
13
12
|
adapter: 'kook',
|
|
14
13
|
scopes: ["channel"],
|
|
15
14
|
tags: ['kook'],
|
|
16
|
-
permissions: [
|
|
17
|
-
async execute({
|
|
18
|
-
const
|
|
19
|
-
const
|
|
15
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
16
|
+
async execute({ user_id, role_id }, context) {
|
|
17
|
+
const guildId = currentGuild(context);
|
|
18
|
+
const denied = await requireRoleBelowRequester(context, guildId, role_id);
|
|
19
|
+
if (denied) return { success: false, message: denied };
|
|
20
|
+
const success = await context.$client.pickGuildMember(guildId, user_id).revoke(role_id);
|
|
20
21
|
return { success, message: success ? t(context.locale, 'roleRevoked', { p0: user_id, p1: role_id }) : t(context.locale, 'roleRevokeFailed') };
|
|
21
22
|
},
|
|
22
23
|
});
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { HttpHost } from '@zhin.js/host-http';
|
|
|
7
7
|
import type { CapabilityId } from 'zhin.js';
|
|
8
8
|
import { type KookInboundMessage, type KookWebhookEventData, type ResolvedKookWebhookConfig, type ResolvedKookWebsocketConfig } from './protocol.js';
|
|
9
9
|
import { RuntimeKookClient, type KookClientTransport } from './ws.js';
|
|
10
|
+
import { KookSenderRoleResolver } from './sender-roles.js';
|
|
10
11
|
export interface KookEndpointOptions {
|
|
11
12
|
readonly id: CapabilityId;
|
|
12
13
|
readonly config: ResolvedKookWebsocketConfig;
|
|
@@ -45,4 +46,4 @@ export declare class KookWebhookEndpoint extends RuntimeKookClient implements En
|
|
|
45
46
|
* 数据走 kook-client 的 HTTP API 封装:/api/v3/guild/list、
|
|
46
47
|
* /api/v3/channel/list、/api/v3/guild/user-list(SDK 内部已做分页聚合)。
|
|
47
48
|
*/
|
|
48
|
-
export declare function createKookEndpointManagement(requireClient: () => KookClientTransport): EndpointManagement;
|
|
49
|
+
export declare function createKookEndpointManagement(requireClient: () => KookClientTransport, roles?: KookSenderRoleResolver): EndpointManagement;
|
package/lib/endpoint.js
CHANGED
|
@@ -11,8 +11,8 @@ import { recallKookMessage, sendKookOutbound } from './outbound.js';
|
|
|
11
11
|
import { KookSenderRoleResolver } from './sender-roles.js';
|
|
12
12
|
import { receiveKookSideEvent } from './side-event-dispatch.js';
|
|
13
13
|
import { createKookSelfProfile } from './self-profile.js';
|
|
14
|
-
/** 入站 message.receive
|
|
15
|
-
function kookInboundPayload(endpointId, conversation, msg,
|
|
14
|
+
/** 入站 message.receive 载荷:发送者平台身份进 `sender.platform`(ADR 0056 §1)。 */
|
|
15
|
+
function kookInboundPayload(endpointId, conversation, msg, platform, selfId) {
|
|
16
16
|
return {
|
|
17
17
|
conversation,
|
|
18
18
|
event: msg.event,
|
|
@@ -22,8 +22,7 @@ function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
|
|
|
22
22
|
sender: {
|
|
23
23
|
id: msg.authorId,
|
|
24
24
|
name: senderDisplayName(msg) || undefined,
|
|
25
|
-
...(
|
|
26
|
-
...(projection.permissions.length ? { permissions: [...projection.permissions] } : {}),
|
|
25
|
+
...(platform ? { platform } : {}),
|
|
27
26
|
},
|
|
28
27
|
endpointId,
|
|
29
28
|
...(isKookBotMentioned(msg, selfId) ? { mentioned: true } : {}),
|
|
@@ -32,7 +31,6 @@ function kookInboundPayload(endpointId, conversation, msg, projection, selfId) {
|
|
|
32
31
|
userId: msg.authorId,
|
|
33
32
|
guildId: msg.guildId,
|
|
34
33
|
authorRoleIds: msg.authorRoles,
|
|
35
|
-
...(projection.role ? { senderRole: projection.role } : {}),
|
|
36
34
|
}),
|
|
37
35
|
};
|
|
38
36
|
}
|
|
@@ -45,7 +43,7 @@ export class KookWebsocketEndpoint extends RuntimeKookClient {
|
|
|
45
43
|
#open = false;
|
|
46
44
|
#executionSignal;
|
|
47
45
|
#started = false;
|
|
48
|
-
#management = createKookEndpointManagement(() => this.#requireClient());
|
|
46
|
+
#management = createKookEndpointManagement(() => this.#requireClient(), this.#roles);
|
|
49
47
|
#control = Object.freeze({
|
|
50
48
|
recall: request => recallKookMessage(this.#requireClient(), request),
|
|
51
49
|
});
|
|
@@ -122,9 +120,9 @@ export class KookWebsocketEndpoint extends RuntimeKookClient {
|
|
|
122
120
|
return;
|
|
123
121
|
const conversation = kookInboundConversation(String(this.#options.id), msg);
|
|
124
122
|
const selfId = this.self_id != null ? String(this.self_id) : undefined;
|
|
125
|
-
return this.#roles.resolve(msg).then((
|
|
123
|
+
return this.#roles.resolve(msg).then((platform) => {
|
|
126
124
|
this.#executionSignal?.throwIfAborted();
|
|
127
|
-
return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg,
|
|
125
|
+
return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, platform, selfId));
|
|
128
126
|
}).catch((err) => {
|
|
129
127
|
this.#logger.warn(formatCompact({
|
|
130
128
|
op: 'kook_gateway_receive_failed',
|
|
@@ -196,7 +194,7 @@ export class KookWebhookEndpoint extends RuntimeKookClient {
|
|
|
196
194
|
#open = false;
|
|
197
195
|
#executionSignal;
|
|
198
196
|
#started = false;
|
|
199
|
-
#management = createKookEndpointManagement(() => this.#requireClient());
|
|
197
|
+
#management = createKookEndpointManagement(() => this.#requireClient(), this.#roles);
|
|
200
198
|
#control = Object.freeze({
|
|
201
199
|
recall: request => recallKookMessage(this.#requireClient(), request),
|
|
202
200
|
});
|
|
@@ -306,9 +304,9 @@ export class KookWebhookEndpoint extends RuntimeKookClient {
|
|
|
306
304
|
return;
|
|
307
305
|
const conversation = kookInboundConversation(String(this.#options.id), msg);
|
|
308
306
|
const selfId = this.self_id != null ? String(this.self_id) : undefined;
|
|
309
|
-
return this.#roles.resolve(msg).then((
|
|
307
|
+
return this.#roles.resolve(msg).then((platform) => {
|
|
310
308
|
this.#executionSignal?.throwIfAborted();
|
|
311
|
-
return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg,
|
|
309
|
+
return this[endpointSpec].events.emit('message.receive', kookInboundPayload(this.#options.config.id, conversation, msg, platform, selfId));
|
|
312
310
|
}).catch((err) => {
|
|
313
311
|
this.#logger.warn(formatCompact({
|
|
314
312
|
op: 'kook_gateway_receive_failed',
|
|
@@ -364,8 +362,25 @@ function isKookTextChannelType(type) {
|
|
|
364
362
|
* 数据走 kook-client 的 HTTP API 封装:/api/v3/guild/list、
|
|
365
363
|
* /api/v3/channel/list、/api/v3/guild/user-list(SDK 内部已做分页聚合)。
|
|
366
364
|
*/
|
|
367
|
-
export function createKookEndpointManagement(requireClient) {
|
|
365
|
+
export function createKookEndpointManagement(requireClient, roles = new KookSenderRoleResolver(requireClient)) {
|
|
368
366
|
return Object.freeze({
|
|
367
|
+
/**
|
|
368
|
+
* ADR 0056 §1: the Bot's own standing in the channel's guild (`/v3/user/view` self → its role
|
|
369
|
+
* ids, then the same guild owner / role-permission resolution as senders).
|
|
370
|
+
*/
|
|
371
|
+
async inspectSelfStanding({ conversation, signal }) {
|
|
372
|
+
const guildId = conversation.kind === 'channel' ? conversation.parent?.id : undefined;
|
|
373
|
+
if (!guildId)
|
|
374
|
+
return undefined;
|
|
375
|
+
const operation = createEndpointOperation({ signal });
|
|
376
|
+
const client = requireClient();
|
|
377
|
+
const selfId = client.self_id != null ? String(client.self_id) : undefined;
|
|
378
|
+
if (!selfId)
|
|
379
|
+
return undefined;
|
|
380
|
+
const { data } = await operation.run(() => client.request.get('/v3/user/view', { params: { user_id: selfId, guild_id: guildId } }));
|
|
381
|
+
const held = Array.isArray(data?.roles) ? data.roles.map(Number).filter(Number.isFinite) : [];
|
|
382
|
+
return roles.resolve({ guildId, authorId: selfId, authorRoles: held });
|
|
383
|
+
},
|
|
369
384
|
async listGroups(request = {}) {
|
|
370
385
|
const operation = createEndpointOperation(request);
|
|
371
386
|
const guilds = await operation.run(() => requireClient().getGuildList());
|
package/lib/index.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export { registerKookWebhookRoutes, handleKookWebhookRequest, type KookWebhookHa
|
|
|
4
4
|
export { kookWebsocketClientOptions, kookWebhookClientOptions, normalizeKookMessage, type KookClientTransport, } from './ws.js';
|
|
5
5
|
export { type KookClientEventMap } from './client.js';
|
|
6
6
|
export { KookAdapter } from './adapter.js';
|
|
7
|
-
export {
|
|
7
|
+
export { platformPermit } 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 { kookWebsocketClientOptions, kookWebhookClientOptions, normalizeKookMessage, } from './ws.js';
|
|
5
5
|
export { KookAdapter } from './adapter.js';
|
|
6
|
-
export {
|
|
6
|
+
export { platformPermit } from './platform-permit.js';
|
package/lib/platform-permit.d.ts
CHANGED
|
@@ -1,22 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* KOOK platform permit
|
|
2
|
+
* KOOK platform permit helper(ADR 0056 §5)。
|
|
3
|
+
*
|
|
4
|
+
* 平台身份由适配器上报到 `sender.platform`(见 `sender-roles.ts`),permit 由内置评估器
|
|
5
|
+
* (`@zhin.js/permission`)判断;适配器不再导出自有的 permit 解析器或检查函数。
|
|
3
6
|
*/
|
|
4
|
-
import type { PermissionSubject } from '@zhin.js/permission';
|
|
5
|
-
import { KookPermission } from './protocol.js';
|
|
6
7
|
export declare function platformPermit(perm: string): string;
|
|
7
|
-
export declare function kookGroupPermitResolver(logicalPerm: string): string;
|
|
8
|
-
export interface KookSenderInfo {
|
|
9
|
-
id: string;
|
|
10
|
-
name: string;
|
|
11
|
-
permission?: KookPermission;
|
|
12
|
-
roles?: number[];
|
|
13
|
-
isGuildOwner?: boolean;
|
|
14
|
-
isAdmin?: boolean;
|
|
15
|
-
role?: string;
|
|
16
|
-
permissions?: string[];
|
|
17
|
-
}
|
|
18
|
-
export declare function normalizeKookSenderForPermit(info: KookSenderInfo, isChannel: boolean): {
|
|
19
|
-
role?: string;
|
|
20
|
-
permissions?: string[];
|
|
21
|
-
};
|
|
22
|
-
export declare function checkKookPlatformPermit(perm: string, subject: PermissionSubject): boolean;
|
package/lib/platform-permit.js
CHANGED
|
@@ -1,48 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* KOOK platform permit helper(ADR 0056 §5)。
|
|
3
|
+
*
|
|
4
|
+
* 平台身份由适配器上报到 `sender.platform`(见 `sender-roles.ts`),permit 由内置评估器
|
|
5
|
+
* (`@zhin.js/permission`)判断;适配器不再导出自有的 permit 解析器或检查函数。
|
|
6
|
+
*/
|
|
3
7
|
export function platformPermit(perm) {
|
|
4
|
-
return `platform
|
|
5
|
-
}
|
|
6
|
-
const FACTORY_PERM_MAP = {
|
|
7
|
-
scene_admin: 'guild_admin',
|
|
8
|
-
scene_owner: 'guild_owner',
|
|
9
|
-
};
|
|
10
|
-
export function kookGroupPermitResolver(logicalPerm) {
|
|
11
|
-
return platformPermit(FACTORY_PERM_MAP[logicalPerm] ?? logicalPerm);
|
|
12
|
-
}
|
|
13
|
-
export function normalizeKookSenderForPermit(info, isChannel) {
|
|
14
|
-
const permissions = [];
|
|
15
|
-
if (info.roles?.length) {
|
|
16
|
-
permissions.push(...info.roles.map((r) => `role:${r}`));
|
|
17
|
-
}
|
|
18
|
-
if (info.isGuildOwner || info.permission === KookPermission.Owner) {
|
|
19
|
-
permissions.push('guild_owner', 'guild_admin');
|
|
20
|
-
return { role: 'owner', permissions };
|
|
21
|
-
}
|
|
22
|
-
if (info.permission === KookPermission.ChannelAdmin && isChannel) {
|
|
23
|
-
permissions.push('channel_admin', 'guild_admin');
|
|
24
|
-
return { role: 'channel_admin', permissions };
|
|
25
|
-
}
|
|
26
|
-
if (info.isAdmin || info.permission === KookPermission.Admin) {
|
|
27
|
-
permissions.push('guild_admin');
|
|
28
|
-
return { role: 'admin', permissions };
|
|
29
|
-
}
|
|
30
|
-
return { role: 'member', permissions };
|
|
31
|
-
}
|
|
32
|
-
export function checkKookPlatformPermit(perm, subject) {
|
|
33
|
-
const role = subject.sender?.role?.[0];
|
|
34
|
-
const permissions = subject.sender?.permissions ?? [];
|
|
35
|
-
const has = (t) => permissions.includes(t);
|
|
36
|
-
switch (perm) {
|
|
37
|
-
case 'guild_owner':
|
|
38
|
-
return role === 'owner' || has('guild_owner');
|
|
39
|
-
case 'guild_admin':
|
|
40
|
-
return role === 'owner' || role === 'admin' || role === 'channel_admin' || has('guild_admin') || has('channel_admin');
|
|
41
|
-
case 'channel_admin':
|
|
42
|
-
return role === 'owner' || role === 'admin' || role === 'channel_admin' || has('channel_admin') || has('guild_admin');
|
|
43
|
-
case 'manage_roles':
|
|
44
|
-
return role === 'owner' || role === 'admin' || has('guild_owner') || has('guild_admin');
|
|
45
|
-
default:
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
8
|
+
return `platform-permission:${perm}`;
|
|
48
9
|
}
|
package/lib/protocol.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { EndpointProfileConfiguration } from 'zhin.js/adapter';
|
|
2
|
-
import type { IncomingMessage } from 'node:http';
|
|
3
2
|
import { type ConversationRef } from '@zhin.js/im-contract';
|
|
4
3
|
import type { Locale } from 'zhin.js/i18n';
|
|
5
4
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'mark' | 'off';
|
|
@@ -131,10 +130,7 @@ export declare function isKookBotMentioned(msg: KookInboundMessage, selfId?: str
|
|
|
131
130
|
*/
|
|
132
131
|
export declare function formatOutboundKmarkdown(payload: unknown, locale?: Locale): string;
|
|
133
132
|
export declare function normalizeWebhookPath(path: string): string;
|
|
134
|
-
export declare function
|
|
135
|
-
readonly limit?: number;
|
|
136
|
-
}): Promise<string>;
|
|
137
|
-
export declare function readRequestBody(request: IncomingMessage, options?: {
|
|
133
|
+
export declare function readRequestBody(request: Request, options?: {
|
|
138
134
|
readonly limit?: number;
|
|
139
135
|
}): Promise<Buffer>;
|
|
140
136
|
export declare function padKookEncryptKey(key: string): Buffer;
|
package/lib/protocol.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** KOOK protocol helpers. Canonicalization is owned by Core. */
|
|
2
2
|
import { createDecipheriv, timingSafeEqual } from 'node:crypto';
|
|
3
3
|
import { inflateSync } from 'node:zlib';
|
|
4
|
+
import { readBodyBytes } from '@zhin.js/host-http';
|
|
4
5
|
import { EndpointDeliveryError, isMediaRef } from '@zhin.js/im-contract';
|
|
5
6
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
6
7
|
import { outboundMessages as t } from './i18n.js';
|
|
@@ -192,35 +193,9 @@ export function normalizeWebhookPath(path) {
|
|
|
192
193
|
const trimmed = path.trim() || '/kook/webhook';
|
|
193
194
|
return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
|
|
194
195
|
}
|
|
195
|
-
export async function readTextBody(request, options = {}) {
|
|
196
|
-
const limit = options.limit ?? 1_048_576;
|
|
197
|
-
const chunks = [];
|
|
198
|
-
let size = 0;
|
|
199
|
-
for await (const chunk of request) {
|
|
200
|
-
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
201
|
-
size += buffer.length;
|
|
202
|
-
if (size > limit) {
|
|
203
|
-
request.destroy();
|
|
204
|
-
throw new Error(`Request body exceeds ${limit} bytes`);
|
|
205
|
-
}
|
|
206
|
-
chunks.push(buffer);
|
|
207
|
-
}
|
|
208
|
-
return Buffer.concat(chunks).toString('utf8');
|
|
209
|
-
}
|
|
210
196
|
export async function readRequestBody(request, options = {}) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
let size = 0;
|
|
214
|
-
for await (const chunk of request) {
|
|
215
|
-
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
216
|
-
size += buffer.length;
|
|
217
|
-
if (size > limit) {
|
|
218
|
-
request.destroy();
|
|
219
|
-
throw new Error(`Request body exceeds ${limit} bytes`);
|
|
220
|
-
}
|
|
221
|
-
chunks.push(buffer);
|
|
222
|
-
}
|
|
223
|
-
return Buffer.concat(chunks);
|
|
197
|
+
// Oversize bodies throw (the webhook answers its generic OK), as before.
|
|
198
|
+
return Buffer.from(await readBodyBytes(request, { limit: options.limit ?? 1_048_576 }));
|
|
224
199
|
}
|
|
225
200
|
export function padKookEncryptKey(key) {
|
|
226
201
|
const buf = Buffer.alloc(32, 0);
|
package/lib/sender-roles.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
+
import type { PlatformStanding } from '@zhin.js/im-contract';
|
|
1
2
|
import type { KookClientTransport } from './ws.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
}
|
|
3
|
+
/** KOOK 角色权限位(按位序,见 KOOK 开发者文档「权限说明」)。 */
|
|
4
|
+
export declare const KOOK_ROLE_PERMISSIONS: readonly string[];
|
|
5
|
+
/** KOOK 权限位 → 权限名;未知位丢弃。 */
|
|
6
|
+
export declare function kookPermissionNames(bits: number): string[];
|
|
7
7
|
export declare class KookSenderRoleResolver {
|
|
8
8
|
#private;
|
|
9
9
|
private readonly getClient;
|
|
@@ -12,5 +12,5 @@ export declare class KookSenderRoleResolver {
|
|
|
12
12
|
readonly guildId?: string;
|
|
13
13
|
readonly authorId: string;
|
|
14
14
|
readonly authorRoles?: readonly number[];
|
|
15
|
-
}): Promise<
|
|
15
|
+
}): Promise<PlatformStanding | undefined>;
|
|
16
16
|
}
|