@zhin.js/adapter-discord 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 +175 -0
- package/LICENSE +21 -0
- package/PERMITS.md +15 -14
- package/README.md +7 -2
- package/adapters/discord/index.js +3 -0
- package/adapters/discord/index.ts +3 -0
- package/agents/discord/conversation.js +70 -0
- package/agents/discord/conversation.ts +77 -0
- package/agents/discord/messages.js +18 -2
- package/agents/discord/messages.ts +18 -2
- package/agents/discord/skills/discord/SKILL.md +1 -1
- package/agents/discord/skills/discord/tools/react/index.js +7 -6
- package/agents/discord/skills/discord/tools/react/index.ts +8 -7
- package/agents/discord/skills/discord/tools/send_embed/index.js +6 -11
- package/agents/discord/skills/discord/tools/send_embed/index.ts +7 -12
- package/agents/discord/skills/discord-guild/tools/add_role/index.js +11 -9
- package/agents/discord/skills/discord-guild/tools/add_role/index.ts +11 -10
- package/agents/discord/skills/discord-guild/tools/create_thread/index.js +5 -5
- package/agents/discord/skills/discord-guild/tools/create_thread/index.ts +6 -6
- package/agents/discord/skills/discord-guild/tools/forum_post/index.js +7 -3
- package/agents/discord/skills/discord-guild/tools/forum_post/index.ts +7 -4
- package/agents/discord/skills/discord-guild/tools/list_roles/index.js +7 -8
- package/agents/discord/skills/discord-guild/tools/list_roles/index.ts +8 -9
- package/agents/discord/skills/discord-guild/tools/remove_role/index.js +11 -9
- package/agents/discord/skills/discord-guild/tools/remove_role/index.ts +11 -10
- package/lib/channel-visibility.d.ts +9 -0
- package/lib/channel-visibility.js +44 -0
- package/lib/endpoint.d.ts +1 -0
- package/lib/endpoint.js +76 -12
- package/lib/gateway.d.ts +1 -0
- package/lib/gateway.js +21 -8
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/platform-permit.d.ts +4 -11
- package/lib/platform-permit.js +7 -40
- package/lib/protocol.d.ts +18 -0
- package/lib/protocol.js +32 -3
- package/lib/sender-standing.d.ts +18 -0
- package/lib/sender-standing.js +91 -0
- package/lib/webhook.d.ts +2 -6
- package/lib/webhook.js +23 -55
- package/package.json +23 -25
- package/plugin.js +0 -6
- package/schema.json +0 -56
- package/src/channel-visibility.ts +44 -0
- package/src/endpoint.ts +77 -11
- package/src/gateway.ts +22 -5
- package/src/index.ts +1 -6
- package/src/platform-permit.ts +5 -52
- package/src/protocol.ts +43 -3
- package/src/sender-standing.ts +91 -0
- package/src/webhook.ts +21 -58
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { sendToCurrentConversation } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
|
-
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
7
|
+
description: '在当前 Discord 频道(或线程)发送富文本嵌入消息(Embed)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
channel_id: z.string().describe('频道 ID'),
|
|
10
9
|
title: z.string().optional().describe('Embed 标题'),
|
|
11
10
|
description: z.string().optional().describe('Embed 描述'),
|
|
12
11
|
color: z.number().optional().describe('颜色值(十进制,如 0x00ff00 = 65280)'),
|
|
@@ -15,8 +14,7 @@ export default defineAgentTool({
|
|
|
15
14
|
}),
|
|
16
15
|
adapter: 'discord',
|
|
17
16
|
tags: ['discord'],
|
|
18
|
-
async execute({
|
|
19
|
-
const client = requireDiscordGatewayClient(context.$client);
|
|
17
|
+
async execute({ title, description, color, url, fields }, context) {
|
|
20
18
|
const embedData = {};
|
|
21
19
|
if (title)
|
|
22
20
|
embedData.title = title;
|
|
@@ -34,11 +32,8 @@ export default defineAgentTool({
|
|
|
34
32
|
return { success: false, message: t(context.locale, 'invalidFields') };
|
|
35
33
|
}
|
|
36
34
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
const msg = await channel.send({ embeds: [embedData] });
|
|
42
|
-
return { success: true, message_id: msg.id, message: t(context.locale, 'embedSent') };
|
|
35
|
+
// `discord:embed` is the Discord adapter's namespaced outbound segment (rendered by formatOutboundBody).
|
|
36
|
+
const result = await sendToCurrentConversation(context, { type: 'discord:embed', data: embedData });
|
|
37
|
+
return { ...result, message: t(context.locale, result.success ? 'embedSent' : 'operationFailed') };
|
|
43
38
|
},
|
|
44
39
|
});
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { sendToCurrentConversation } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
|
-
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<{
|
|
7
|
-
description: '
|
|
6
|
+
export default defineAgentTool<{ title?: string; description?: string; color?: number; url?: string; fields?: string }>({
|
|
7
|
+
description: '在当前 Discord 频道(或线程)发送富文本嵌入消息(Embed)',
|
|
8
8
|
inputSchema: z.object({
|
|
9
|
-
channel_id: z.string().describe('频道 ID'),
|
|
10
9
|
title: z.string().optional().describe('Embed 标题'),
|
|
11
10
|
description: z.string().optional().describe('Embed 描述'),
|
|
12
11
|
color: z.number().optional().describe('颜色值(十进制,如 0x00ff00 = 65280)'),
|
|
@@ -15,8 +14,7 @@ export default defineAgentTool<{ channel_id: string; title?: string; description
|
|
|
15
14
|
}),
|
|
16
15
|
adapter: 'discord',
|
|
17
16
|
tags: ['discord'],
|
|
18
|
-
async execute({
|
|
19
|
-
const client = requireDiscordGatewayClient(context.$client);
|
|
17
|
+
async execute({ title, description, color, url, fields }, context) {
|
|
20
18
|
const embedData: Record<string, unknown> = {};
|
|
21
19
|
if (title) embedData.title = title;
|
|
22
20
|
if (description) embedData.description = description;
|
|
@@ -29,11 +27,8 @@ export default defineAgentTool<{ channel_id: string; title?: string; description
|
|
|
29
27
|
return { success: false, message: t(context.locale, 'invalidFields') };
|
|
30
28
|
}
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
const msg = await channel.send({ embeds: [embedData] } as never);
|
|
37
|
-
return { success: true, message_id: msg.id, message: t(context.locale, 'embedSent') };
|
|
30
|
+
// `discord:embed` is the Discord adapter's namespaced outbound segment (rendered by formatOutboundBody).
|
|
31
|
+
const result = await sendToCurrentConversation(context, { type: 'discord:embed', data: embedData });
|
|
32
|
+
return { ...result, message: t(context.locale, result.success ? 'embedSent' : 'operationFailed') };
|
|
38
33
|
},
|
|
39
34
|
});
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuildChannel, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
6
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
7
7
|
export default defineAgentTool({
|
|
8
|
-
description: '
|
|
8
|
+
description: '给当前 Discord 服务器的成员添加身份组(只能是低于你最高身份组的身份组)',
|
|
9
9
|
inputSchema: z.object({
|
|
10
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
11
10
|
user_id: z.string().describe('用户 ID'),
|
|
12
|
-
role_id: z.string().describe('
|
|
11
|
+
role_id: z.string().describe('身份组 ID'),
|
|
13
12
|
}),
|
|
14
13
|
adapter: 'discord',
|
|
15
14
|
scopes: ["channel"],
|
|
16
15
|
tags: ['discord'],
|
|
17
|
-
permissions: [
|
|
18
|
-
async execute({
|
|
16
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
17
|
+
async execute({ user_id, role_id }, context) {
|
|
18
|
+
const { guildId } = currentGuildChannel(context);
|
|
19
19
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
|
-
const guild = await client.guilds.fetch(
|
|
20
|
+
const guild = await client.guilds.fetch(guildId);
|
|
21
|
+
const denied = await requireRoleBelowRequester(context, guild, role_id);
|
|
22
|
+
if (denied)
|
|
23
|
+
return { success: false, message: denied };
|
|
21
24
|
const member = await guild.members.fetch(user_id);
|
|
22
25
|
await member.roles.add(role_id);
|
|
23
|
-
|
|
24
|
-
return { success, message: success ? t(context.locale, 'memberRoleAdded', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
26
|
+
return { success: true, message: t(context.locale, 'memberRoleAdded', { p0: user_id }) };
|
|
25
27
|
},
|
|
26
28
|
});
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuildChannel, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
|
|
7
|
-
export default defineAgentTool<{
|
|
8
|
-
description: '
|
|
7
|
+
export default defineAgentTool<{ user_id: string; role_id: string }>({
|
|
8
|
+
description: '给当前 Discord 服务器的成员添加身份组(只能是低于你最高身份组的身份组)',
|
|
9
9
|
inputSchema: z.object({
|
|
10
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
11
10
|
user_id: z.string().describe('用户 ID'),
|
|
12
|
-
role_id: z.string().describe('
|
|
11
|
+
role_id: z.string().describe('身份组 ID'),
|
|
13
12
|
}),
|
|
14
13
|
adapter: 'discord',
|
|
15
14
|
scopes: ["channel"],
|
|
16
15
|
tags: ['discord'],
|
|
17
|
-
permissions: [
|
|
18
|
-
async execute({
|
|
16
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
17
|
+
async execute({ user_id, role_id }, context) {
|
|
18
|
+
const { guildId } = currentGuildChannel(context);
|
|
19
19
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
|
-
const guild = await client.guilds.fetch(
|
|
20
|
+
const guild = await client.guilds.fetch(guildId);
|
|
21
|
+
const denied = await requireRoleBelowRequester(context, guild, role_id);
|
|
22
|
+
if (denied) return { success: false, message: denied };
|
|
21
23
|
const member = await guild.members.fetch(user_id) as {
|
|
22
24
|
roles: { add(id: string): Promise<unknown> };
|
|
23
25
|
};
|
|
24
26
|
await member.roles.add(role_id);
|
|
25
|
-
|
|
26
|
-
return { success, message: success ? t(context.locale, 'memberRoleAdded', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
27
|
+
return { success: true, message: t(context.locale, 'memberRoleAdded', { p0: user_id }) };
|
|
27
28
|
},
|
|
28
29
|
});
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuildChannel } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
6
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
7
7
|
import { ThreadAutoArchiveDuration } from 'discord.js';
|
|
8
8
|
export default defineAgentTool({
|
|
9
|
-
description: '
|
|
9
|
+
description: '在当前 Discord 频道中创建帖子/子线程',
|
|
10
10
|
inputSchema: z.object({
|
|
11
|
-
channel_id: z.string().describe('频道 ID'),
|
|
12
11
|
name: z.string().describe('帖子标题'),
|
|
13
12
|
message_id: z.string().optional().describe('基于某条消息创建(可选)'),
|
|
14
13
|
auto_archive_duration: z.number().optional().describe('自动归档时间(分钟:60/1440/4320/10080)'),
|
|
@@ -16,8 +15,9 @@ export default defineAgentTool({
|
|
|
16
15
|
adapter: 'discord',
|
|
17
16
|
scopes: ["channel"],
|
|
18
17
|
tags: ['discord'],
|
|
19
|
-
permissions: [
|
|
20
|
-
async execute({
|
|
18
|
+
permissions: ['platform-permission:manage_channels', 'bot-permission:create_public_threads'],
|
|
19
|
+
async execute({ name, message_id, auto_archive_duration }, context) {
|
|
20
|
+
const { channelId: channel_id } = currentGuildChannel(context);
|
|
21
21
|
const client = requireDiscordGatewayClient(context.$client);
|
|
22
22
|
const channel = await client.channels.fetch(channel_id);
|
|
23
23
|
if (!channel || !('threads' in channel) || channel.isThreadOnly())
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuildChannel } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
import { ThreadAutoArchiveDuration } from 'discord.js';
|
|
7
7
|
|
|
8
|
-
export default defineAgentTool<{
|
|
9
|
-
description: '
|
|
8
|
+
export default defineAgentTool<{ name: string; message_id?: string; auto_archive_duration?: number }>({
|
|
9
|
+
description: '在当前 Discord 频道中创建帖子/子线程',
|
|
10
10
|
inputSchema: z.object({
|
|
11
|
-
channel_id: z.string().describe('频道 ID'),
|
|
12
11
|
name: z.string().describe('帖子标题'),
|
|
13
12
|
message_id: z.string().optional().describe('基于某条消息创建(可选)'),
|
|
14
13
|
auto_archive_duration: z.number().optional().describe('自动归档时间(分钟:60/1440/4320/10080)'),
|
|
@@ -16,8 +15,9 @@ export default defineAgentTool<{ channel_id: string; name: string; message_id?:
|
|
|
16
15
|
adapter: 'discord',
|
|
17
16
|
scopes: ["channel"],
|
|
18
17
|
tags: ['discord'],
|
|
19
|
-
permissions: [
|
|
20
|
-
async execute({
|
|
18
|
+
permissions: ['platform-permission:manage_channels', 'bot-permission:create_public_threads'],
|
|
19
|
+
async execute({ name, message_id, auto_archive_duration }, context) {
|
|
20
|
+
const { channelId: channel_id } = currentGuildChannel(context);
|
|
21
21
|
const client = requireDiscordGatewayClient(context.$client);
|
|
22
22
|
const channel = await client.channels.fetch(channel_id);
|
|
23
23
|
if (!channel || !('threads' in channel) || channel.isThreadOnly()) throw new Error(t(context.locale, 'threadsUnsupported', { p0: channel_id }));
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentChannel } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
6
7
|
import { ChannelType } from 'discord.js';
|
|
7
8
|
export default defineAgentTool({
|
|
8
|
-
description: '
|
|
9
|
+
description: '在当前 Discord 论坛频道中创建帖子(需在该论坛的帖子里发起)',
|
|
9
10
|
inputSchema: z.object({
|
|
10
|
-
channel_id: z.string().describe('论坛频道 ID'),
|
|
11
11
|
name: z.string().describe('帖子标题'),
|
|
12
12
|
content: z.string().describe('帖子内容'),
|
|
13
13
|
tags: z.string().optional().describe('标签名,逗号分隔(可选)'),
|
|
@@ -15,7 +15,11 @@ export default defineAgentTool({
|
|
|
15
15
|
adapter: 'discord',
|
|
16
16
|
scopes: ["channel"],
|
|
17
17
|
tags: ['discord'],
|
|
18
|
-
async execute({
|
|
18
|
+
async execute({ name, content, tags }, context) {
|
|
19
|
+
// A forum post reports the forum as its conversation id and the post as `threadId`.
|
|
20
|
+
const { conversationChannelId: channel_id, guildId } = currentChannel(context);
|
|
21
|
+
if (!guildId)
|
|
22
|
+
throw new Error(t(context.locale, 'guildChannelRequired'));
|
|
19
23
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
24
|
const tagList = tags ? tags.split(',').map((t) => t.trim()) : undefined;
|
|
21
25
|
const channel = await client.channels.fetch(channel_id);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentChannel } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
6
|
import { ChannelType } from 'discord.js';
|
|
6
7
|
|
|
7
|
-
export default defineAgentTool<{
|
|
8
|
-
description: '
|
|
8
|
+
export default defineAgentTool<{ name: string; content: string; tags?: string }>({
|
|
9
|
+
description: '在当前 Discord 论坛频道中创建帖子(需在该论坛的帖子里发起)',
|
|
9
10
|
inputSchema: z.object({
|
|
10
|
-
channel_id: z.string().describe('论坛频道 ID'),
|
|
11
11
|
name: z.string().describe('帖子标题'),
|
|
12
12
|
content: z.string().describe('帖子内容'),
|
|
13
13
|
tags: z.string().optional().describe('标签名,逗号分隔(可选)'),
|
|
@@ -15,7 +15,10 @@ export default defineAgentTool<{ channel_id: string; name: string; content: stri
|
|
|
15
15
|
adapter: 'discord',
|
|
16
16
|
scopes: ["channel"],
|
|
17
17
|
tags: ['discord'],
|
|
18
|
-
async execute({
|
|
18
|
+
async execute({ name, content, tags }, context) {
|
|
19
|
+
// A forum post reports the forum as its conversation id and the post as `threadId`.
|
|
20
|
+
const { conversationChannelId: channel_id, guildId } = currentChannel(context);
|
|
21
|
+
if (!guildId) throw new Error(t(context.locale, 'guildChannelRequired'));
|
|
19
22
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
23
|
const tagList = tags ? tags.split(',').map((t: string) => t.trim()) : undefined;
|
|
21
24
|
const channel = await client.channels.fetch(channel_id);
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
+
import { currentGuildChannel } from '../../../../conversation.js';
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
export default defineAgentTool({
|
|
7
|
-
description: '
|
|
8
|
-
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
|
-
}),
|
|
7
|
+
description: '获取当前 Discord 服务器的身份组列表',
|
|
8
|
+
inputSchema: z.object({}),
|
|
11
9
|
adapter: 'discord',
|
|
12
10
|
scopes: ["channel"],
|
|
13
11
|
tags: ['discord'],
|
|
14
|
-
permissions: [
|
|
15
|
-
async execute(
|
|
12
|
+
permissions: ['platform-permission:manage_roles'],
|
|
13
|
+
async execute(_args, context) {
|
|
14
|
+
const { guildId } = currentGuildChannel(context);
|
|
16
15
|
const client = requireDiscordGatewayClient(context.$client);
|
|
17
|
-
const guild = await client.guilds.fetch(
|
|
16
|
+
const guild = await client.guilds.fetch(guildId);
|
|
18
17
|
await guild.roles.fetch();
|
|
19
18
|
const cache = guild.roles.cache;
|
|
20
19
|
const roles = [...cache.values()].map((role) => ({
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
+
import { currentGuildChannel } from '../../../../conversation.js';
|
|
1
2
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
2
3
|
import { z } from 'zod';
|
|
3
4
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
4
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
5
5
|
|
|
6
|
-
export default defineAgentTool<
|
|
7
|
-
description: '
|
|
8
|
-
inputSchema: z.object({
|
|
9
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
10
|
-
}),
|
|
6
|
+
export default defineAgentTool<Record<string, never>>({
|
|
7
|
+
description: '获取当前 Discord 服务器的身份组列表',
|
|
8
|
+
inputSchema: z.object({}),
|
|
11
9
|
adapter: 'discord',
|
|
12
10
|
scopes: ["channel"],
|
|
13
11
|
tags: ['discord'],
|
|
14
|
-
permissions: [
|
|
15
|
-
async execute(
|
|
12
|
+
permissions: ['platform-permission:manage_roles'],
|
|
13
|
+
async execute(_args, context) {
|
|
14
|
+
const { guildId } = currentGuildChannel(context);
|
|
16
15
|
const client = requireDiscordGatewayClient(context.$client);
|
|
17
|
-
const guild = await client.guilds.fetch(
|
|
16
|
+
const guild = await client.guilds.fetch(guildId);
|
|
18
17
|
await guild.roles.fetch();
|
|
19
18
|
const cache = guild.roles.cache as Map<string, {
|
|
20
19
|
id: string;
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
2
|
import { messages as t } from "../../../../messages.js";
|
|
3
|
+
import { currentGuildChannel, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
3
4
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
6
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
7
7
|
export default defineAgentTool({
|
|
8
|
-
description: '
|
|
8
|
+
description: '移除当前 Discord 服务器成员的身份组(只能是低于你最高身份组的身份组)',
|
|
9
9
|
inputSchema: z.object({
|
|
10
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
11
10
|
user_id: z.string().describe('用户 ID'),
|
|
12
|
-
role_id: z.string().describe('
|
|
11
|
+
role_id: z.string().describe('身份组 ID'),
|
|
13
12
|
}),
|
|
14
13
|
adapter: 'discord',
|
|
15
14
|
scopes: ["channel"],
|
|
16
15
|
tags: ['discord'],
|
|
17
|
-
permissions: [
|
|
18
|
-
async execute({
|
|
16
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
17
|
+
async execute({ user_id, role_id }, context) {
|
|
18
|
+
const { guildId } = currentGuildChannel(context);
|
|
19
19
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
|
-
const guild = await client.guilds.fetch(
|
|
20
|
+
const guild = await client.guilds.fetch(guildId);
|
|
21
|
+
const denied = await requireRoleBelowRequester(context, guild, role_id);
|
|
22
|
+
if (denied)
|
|
23
|
+
return { success: false, message: denied };
|
|
21
24
|
const member = await guild.members.fetch(user_id);
|
|
22
25
|
await member.roles.remove(role_id);
|
|
23
|
-
|
|
24
|
-
return { success, message: success ? t(context.locale, 'memberRoleRemoved', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
26
|
+
return { success: true, message: t(context.locale, 'memberRoleRemoved', { p0: user_id }) };
|
|
25
27
|
},
|
|
26
28
|
});
|
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { messages as t } from "../../../../messages.js";
|
|
2
|
+
import { currentGuildChannel, requireRoleBelowRequester } from "../../../../conversation.js";
|
|
2
3
|
import { defineAgentTool } from '@zhin.js/tool';
|
|
3
4
|
import { z } from 'zod';
|
|
4
5
|
import { requireDiscordGatewayClient } from '@zhin.js/adapter-discord';
|
|
5
|
-
import { platformPermission } from '@zhin.js/permission';
|
|
6
6
|
|
|
7
|
-
export default defineAgentTool<{
|
|
8
|
-
description: '
|
|
7
|
+
export default defineAgentTool<{ user_id: string; role_id: string }>({
|
|
8
|
+
description: '移除当前 Discord 服务器成员的身份组(只能是低于你最高身份组的身份组)',
|
|
9
9
|
inputSchema: z.object({
|
|
10
|
-
guild_id: z.string().describe('服务器 ID'),
|
|
11
10
|
user_id: z.string().describe('用户 ID'),
|
|
12
|
-
role_id: z.string().describe('
|
|
11
|
+
role_id: z.string().describe('身份组 ID'),
|
|
13
12
|
}),
|
|
14
13
|
adapter: 'discord',
|
|
15
14
|
scopes: ["channel"],
|
|
16
15
|
tags: ['discord'],
|
|
17
|
-
permissions: [
|
|
18
|
-
async execute({
|
|
16
|
+
permissions: ['platform-permission:manage_roles', 'bot-permission:manage_roles'],
|
|
17
|
+
async execute({ user_id, role_id }, context) {
|
|
18
|
+
const { guildId } = currentGuildChannel(context);
|
|
19
19
|
const client = requireDiscordGatewayClient(context.$client);
|
|
20
|
-
const guild = await client.guilds.fetch(
|
|
20
|
+
const guild = await client.guilds.fetch(guildId);
|
|
21
|
+
const denied = await requireRoleBelowRequester(context, guild, role_id);
|
|
22
|
+
if (denied) return { success: false, message: denied };
|
|
21
23
|
const member = await guild.members.fetch(user_id) as {
|
|
22
24
|
roles: { remove(id: string): Promise<unknown> };
|
|
23
25
|
};
|
|
24
26
|
await member.roles.remove(role_id);
|
|
25
|
-
|
|
26
|
-
return { success, message: success ? t(context.locale, 'memberRoleRemoved', { p0: user_id }) : t(context.locale, 'operationFailed') };
|
|
27
|
+
return { success: true, message: t(context.locale, 'memberRoleRemoved', { p0: user_id }) };
|
|
27
28
|
},
|
|
28
29
|
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DISCORD_CHANNEL_FLAG_OBFUSCATED: number;
|
|
2
|
+
type ChannelFlagsLike = number | bigint | {
|
|
3
|
+
readonly bitfield?: number | bigint;
|
|
4
|
+
} | null | undefined;
|
|
5
|
+
/** 频道是否被 Discord 混淆(机器人无 `VIEW_CHANNEL`)。兼容 discord.js 的 `ChannelFlagsBitField` 与原始 `flags` 数值。 */
|
|
6
|
+
export declare function isDiscordChannelObfuscated(channel: {
|
|
7
|
+
readonly flags?: ChannelFlagsLike;
|
|
8
|
+
} | null | undefined): boolean;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ChannelFlagsBitField } from 'discord.js';
|
|
2
|
+
/**
|
|
3
|
+
* Discord 频道混淆(Channel Obfuscation)判定。
|
|
4
|
+
*
|
|
5
|
+
* 自 2026-11-16 起,Gateway 会继续下发机器人缺少 `VIEW_CHANNEL` 的频道,但其元数据被混淆:
|
|
6
|
+
* `name` 变为 `"___hidden___"`,并在 `flags` 上置 `CHANNEL_OBFUSCATED`;HTTP 的
|
|
7
|
+
* `GET /guilds/{guild.id}/channels` 则直接不返回这些频道。
|
|
8
|
+
*
|
|
9
|
+
* 出处:
|
|
10
|
+
* - https://docs.discord.com/developers/resources/channel#channel-object-channel-flags
|
|
11
|
+
* (Channel Flags 表:`CHANNEL_OBFUSCATED` = `1 << 17`)
|
|
12
|
+
* - https://docs.discord.com/developers/resources/channel#channel-object-obfuscated-channels
|
|
13
|
+
* - https://docs.discord.com/developers/change-log (2026-08-12 "Channel Obfuscation for Users and Bots")
|
|
14
|
+
* - discord-api-types `ChannelFlags.ChannelObfuscated`(0.38.54 起,值为 `131072`)。
|
|
15
|
+
* discord.js 14.27.0 把它声明为 dependencies `^0.38.49`,并通过
|
|
16
|
+
* `ChannelFlagsBitField.Flags` 暴露同一枚举。0.38.49–0.38.53 上该枚举是 `undefined`,
|
|
17
|
+
* 因此这里用 `?? (1 << 17)` 兜底,避免过滤悄悄失效。
|
|
18
|
+
*
|
|
19
|
+
* 官方要求以 flag 判定,不要依赖 `name` 等被混淆字段。
|
|
20
|
+
*/
|
|
21
|
+
function obfuscatedFlagBit() {
|
|
22
|
+
return ChannelFlagsBitField.Flags.ChannelObfuscated ?? (1 << 17);
|
|
23
|
+
}
|
|
24
|
+
export const DISCORD_CHANNEL_FLAG_OBFUSCATED = obfuscatedFlagBit();
|
|
25
|
+
function readFlagBits(flags) {
|
|
26
|
+
if (flags == null)
|
|
27
|
+
return 0;
|
|
28
|
+
if (typeof flags === 'number')
|
|
29
|
+
return flags;
|
|
30
|
+
if (typeof flags === 'bigint')
|
|
31
|
+
return Number(flags & 0xffffffffn);
|
|
32
|
+
const bitfield = flags.bitfield;
|
|
33
|
+
if (typeof bitfield === 'number')
|
|
34
|
+
return bitfield;
|
|
35
|
+
if (typeof bitfield === 'bigint')
|
|
36
|
+
return Number(bitfield & 0xffffffffn);
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
/** 频道是否被 Discord 混淆(机器人无 `VIEW_CHANNEL`)。兼容 discord.js 的 `ChannelFlagsBitField` 与原始 `flags` 数值。 */
|
|
40
|
+
export function isDiscordChannelObfuscated(channel) {
|
|
41
|
+
if (!channel)
|
|
42
|
+
return false;
|
|
43
|
+
return (readFlagBits(channel.flags) & obfuscatedFlagBit()) !== 0;
|
|
44
|
+
}
|
package/lib/endpoint.d.ts
CHANGED
|
@@ -74,5 +74,6 @@ export declare class DiscordInteractionsEndpoint extends DiscordRestClient imple
|
|
|
74
74
|
/**
|
|
75
75
|
* DiscordGatewayEndpoint 的 EndpointManagement 语义端口(参照 qq 的工厂模式)。
|
|
76
76
|
* 数据源为 discord.js SDK 缓存:guilds.cache / guild.channels.cache / guild.members。
|
|
77
|
+
* listChannels 会过滤带 CHANNEL_OBFUSCATED flag 的混淆频道(见 channel-visibility.ts)。
|
|
77
78
|
*/
|
|
78
79
|
export declare function createDiscordEndpointManagement(requireClient: () => DiscordClientTransport): EndpointManagement;
|