@zhin.js/adapter-discord 5.0.1 → 5.0.3
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 +55 -0
- package/README.md +51 -76
- package/adapters/discord.ts +46 -0
- package/agent/tools/add_role.ts +24 -0
- package/agent/tools/create_thread.ts +25 -0
- package/agent/tools/forum_post.ts +24 -0
- package/agent/tools/list_roles.ts +22 -0
- package/agent/tools/react.ts +22 -0
- package/agent/tools/remove_role.ts +24 -0
- package/agent/tools/send_embed.ts +37 -0
- package/lib/discord-agent-deps.d.ts +35 -0
- package/lib/discord-agent-deps.js +32 -0
- package/lib/endpoint.d.ts +66 -119
- package/lib/endpoint.js +308 -1047
- package/lib/gateway.d.ts +122 -0
- package/lib/gateway.js +235 -0
- package/lib/index.d.ts +6 -18
- package/lib/index.js +6 -330
- package/lib/platform-permit.d.ts +1 -2
- package/lib/platform-permit.js +4 -2
- package/lib/protocol.d.ts +135 -0
- package/lib/protocol.js +234 -0
- package/lib/webhook.d.ts +13 -0
- package/lib/webhook.js +86 -0
- package/package.json +48 -31
- package/plugin.ts +13 -0
- package/schema.json +63 -0
- package/src/discord-agent-deps.ts +79 -0
- package/src/endpoint.ts +385 -1167
- package/src/gateway.ts +337 -0
- package/src/index.ts +55 -332
- package/src/platform-permit.ts +1 -2
- package/src/protocol.ts +392 -0
- package/src/webhook.ts +121 -0
- package/client/Dashboard.tsx +0 -195
- package/client/index.tsx +0 -11
- package/client/tsconfig.json +0 -7
- package/client/utils/api.ts +0 -30
- package/dist/index.js +0 -29
- package/lib/adapter.d.ts +0 -25
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js +0 -96
- package/lib/adapter.js.map +0 -1
- package/lib/endpoint-interactions.d.ts +0 -34
- package/lib/endpoint-interactions.d.ts.map +0 -1
- package/lib/endpoint-interactions.js +0 -284
- package/lib/endpoint-interactions.js.map +0 -1
- package/lib/endpoint.d.ts.map +0 -1
- package/lib/endpoint.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/platform-permit.d.ts.map +0 -1
- package/lib/platform-permit.js.map +0 -1
- package/lib/segment-mapper.d.ts +0 -2
- package/lib/segment-mapper.d.ts.map +0 -1
- package/lib/segment-mapper.js +0 -2
- package/lib/segment-mapper.js.map +0 -1
- package/lib/types.d.ts +0 -49
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/plugin.yml +0 -3
- package/src/adapter.ts +0 -108
- package/src/endpoint-interactions.ts +0 -354
- package/src/segment-mapper.ts +0 -1
- package/src/types.ts +0 -60
- /package/{skills/discord → agent}/PERMITS.md +0 -0
- /package/{skills/discord/SKILL.md → agent/skills/discord.md} +0 -0
package/lib/index.js
CHANGED
|
@@ -1,330 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import { discordGroupPermitResolver, platformPermit, registerDiscordPlatformPermitChecker, } from "./platform-permit.js";
|
|
8
|
-
export * from "./types.js";
|
|
9
|
-
export { DiscordEndpoint } from "./endpoint.js";
|
|
10
|
-
export { DiscordInteractionsEndpoint } from "./endpoint-interactions.js";
|
|
11
|
-
export { DiscordAdapter } from "./adapter.js";
|
|
12
|
-
const plugin = usePlugin();
|
|
13
|
-
const { provide, useContext } = plugin;
|
|
14
|
-
provide({
|
|
15
|
-
name: "discord",
|
|
16
|
-
description: "Discord 适配器(Gateway / Interactions)",
|
|
17
|
-
mounted: async (p) => {
|
|
18
|
-
const adapter = new DiscordAdapter(p);
|
|
19
|
-
await adapter.start();
|
|
20
|
-
return adapter;
|
|
21
|
-
},
|
|
22
|
-
dispose: async (adapter) => {
|
|
23
|
-
await adapter.stop();
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
useContext('tool', 'discord', (toolService, discord) => {
|
|
27
|
-
const disposers = [];
|
|
28
|
-
disposers.push(registerDiscordPlatformPermitChecker());
|
|
29
|
-
const sceneTools = createSceneManagementTools(discord, 'discord', { permitResolver: discordGroupPermitResolver, registerChecker: false });
|
|
30
|
-
disposers.push(...sceneTools.map(t => toolService.addTool(t, plugin.name)));
|
|
31
|
-
function getGatewayBot(endpointId) {
|
|
32
|
-
const endpoint = discord.endpoints.get(endpointId);
|
|
33
|
-
if (!endpoint)
|
|
34
|
-
throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
35
|
-
if (endpoint.$config.connection !== 'gateway') {
|
|
36
|
-
throw new Error('此工具仅支持 connection: gateway');
|
|
37
|
-
}
|
|
38
|
-
return endpoint;
|
|
39
|
-
}
|
|
40
|
-
disposers.push(toolService.addTool({
|
|
41
|
-
name: 'discord_add_role',
|
|
42
|
-
description: '给成员添加 Discord 角色',
|
|
43
|
-
parameters: {
|
|
44
|
-
type: 'object',
|
|
45
|
-
properties: {
|
|
46
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
47
|
-
guild_id: { type: 'string', description: '服务器 ID' },
|
|
48
|
-
user_id: { type: 'string', description: '用户 ID' },
|
|
49
|
-
role_id: { type: 'string', description: '角色 ID' },
|
|
50
|
-
},
|
|
51
|
-
required: ['endpoint_id', 'guild_id', 'user_id', 'role_id'],
|
|
52
|
-
},
|
|
53
|
-
platforms: ['discord'],
|
|
54
|
-
tags: ['discord'],
|
|
55
|
-
permissions: [platformPermit('manage_roles')],
|
|
56
|
-
execute: async (args) => {
|
|
57
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
58
|
-
const success = await endpoint.addRole(args.guild_id, args.user_id, args.role_id);
|
|
59
|
-
return { success, message: success ? `已给用户 ${args.user_id} 添加角色` : '操作失败' };
|
|
60
|
-
},
|
|
61
|
-
}, plugin.name));
|
|
62
|
-
disposers.push(toolService.addTool({
|
|
63
|
-
name: 'discord_remove_role',
|
|
64
|
-
description: '移除成员的 Discord 角色',
|
|
65
|
-
parameters: {
|
|
66
|
-
type: 'object',
|
|
67
|
-
properties: {
|
|
68
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
69
|
-
guild_id: { type: 'string', description: '服务器 ID' },
|
|
70
|
-
user_id: { type: 'string', description: '用户 ID' },
|
|
71
|
-
role_id: { type: 'string', description: '角色 ID' },
|
|
72
|
-
},
|
|
73
|
-
required: ['endpoint_id', 'guild_id', 'user_id', 'role_id'],
|
|
74
|
-
},
|
|
75
|
-
platforms: ['discord'],
|
|
76
|
-
tags: ['discord'],
|
|
77
|
-
permissions: [platformPermit('manage_roles')],
|
|
78
|
-
execute: async (args) => {
|
|
79
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
80
|
-
const success = await endpoint.removeRole(args.guild_id, args.user_id, args.role_id);
|
|
81
|
-
return { success, message: success ? `已移除用户 ${args.user_id} 的角色` : '操作失败' };
|
|
82
|
-
},
|
|
83
|
-
}, plugin.name));
|
|
84
|
-
disposers.push(toolService.addTool({
|
|
85
|
-
name: 'discord_list_roles',
|
|
86
|
-
description: '获取 Discord 服务器角色列表',
|
|
87
|
-
parameters: {
|
|
88
|
-
type: 'object',
|
|
89
|
-
properties: {
|
|
90
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
91
|
-
guild_id: { type: 'string', description: '服务器 ID' },
|
|
92
|
-
},
|
|
93
|
-
required: ['endpoint_id', 'guild_id'],
|
|
94
|
-
},
|
|
95
|
-
platforms: ['discord'],
|
|
96
|
-
tags: ['discord'],
|
|
97
|
-
permissions: [platformPermit('manage_roles')],
|
|
98
|
-
execute: async (args) => {
|
|
99
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
100
|
-
const roles = await endpoint.getRoles(args.guild_id);
|
|
101
|
-
return { roles, count: roles.length };
|
|
102
|
-
},
|
|
103
|
-
}, plugin.name));
|
|
104
|
-
disposers.push(toolService.addTool({
|
|
105
|
-
name: 'discord_create_thread',
|
|
106
|
-
description: '在 Discord 频道中创建帖子/子线程',
|
|
107
|
-
parameters: {
|
|
108
|
-
type: 'object',
|
|
109
|
-
properties: {
|
|
110
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
111
|
-
channel_id: { type: 'string', description: '频道 ID' },
|
|
112
|
-
name: { type: 'string', description: '帖子标题' },
|
|
113
|
-
message_id: { type: 'string', description: '基于某条消息创建(可选)' },
|
|
114
|
-
auto_archive_duration: {
|
|
115
|
-
type: 'number',
|
|
116
|
-
description: '自动归档时间(分钟:60/1440/4320/10080)',
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
required: ['endpoint_id', 'channel_id', 'name'],
|
|
120
|
-
},
|
|
121
|
-
platforms: ['discord'],
|
|
122
|
-
tags: ['discord'],
|
|
123
|
-
permissions: [platformPermit('manage_channels')],
|
|
124
|
-
execute: async (args) => {
|
|
125
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
126
|
-
const thread = await endpoint.createThread(args.channel_id, args.name, args.message_id, args.auto_archive_duration);
|
|
127
|
-
return { success: true, thread_id: thread.id, message: `帖子 "${args.name}" 已创建` };
|
|
128
|
-
},
|
|
129
|
-
}, plugin.name));
|
|
130
|
-
disposers.push(toolService.addTool({
|
|
131
|
-
name: 'discord_react',
|
|
132
|
-
description: '对 Discord 消息添加表情反应',
|
|
133
|
-
parameters: {
|
|
134
|
-
type: 'object',
|
|
135
|
-
properties: {
|
|
136
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
137
|
-
channel_id: { type: 'string', description: '频道 ID' },
|
|
138
|
-
message_id: { type: 'string', description: '消息 ID' },
|
|
139
|
-
emoji: {
|
|
140
|
-
type: 'string',
|
|
141
|
-
description: '表情(Unicode 表情或自定义表情如 <:name:id>)',
|
|
142
|
-
},
|
|
143
|
-
},
|
|
144
|
-
required: ['endpoint_id', 'channel_id', 'message_id', 'emoji'],
|
|
145
|
-
},
|
|
146
|
-
platforms: ['discord'],
|
|
147
|
-
tags: ['discord'],
|
|
148
|
-
execute: async (args) => {
|
|
149
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
150
|
-
await endpoint.addReaction(args.channel_id, args.message_id, args.emoji);
|
|
151
|
-
return { success: true, message: `已添加反应 ${args.emoji}` };
|
|
152
|
-
},
|
|
153
|
-
}, plugin.name));
|
|
154
|
-
disposers.push(toolService.addTool({
|
|
155
|
-
name: 'discord_send_embed',
|
|
156
|
-
description: '发送 Discord 富文本嵌入消息(Embed)',
|
|
157
|
-
parameters: {
|
|
158
|
-
type: 'object',
|
|
159
|
-
properties: {
|
|
160
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
161
|
-
channel_id: { type: 'string', description: '频道 ID' },
|
|
162
|
-
title: { type: 'string', description: 'Embed 标题' },
|
|
163
|
-
description: { type: 'string', description: 'Embed 描述' },
|
|
164
|
-
color: { type: 'number', description: '颜色值(十进制,如 0x00ff00 = 65280)' },
|
|
165
|
-
url: { type: 'string', description: '标题链接(可选)' },
|
|
166
|
-
fields: {
|
|
167
|
-
type: 'string',
|
|
168
|
-
description: '字段,JSON 格式: [{"name":"k","value":"v","inline":false}]',
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
required: ['endpoint_id', 'channel_id'],
|
|
172
|
-
},
|
|
173
|
-
platforms: ['discord'],
|
|
174
|
-
tags: ['discord'],
|
|
175
|
-
execute: async (args) => {
|
|
176
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
177
|
-
const embedData = {};
|
|
178
|
-
if (args.title)
|
|
179
|
-
embedData.title = args.title;
|
|
180
|
-
if (args.description)
|
|
181
|
-
embedData.description = args.description;
|
|
182
|
-
if (args.color)
|
|
183
|
-
embedData.color = args.color;
|
|
184
|
-
if (args.url)
|
|
185
|
-
embedData.url = args.url;
|
|
186
|
-
if (args.fields) {
|
|
187
|
-
try {
|
|
188
|
-
embedData.fields = JSON.parse(args.fields);
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
return { success: false, message: 'fields 格式错误,应为 JSON 数组' };
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
const msg = await endpoint.sendEmbed(args.channel_id, embedData);
|
|
195
|
-
return { success: true, message_id: msg.id, message: 'Embed 已发送' };
|
|
196
|
-
},
|
|
197
|
-
}, plugin.name));
|
|
198
|
-
disposers.push(toolService.addTool({
|
|
199
|
-
name: 'discord_forum_post',
|
|
200
|
-
description: '在 Discord 论坛频道中创建帖子',
|
|
201
|
-
parameters: {
|
|
202
|
-
type: 'object',
|
|
203
|
-
properties: {
|
|
204
|
-
endpoint_id: { type: 'string', description: 'Endpoint 名称', contextKey: 'endpointId' },
|
|
205
|
-
channel_id: { type: 'string', description: '论坛频道 ID' },
|
|
206
|
-
name: { type: 'string', description: '帖子标题' },
|
|
207
|
-
content: { type: 'string', description: '帖子内容' },
|
|
208
|
-
tags: { type: 'string', description: '标签名,逗号分隔(可选)' },
|
|
209
|
-
},
|
|
210
|
-
required: ['endpoint_id', 'channel_id', 'name', 'content'],
|
|
211
|
-
},
|
|
212
|
-
platforms: ['discord'],
|
|
213
|
-
tags: ['discord'],
|
|
214
|
-
execute: async (args) => {
|
|
215
|
-
const endpoint = getGatewayBot(args.endpoint_id);
|
|
216
|
-
const tagList = args.tags ? args.tags.split(',').map((t) => t.trim()) : undefined;
|
|
217
|
-
const thread = await endpoint.createForumPost(args.channel_id, args.name, args.content, tagList);
|
|
218
|
-
return { success: true, thread_id: thread.id, message: `论坛帖 "${args.name}" 已创建` };
|
|
219
|
-
},
|
|
220
|
-
}, plugin.name));
|
|
221
|
-
return () => disposers.forEach(d => d());
|
|
222
|
-
});
|
|
223
|
-
// ── Web 控制台 ─────────────────────────────────────────────────────────
|
|
224
|
-
useContext("web", (pageManager) => {
|
|
225
|
-
pageManager.addEntry({
|
|
226
|
-
id: "discord",
|
|
227
|
-
development: path.resolve(import.meta.dirname, "../client/index.tsx"),
|
|
228
|
-
production: path.resolve(import.meta.dirname, "../dist/index.js"),
|
|
229
|
-
meta: { name: "Discord" },
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
useContext("router", "discord", (router, discord) => {
|
|
233
|
-
router.get("/api/discord/endpoints", async (ctx) => {
|
|
234
|
-
try {
|
|
235
|
-
const endpoints = Array.from(discord.endpoints.values());
|
|
236
|
-
const result = endpoints.map((endpoint) => {
|
|
237
|
-
try {
|
|
238
|
-
const client = endpoint.client || endpoint;
|
|
239
|
-
return {
|
|
240
|
-
name: endpoint.$config.name,
|
|
241
|
-
connected: endpoint.$connected || false,
|
|
242
|
-
mode: endpoint.$config.connection || "gateway",
|
|
243
|
-
guildCount: client.guilds?.cache?.size || 0,
|
|
244
|
-
channelCount: client.channels?.cache?.size || 0,
|
|
245
|
-
status: endpoint.$connected ? "online" : "offline",
|
|
246
|
-
user: client.user ? { tag: client.user.tag, id: client.user.id } : null,
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
catch {
|
|
250
|
-
return { name: endpoint.$config.name, connected: false, mode: "unknown", guildCount: 0, channelCount: 0, status: "error", user: null };
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
ctx.body = { success: true, data: result };
|
|
254
|
-
}
|
|
255
|
-
catch {
|
|
256
|
-
ctx.status = 500;
|
|
257
|
-
ctx.body = { success: false, error: "获取 Endpoint 数据失败" };
|
|
258
|
-
}
|
|
259
|
-
});
|
|
260
|
-
// Endpoint 连接/断开
|
|
261
|
-
router.post("/api/discord/endpoints/:name/connect", async (ctx) => {
|
|
262
|
-
try {
|
|
263
|
-
const endpoint = discord.endpoints.get(ctx.params.name);
|
|
264
|
-
if (!endpoint) {
|
|
265
|
-
ctx.status = 404;
|
|
266
|
-
ctx.body = { success: false, error: "Endpoint 不存在" };
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (endpoint.$connected) {
|
|
270
|
-
ctx.body = { success: true, message: "已经在线" };
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
await endpoint.$connect();
|
|
274
|
-
ctx.body = { success: true, message: "连接成功" };
|
|
275
|
-
}
|
|
276
|
-
catch (e) {
|
|
277
|
-
ctx.status = 500;
|
|
278
|
-
ctx.body = { success: false, error: e instanceof Error ? e.message : "连接失败" };
|
|
279
|
-
}
|
|
280
|
-
});
|
|
281
|
-
router.post("/api/discord/endpoints/:name/disconnect", async (ctx) => {
|
|
282
|
-
try {
|
|
283
|
-
const endpoint = discord.endpoints.get(ctx.params.name);
|
|
284
|
-
if (!endpoint) {
|
|
285
|
-
ctx.status = 404;
|
|
286
|
-
ctx.body = { success: false, error: "Endpoint 不存在" };
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
if (!endpoint.$connected) {
|
|
290
|
-
ctx.body = { success: true, message: "已经离线" };
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
await endpoint.$disconnect();
|
|
294
|
-
ctx.body = { success: true, message: "已断开" };
|
|
295
|
-
}
|
|
296
|
-
catch (e) {
|
|
297
|
-
ctx.status = 500;
|
|
298
|
-
ctx.body = { success: false, error: e instanceof Error ? e.message : "断开失败" };
|
|
299
|
-
}
|
|
300
|
-
});
|
|
301
|
-
// 服务器列表(仅 Gateway 模式)
|
|
302
|
-
router.get("/api/discord/endpoints/:name/guilds", async (ctx) => {
|
|
303
|
-
try {
|
|
304
|
-
const endpoint = discord.endpoints.get(ctx.params.name);
|
|
305
|
-
if (!endpoint) {
|
|
306
|
-
ctx.status = 404;
|
|
307
|
-
ctx.body = { success: false, error: "Endpoint 不存在" };
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
if (!endpoint.$connected) {
|
|
311
|
-
ctx.status = 400;
|
|
312
|
-
ctx.body = { success: false, error: "Endpoint 未连接" };
|
|
313
|
-
return;
|
|
314
|
-
}
|
|
315
|
-
const client = endpoint.client || endpoint;
|
|
316
|
-
const guilds = client.guilds?.cache?.map((g) => ({
|
|
317
|
-
id: g.id,
|
|
318
|
-
name: g.name,
|
|
319
|
-
memberCount: g.memberCount,
|
|
320
|
-
icon: g.iconURL({ size: 64 }),
|
|
321
|
-
})) || [];
|
|
322
|
-
ctx.body = { success: true, data: guilds };
|
|
323
|
-
}
|
|
324
|
-
catch (e) {
|
|
325
|
-
ctx.status = 500;
|
|
326
|
-
ctx.body = { success: false, error: e instanceof Error ? e.message : "获取服务器列表失败" };
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
});
|
|
330
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { activityTypeCode, formatButtonContent, formatInboundContent, formatOutboundBody, resolveChannelKind, resolveDiscordConfig, senderDisplayName, } from './protocol.js';
|
|
2
|
+
export { getDiscordAgentDeps, registerDiscordAgentEndpoint, setDiscordAgentDeps, } from './discord-agent-deps.js';
|
|
3
|
+
export { checkDiscordPlatformPermit, discordGroupPermitResolver, normalizeDiscordSenderForPermit, platformPermit, registerDiscordPlatformPermitChecker, } from './platform-permit.js';
|
|
4
|
+
export { DiscordGatewayEndpoint, DiscordInteractionsEndpoint, } from './endpoint.js';
|
|
5
|
+
export { connectDiscordGatewayClient, defaultCreateClient, normalizeDiscordMessage, resolveSenderRole, toMessageCreateOptions, } from './gateway.js';
|
|
6
|
+
export { handleDiscordInteractionRequest, registerDiscordInteractionRoutes, } from './webhook.js';
|
package/lib/platform-permit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Discord platform permit — Guild 权限位
|
|
3
3
|
*/
|
|
4
|
-
import type
|
|
4
|
+
import { type Message } from '@zhin.js/core';
|
|
5
5
|
export declare function platformPermit(perm: string): string;
|
|
6
6
|
export declare function discordGroupPermitResolver(logicalPerm: string): string;
|
|
7
7
|
export declare function normalizeDiscordSenderForPermit(input: {
|
|
@@ -13,4 +13,3 @@ export declare function normalizeDiscordSenderForPermit(input: {
|
|
|
13
13
|
};
|
|
14
14
|
export declare function checkDiscordPlatformPermit(perm: string, message: Message<any>): boolean;
|
|
15
15
|
export declare function registerDiscordPlatformPermitChecker(): () => void;
|
|
16
|
-
//# sourceMappingURL=platform-permit.d.ts.map
|
package/lib/platform-permit.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Discord platform permit — Guild 权限位
|
|
3
|
+
*/
|
|
4
|
+
import { registerPlatformPermitChecker } from '@zhin.js/core';
|
|
2
5
|
const ADAPTER = 'discord';
|
|
3
6
|
export function platformPermit(perm) {
|
|
4
7
|
return `platform(${ADAPTER},${perm})`;
|
|
@@ -47,4 +50,3 @@ export function checkDiscordPlatformPermit(perm, message) {
|
|
|
47
50
|
export function registerDiscordPlatformPermitChecker() {
|
|
48
51
|
return registerPlatformPermitChecker(ADAPTER, checkDiscordPlatformPermit);
|
|
49
52
|
}
|
|
50
|
-
//# sourceMappingURL=platform-permit.js.map
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord Gateway protocol helpers — no legacy Adapter/Endpoint / segment-mapper.
|
|
3
|
+
* Canonicalization is owned by gateway/core before endpoint.send.
|
|
4
|
+
*/
|
|
5
|
+
/** Plugin Runtime owner config (`plugins.<instanceKey>` / schema.json). */
|
|
6
|
+
export interface DiscordAdapterConfig {
|
|
7
|
+
readonly name?: string;
|
|
8
|
+
readonly token?: string;
|
|
9
|
+
/** Default `gateway`. `interactions` uses httpHostToken POST + Ed25519 verify. */
|
|
10
|
+
readonly connection?: 'gateway' | 'interactions';
|
|
11
|
+
readonly intents?: readonly number[];
|
|
12
|
+
readonly enableSlashCommands?: boolean;
|
|
13
|
+
readonly globalCommands?: boolean;
|
|
14
|
+
readonly defaultActivity?: {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly type: 'PLAYING' | 'STREAMING' | 'LISTENING' | 'WATCHING' | 'COMPETING';
|
|
17
|
+
readonly url?: string;
|
|
18
|
+
};
|
|
19
|
+
readonly slashCommands?: readonly Record<string, unknown>[];
|
|
20
|
+
/** Interactions-only fields. */
|
|
21
|
+
readonly applicationId?: string;
|
|
22
|
+
readonly publicKey?: string;
|
|
23
|
+
readonly interactionsPath?: string;
|
|
24
|
+
/** Transitional: legacy root `endpoints[]` with `context: discord`. */
|
|
25
|
+
readonly endpoints?: ReadonlyArray<{
|
|
26
|
+
readonly context?: string;
|
|
27
|
+
readonly name?: string;
|
|
28
|
+
readonly token?: string;
|
|
29
|
+
readonly connection?: 'gateway' | 'interactions';
|
|
30
|
+
readonly intents?: readonly number[];
|
|
31
|
+
readonly enableSlashCommands?: boolean;
|
|
32
|
+
readonly globalCommands?: boolean;
|
|
33
|
+
readonly defaultActivity?: DiscordAdapterConfig['defaultActivity'];
|
|
34
|
+
readonly slashCommands?: readonly Record<string, unknown>[];
|
|
35
|
+
readonly applicationId?: string;
|
|
36
|
+
readonly publicKey?: string;
|
|
37
|
+
readonly interactionsPath?: string;
|
|
38
|
+
}>;
|
|
39
|
+
}
|
|
40
|
+
export interface ResolvedDiscordGatewayConfig {
|
|
41
|
+
readonly context: 'discord';
|
|
42
|
+
readonly connection: 'gateway';
|
|
43
|
+
readonly name: string;
|
|
44
|
+
readonly token: string;
|
|
45
|
+
readonly intents?: readonly number[];
|
|
46
|
+
readonly enableSlashCommands: boolean;
|
|
47
|
+
readonly globalCommands: boolean;
|
|
48
|
+
readonly defaultActivity?: DiscordAdapterConfig['defaultActivity'];
|
|
49
|
+
readonly slashCommands?: readonly Record<string, unknown>[];
|
|
50
|
+
}
|
|
51
|
+
export interface ResolvedDiscordInteractionsConfig {
|
|
52
|
+
readonly context: 'discord';
|
|
53
|
+
readonly connection: 'interactions';
|
|
54
|
+
readonly name: string;
|
|
55
|
+
readonly token: string;
|
|
56
|
+
readonly applicationId: string;
|
|
57
|
+
readonly publicKey: string;
|
|
58
|
+
readonly interactionsPath: string;
|
|
59
|
+
}
|
|
60
|
+
export type ResolvedDiscordConfig = ResolvedDiscordGatewayConfig | ResolvedDiscordInteractionsConfig;
|
|
61
|
+
export interface DiscordInboundAttachment {
|
|
62
|
+
readonly id?: string;
|
|
63
|
+
readonly name?: string;
|
|
64
|
+
readonly url?: string;
|
|
65
|
+
readonly contentType?: string;
|
|
66
|
+
readonly size?: number;
|
|
67
|
+
}
|
|
68
|
+
export interface DiscordInboundMessage {
|
|
69
|
+
readonly id: string;
|
|
70
|
+
readonly content: string;
|
|
71
|
+
readonly channelId: string;
|
|
72
|
+
readonly channelKind: 'private' | 'group' | 'channel';
|
|
73
|
+
readonly authorId: string;
|
|
74
|
+
readonly authorName: string;
|
|
75
|
+
readonly authorBot?: boolean;
|
|
76
|
+
readonly createdTimestamp: number;
|
|
77
|
+
readonly guildId?: string;
|
|
78
|
+
readonly isGuildOwner?: boolean;
|
|
79
|
+
readonly permissionTokens?: readonly string[];
|
|
80
|
+
readonly attachments?: readonly DiscordInboundAttachment[];
|
|
81
|
+
readonly embedTitles?: readonly string[];
|
|
82
|
+
readonly stickerNames?: readonly string[];
|
|
83
|
+
readonly replyToId?: string;
|
|
84
|
+
/** 入站 mentions 数组含 bot 用户时由 gateway connect 装配标注(Message.content 纯文本,@ 只能走 metadata)。 */
|
|
85
|
+
readonly mentionedBot?: boolean;
|
|
86
|
+
}
|
|
87
|
+
export interface DiscordButtonInbound {
|
|
88
|
+
readonly id: string;
|
|
89
|
+
readonly customId: string;
|
|
90
|
+
readonly channelId: string;
|
|
91
|
+
readonly channelKind: 'private' | 'group' | 'channel';
|
|
92
|
+
readonly userId: string;
|
|
93
|
+
readonly userName: string;
|
|
94
|
+
readonly sourceMessageId?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface DiscordWireSegment {
|
|
97
|
+
readonly type: string;
|
|
98
|
+
readonly data?: Record<string, unknown>;
|
|
99
|
+
}
|
|
100
|
+
export interface DiscordOutboundComponentButton {
|
|
101
|
+
type: 2;
|
|
102
|
+
custom_id: string;
|
|
103
|
+
label: string;
|
|
104
|
+
style: number;
|
|
105
|
+
disabled?: boolean;
|
|
106
|
+
}
|
|
107
|
+
export interface DiscordOutboundActionRow {
|
|
108
|
+
type: 1;
|
|
109
|
+
components: DiscordOutboundComponentButton[];
|
|
110
|
+
}
|
|
111
|
+
export interface DiscordOutboundBody {
|
|
112
|
+
readonly content?: string;
|
|
113
|
+
readonly embeds?: ReadonlyArray<Record<string, unknown>>;
|
|
114
|
+
readonly files?: ReadonlyArray<{
|
|
115
|
+
name: string;
|
|
116
|
+
url?: string;
|
|
117
|
+
file?: string;
|
|
118
|
+
}>;
|
|
119
|
+
readonly components?: ReadonlyArray<DiscordOutboundActionRow>;
|
|
120
|
+
}
|
|
121
|
+
export declare function resolveDiscordConfig(config?: DiscordAdapterConfig): ResolvedDiscordConfig;
|
|
122
|
+
export declare function resolveChannelKind(channelType: number | string | undefined): 'private' | 'group' | 'channel';
|
|
123
|
+
export declare function senderDisplayName(msg: DiscordInboundMessage): string;
|
|
124
|
+
/** Build inbound text for MessageGateway.receive (gateway owns reply routing). */
|
|
125
|
+
export declare function formatInboundContent(msg: DiscordInboundMessage): string;
|
|
126
|
+
export declare function formatButtonContent(interaction: DiscordButtonInbound): string;
|
|
127
|
+
/**
|
|
128
|
+
* Wire-encode an already-rendered outbound payload into Discord message body.
|
|
129
|
+
* Segment canonicalization is intentionally not done here.
|
|
130
|
+
*/
|
|
131
|
+
export declare function formatOutboundBody(payload: unknown): DiscordOutboundBody;
|
|
132
|
+
export declare function activityTypeCode(type: NonNullable<DiscordAdapterConfig['defaultActivity']>['type']): number;
|
|
133
|
+
export declare function verifyDiscordInteractionSignature(publicKeyHex: string, body: string, signature: string, timestamp: string): boolean;
|
|
134
|
+
export declare function formatSlashCommandContent(interaction: Record<string, unknown>): string;
|
|
135
|
+
export declare function interactionToInboundMessage(interaction: Record<string, unknown>): DiscordInboundMessage;
|