@zhin.js/adapter-discord 2.0.12 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -3
- package/README.md +6 -6
- package/client/Dashboard.tsx +33 -33
- package/dist/index.js +1 -1
- package/lib/adapter.d.ts +14 -13
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +50 -49
- package/lib/adapter.js.map +1 -1
- package/lib/{bot-interactions.d.ts → endpoint-interactions.d.ts} +4 -4
- package/lib/endpoint-interactions.d.ts.map +1 -0
- package/lib/{bot-interactions.js → endpoint-interactions.js} +4 -4
- package/lib/endpoint-interactions.js.map +1 -0
- package/lib/{bot.d.ts → endpoint.d.ts} +4 -4
- package/lib/endpoint.d.ts.map +1 -0
- package/lib/{bot.js → endpoint.js} +73 -42
- package/lib/endpoint.js.map +1 -0
- package/lib/index.d.ts +3 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +78 -71
- package/lib/index.js.map +1 -1
- package/lib/platform-permit.d.ts +16 -0
- package/lib/platform-permit.d.ts.map +1 -0
- package/lib/platform-permit.js +50 -0
- package/lib/platform-permit.js.map +1 -0
- package/lib/types.d.ts +3 -3
- package/lib/types.d.ts.map +1 -1
- package/package.json +11 -9
- package/skills/discord/PERMITS.md +25 -0
- package/skills/discord/SKILL.md +1 -1
- package/src/adapter.ts +48 -46
- package/src/{bot-interactions.ts → endpoint-interactions.ts} +5 -5
- package/src/{bot.ts → endpoint.ts} +73 -43
- package/src/index.ts +82 -70
- package/src/platform-permit.ts +65 -0
- package/src/types.ts +3 -3
- package/lib/bot-interactions.d.ts.map +0 -1
- package/lib/bot-interactions.js.map +0 -1
- package/lib/bot.d.ts.map +0 -1
- package/lib/bot.js.map +0 -1
package/src/adapter.ts
CHANGED
|
@@ -3,91 +3,93 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Adapter, Plugin } from "zhin.js";
|
|
5
5
|
import type { Router } from "@zhin.js/host-router";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { DiscordEndpoint } from "./endpoint.js";
|
|
7
|
+
import { DiscordInteractionsEndpoint } from "./endpoint-interactions.js";
|
|
8
8
|
import type {
|
|
9
|
-
|
|
9
|
+
DiscordEndpointConfig,
|
|
10
10
|
DiscordGatewayConfig,
|
|
11
11
|
DiscordInteractionsConfig,
|
|
12
12
|
} from "./types.js";
|
|
13
13
|
|
|
14
|
-
export type
|
|
14
|
+
export type DiscordEndpointLike = DiscordEndpoint | DiscordInteractionsEndpoint;
|
|
15
15
|
|
|
16
|
-
function isGatewayBot(
|
|
17
|
-
return (
|
|
16
|
+
function isGatewayBot(endpoint: DiscordEndpointLike): endpoint is DiscordEndpoint {
|
|
17
|
+
return (endpoint.$config as { connection?: string }).connection === "gateway";
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export class DiscordAdapter extends Adapter<
|
|
20
|
+
export class DiscordAdapter extends Adapter<DiscordEndpointLike> {
|
|
21
|
+
static override readonly capabilities = ['inbound', 'outbound'] as const;
|
|
22
|
+
|
|
21
23
|
#router?: Router;
|
|
22
24
|
|
|
23
25
|
constructor(plugin: Plugin) {
|
|
24
26
|
super(plugin, "discord", []);
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
createEndpoint(config: DiscordEndpointConfig): DiscordEndpointLike {
|
|
28
30
|
const connection = config.connection ?? "gateway";
|
|
29
31
|
switch (connection) {
|
|
30
32
|
case "gateway":
|
|
31
|
-
return new
|
|
33
|
+
return new DiscordEndpoint(this, config as DiscordGatewayConfig);
|
|
32
34
|
case "interactions":
|
|
33
35
|
if (!this.#router) {
|
|
34
36
|
throw new Error(
|
|
35
37
|
"Discord connection: interactions 需要 router,请安装并在配置中启用 @zhin.js/host-router"
|
|
36
38
|
);
|
|
37
39
|
}
|
|
38
|
-
return new
|
|
40
|
+
return new DiscordInteractionsEndpoint(this, this.#router, config as DiscordInteractionsConfig);
|
|
39
41
|
default:
|
|
40
|
-
throw new Error(`Unknown Discord connection: ${(config as
|
|
42
|
+
throw new Error(`Unknown Discord connection: ${(config as DiscordEndpointConfig).connection}`);
|
|
41
43
|
}
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
async kickMember(
|
|
45
|
-
const
|
|
46
|
-
if (!
|
|
47
|
-
if (!isGatewayBot(
|
|
48
|
-
return
|
|
46
|
+
async kickMember(endpointId: string, sceneId: string, userId: string) {
|
|
47
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
48
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
49
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
50
|
+
return endpoint.kickMember(sceneId, userId);
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
async banMember(
|
|
52
|
-
const
|
|
53
|
-
if (!
|
|
54
|
-
if (!isGatewayBot(
|
|
55
|
-
return
|
|
53
|
+
async banMember(endpointId: string, sceneId: string, userId: string, reason?: string) {
|
|
54
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
55
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
56
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
57
|
+
return endpoint.banMember(sceneId, userId, reason);
|
|
56
58
|
}
|
|
57
59
|
|
|
58
|
-
async unbanMember(
|
|
59
|
-
const
|
|
60
|
-
if (!
|
|
61
|
-
if (!isGatewayBot(
|
|
62
|
-
return
|
|
60
|
+
async unbanMember(endpointId: string, sceneId: string, userId: string) {
|
|
61
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
62
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
63
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
64
|
+
return endpoint.unbanMember(sceneId, userId);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
|
-
async muteMember(
|
|
66
|
-
const
|
|
67
|
-
if (!
|
|
68
|
-
if (!isGatewayBot(
|
|
69
|
-
return
|
|
67
|
+
async muteMember(endpointId: string, sceneId: string, userId: string, duration = 600) {
|
|
68
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
69
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
70
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
71
|
+
return endpoint.timeoutMember(sceneId, userId, duration);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
|
-
async setMemberNickname(
|
|
73
|
-
const
|
|
74
|
-
if (!
|
|
75
|
-
if (!isGatewayBot(
|
|
76
|
-
return
|
|
74
|
+
async setMemberNickname(endpointId: string, sceneId: string, userId: string, nickname: string) {
|
|
75
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
76
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
77
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
78
|
+
return endpoint.setNickname(sceneId, userId, nickname);
|
|
77
79
|
}
|
|
78
80
|
|
|
79
|
-
async listMembers(
|
|
80
|
-
const
|
|
81
|
-
if (!
|
|
82
|
-
if (!isGatewayBot(
|
|
83
|
-
return
|
|
81
|
+
async listMembers(endpointId: string, sceneId: string) {
|
|
82
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
83
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
84
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
85
|
+
return endpoint.getMembers(sceneId);
|
|
84
86
|
}
|
|
85
87
|
|
|
86
|
-
async getGroupInfo(
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
if (!isGatewayBot(
|
|
90
|
-
return
|
|
88
|
+
async getGroupInfo(endpointId: string, sceneId: string) {
|
|
89
|
+
const endpoint = this.endpoints.get(endpointId);
|
|
90
|
+
if (!endpoint) throw new Error(`Endpoint ${endpointId} 不存在`);
|
|
91
|
+
if (!isGatewayBot(endpoint)) throw new Error("群管仅支持 connection: gateway");
|
|
92
|
+
return endpoint.getGuildInfo(sceneId);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
async start(): Promise<void> {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Discord Interactions
|
|
2
|
+
* Discord Interactions Endpoint 实现
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
5
|
Client,
|
|
@@ -21,14 +21,14 @@ import {
|
|
|
21
21
|
InteractionResponseType,
|
|
22
22
|
} from "discord.js";
|
|
23
23
|
import nacl from "tweetnacl";
|
|
24
|
-
import {
|
|
24
|
+
import { Endpoint, Message, SendOptions, SendContent, MessageSegment, segment } from "zhin.js";
|
|
25
25
|
import { registerFetchRoute, type Router, type RouterContext } from "@zhin.js/host-router/router";
|
|
26
26
|
import type { DiscordInteractionsConfig } from "./types.js";
|
|
27
27
|
import type { DiscordAdapter } from "./adapter.js";
|
|
28
28
|
|
|
29
|
-
export class
|
|
29
|
+
export class DiscordInteractionsEndpoint
|
|
30
30
|
extends Client
|
|
31
|
-
implements
|
|
31
|
+
implements Endpoint<DiscordInteractionsConfig, any> {
|
|
32
32
|
$connected: boolean;
|
|
33
33
|
private router: Router;
|
|
34
34
|
private slashCommandHandlers: Map<
|
|
@@ -171,7 +171,7 @@ export class DiscordInteractionsBot
|
|
|
171
171
|
return Message.from(interaction, {
|
|
172
172
|
$id: interaction.id,
|
|
173
173
|
$adapter: "discord",
|
|
174
|
-
$
|
|
174
|
+
$endpoint: this.$config.name,
|
|
175
175
|
$sender: {
|
|
176
176
|
id: interaction.user?.id || interaction.member?.user?.id,
|
|
177
177
|
name: interaction.user?.username || interaction.member?.user?.username,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Discord
|
|
2
|
+
* Discord Endpoint 实现 (Gateway)
|
|
3
3
|
*/
|
|
4
4
|
import {
|
|
5
5
|
Client,
|
|
@@ -21,9 +21,10 @@ import {
|
|
|
21
21
|
InteractionResponseType,
|
|
22
22
|
GuildMember,
|
|
23
23
|
PermissionsBitField,
|
|
24
|
+
PermissionFlagsBits,
|
|
24
25
|
} from "discord.js";
|
|
25
26
|
import {
|
|
26
|
-
|
|
27
|
+
Endpoint,
|
|
27
28
|
Message,
|
|
28
29
|
SendOptions,
|
|
29
30
|
SendContent,
|
|
@@ -36,9 +37,9 @@ import { createReadStream } from "fs";
|
|
|
36
37
|
import { promises as fs } from "fs";
|
|
37
38
|
import path from "path";
|
|
38
39
|
|
|
39
|
-
export class
|
|
40
|
+
export class DiscordEndpoint
|
|
40
41
|
extends Client
|
|
41
|
-
implements
|
|
42
|
+
implements Endpoint<DiscordGatewayConfig, DiscordChannelMessage> {
|
|
42
43
|
private slashCommandHandlers: Map<
|
|
43
44
|
string,
|
|
44
45
|
(interaction: ChatInputCommandInteraction) => Promise<void>
|
|
@@ -140,7 +141,7 @@ export class DiscordBot
|
|
|
140
141
|
this.once("clientReady", async () => {
|
|
141
142
|
this.$connected = true;
|
|
142
143
|
this.pluginLogger.info(
|
|
143
|
-
`Discord
|
|
144
|
+
`Discord endpoint ${this.$config.name} connected successfully as ${this.user?.tag}`
|
|
144
145
|
);
|
|
145
146
|
|
|
146
147
|
// 设置活动状态
|
|
@@ -179,7 +180,7 @@ export class DiscordBot
|
|
|
179
180
|
try {
|
|
180
181
|
await this.destroy();
|
|
181
182
|
this.$connected = false;
|
|
182
|
-
this.pluginLogger.info(`Discord
|
|
183
|
+
this.pluginLogger.info(`Discord endpoint ${this.$config.name} disconnected`);
|
|
183
184
|
} catch (error) {
|
|
184
185
|
this.pluginLogger.error("Error disconnecting Discord bot:", error);
|
|
185
186
|
throw error;
|
|
@@ -205,14 +206,43 @@ export class DiscordBot
|
|
|
205
206
|
// 转换消息内容为 segment 格式
|
|
206
207
|
const content = this.parseMessageContent(msg);
|
|
207
208
|
|
|
209
|
+
const sender = (() => {
|
|
210
|
+
const base = {
|
|
211
|
+
id: msg.author.id,
|
|
212
|
+
name: msg.member?.displayName || msg.author.displayName,
|
|
213
|
+
} as { id: string; name: string; role?: string; permissions?: string[] };
|
|
214
|
+
const member = msg.member;
|
|
215
|
+
const guild = msg.guild;
|
|
216
|
+
if (member && guild) {
|
|
217
|
+
const tokens: string[] = [];
|
|
218
|
+
const permChecks: Array<[bigint, string]> = [
|
|
219
|
+
[PermissionFlagsBits.Administrator, "ADMINISTRATOR"],
|
|
220
|
+
[PermissionFlagsBits.ManageRoles, "MANAGE_ROLES"],
|
|
221
|
+
[PermissionFlagsBits.ModerateMembers, "MODERATE_MEMBERS"],
|
|
222
|
+
[PermissionFlagsBits.ManageChannels, "MANAGE_CHANNELS"],
|
|
223
|
+
[PermissionFlagsBits.ManageGuild, "MANAGE_GUILD"],
|
|
224
|
+
];
|
|
225
|
+
for (const [bit, name] of permChecks) {
|
|
226
|
+
if (member.permissions.has(bit)) tokens.push(name);
|
|
227
|
+
}
|
|
228
|
+
if (guild.ownerId === msg.author.id) {
|
|
229
|
+
base.role = "owner";
|
|
230
|
+
tokens.push("guild_owner", "ADMINISTRATOR");
|
|
231
|
+
} else if (tokens.includes("ADMINISTRATOR") || tokens.includes("MODERATE_MEMBERS")) {
|
|
232
|
+
base.role = "admin";
|
|
233
|
+
} else {
|
|
234
|
+
base.role = "member";
|
|
235
|
+
}
|
|
236
|
+
base.permissions = tokens;
|
|
237
|
+
}
|
|
238
|
+
return base;
|
|
239
|
+
})();
|
|
240
|
+
|
|
208
241
|
const result = Message.from(msg, {
|
|
209
242
|
$id: msg.id,
|
|
210
243
|
$adapter: "discord",
|
|
211
|
-
$
|
|
212
|
-
$sender:
|
|
213
|
-
id: msg.author.id,
|
|
214
|
-
name: msg.member?.displayName || msg.author.displayName,
|
|
215
|
-
},
|
|
244
|
+
$endpoint: this.$config.name,
|
|
245
|
+
$sender: sender,
|
|
216
246
|
$channel: {
|
|
217
247
|
id: channelId,
|
|
218
248
|
type: channelType,
|
|
@@ -246,7 +276,7 @@ export class DiscordBot
|
|
|
246
276
|
|
|
247
277
|
const res = await this.adapter.sendMessage({
|
|
248
278
|
context: "discord",
|
|
249
|
-
|
|
279
|
+
endpoint: this.$config.name,
|
|
250
280
|
id: msg.channel.id,
|
|
251
281
|
type: msg.channel.type as any,
|
|
252
282
|
content: content,
|
|
@@ -627,10 +657,10 @@ export class DiscordBot
|
|
|
627
657
|
const guild = await this.guilds.fetch(guildId);
|
|
628
658
|
const member = await guild.members.fetch(userId);
|
|
629
659
|
await member.kick(reason);
|
|
630
|
-
this.pluginLogger.info(`Discord
|
|
660
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 踢出成员 ${userId}(服务器 ${guildId})`);
|
|
631
661
|
return true;
|
|
632
662
|
} catch (error) {
|
|
633
|
-
this.pluginLogger.error(`Discord
|
|
663
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 踢出成员失败:`, error);
|
|
634
664
|
throw error;
|
|
635
665
|
}
|
|
636
666
|
}
|
|
@@ -646,10 +676,10 @@ export class DiscordBot
|
|
|
646
676
|
try {
|
|
647
677
|
const guild = await this.guilds.fetch(guildId);
|
|
648
678
|
await guild.members.ban(userId, { reason, deleteMessageSeconds: deleteMessageDays ? deleteMessageDays * 86400 : undefined });
|
|
649
|
-
this.pluginLogger.info(`Discord
|
|
679
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 封禁成员 ${userId}(服务器 ${guildId})`);
|
|
650
680
|
return true;
|
|
651
681
|
} catch (error) {
|
|
652
|
-
this.pluginLogger.error(`Discord
|
|
682
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 封禁成员失败:`, error);
|
|
653
683
|
throw error;
|
|
654
684
|
}
|
|
655
685
|
}
|
|
@@ -664,10 +694,10 @@ export class DiscordBot
|
|
|
664
694
|
try {
|
|
665
695
|
const guild = await this.guilds.fetch(guildId);
|
|
666
696
|
await guild.members.unban(userId, reason);
|
|
667
|
-
this.pluginLogger.info(`Discord
|
|
697
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 解除封禁 ${userId}(服务器 ${guildId})`);
|
|
668
698
|
return true;
|
|
669
699
|
} catch (error) {
|
|
670
|
-
this.pluginLogger.error(`Discord
|
|
700
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 解除封禁失败:`, error);
|
|
671
701
|
throw error;
|
|
672
702
|
}
|
|
673
703
|
}
|
|
@@ -685,14 +715,14 @@ export class DiscordBot
|
|
|
685
715
|
const member = await guild.members.fetch(userId);
|
|
686
716
|
if (duration === 0) {
|
|
687
717
|
await member.timeout(null, reason);
|
|
688
|
-
this.pluginLogger.info(`Discord
|
|
718
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 取消成员 ${userId} 超时(服务器 ${guildId})`);
|
|
689
719
|
} else {
|
|
690
720
|
await member.timeout(duration * 1000, reason);
|
|
691
|
-
this.pluginLogger.info(`Discord
|
|
721
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 超时成员 ${userId} ${duration}秒(服务器 ${guildId})`);
|
|
692
722
|
}
|
|
693
723
|
return true;
|
|
694
724
|
} catch (error) {
|
|
695
|
-
this.pluginLogger.error(`Discord
|
|
725
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 超时操作失败:`, error);
|
|
696
726
|
throw error;
|
|
697
727
|
}
|
|
698
728
|
}
|
|
@@ -708,10 +738,10 @@ export class DiscordBot
|
|
|
708
738
|
const guild = await this.guilds.fetch(guildId);
|
|
709
739
|
const member = await guild.members.fetch(userId);
|
|
710
740
|
await member.setNickname(nickname);
|
|
711
|
-
this.pluginLogger.info(`Discord
|
|
741
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 设置成员 ${userId} 昵称为 "${nickname}"(服务器 ${guildId})`);
|
|
712
742
|
return true;
|
|
713
743
|
} catch (error) {
|
|
714
|
-
this.pluginLogger.error(`Discord
|
|
744
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 设置昵称失败:`, error);
|
|
715
745
|
throw error;
|
|
716
746
|
}
|
|
717
747
|
}
|
|
@@ -727,10 +757,10 @@ export class DiscordBot
|
|
|
727
757
|
const guild = await this.guilds.fetch(guildId);
|
|
728
758
|
const member = await guild.members.fetch(userId);
|
|
729
759
|
await member.roles.add(roleId);
|
|
730
|
-
this.pluginLogger.info(`Discord
|
|
760
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 给成员 ${userId} 添加角色 ${roleId}(服务器 ${guildId})`);
|
|
731
761
|
return true;
|
|
732
762
|
} catch (error) {
|
|
733
|
-
this.pluginLogger.error(`Discord
|
|
763
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 添加角色失败:`, error);
|
|
734
764
|
throw error;
|
|
735
765
|
}
|
|
736
766
|
}
|
|
@@ -746,10 +776,10 @@ export class DiscordBot
|
|
|
746
776
|
const guild = await this.guilds.fetch(guildId);
|
|
747
777
|
const member = await guild.members.fetch(userId);
|
|
748
778
|
await member.roles.remove(roleId);
|
|
749
|
-
this.pluginLogger.info(`Discord
|
|
779
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 移除成员 ${userId} 的角色 ${roleId}(服务器 ${guildId})`);
|
|
750
780
|
return true;
|
|
751
781
|
} catch (error) {
|
|
752
|
-
this.pluginLogger.error(`Discord
|
|
782
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 移除角色失败:`, error);
|
|
753
783
|
throw error;
|
|
754
784
|
}
|
|
755
785
|
}
|
|
@@ -770,7 +800,7 @@ export class DiscordBot
|
|
|
770
800
|
permissions: role.permissions.bitfield.toString(),
|
|
771
801
|
}));
|
|
772
802
|
} catch (error) {
|
|
773
|
-
this.pluginLogger.error(`Discord
|
|
803
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 获取角色列表失败:`, error);
|
|
774
804
|
throw error;
|
|
775
805
|
}
|
|
776
806
|
}
|
|
@@ -792,7 +822,7 @@ export class DiscordBot
|
|
|
792
822
|
joined_at: member.joinedAt?.toISOString(),
|
|
793
823
|
}));
|
|
794
824
|
} catch (error) {
|
|
795
|
-
this.pluginLogger.error(`Discord
|
|
825
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 获取成员列表失败:`, error);
|
|
796
826
|
throw error;
|
|
797
827
|
}
|
|
798
828
|
}
|
|
@@ -813,7 +843,7 @@ export class DiscordBot
|
|
|
813
843
|
created_at: guild.createdAt?.toISOString(),
|
|
814
844
|
};
|
|
815
845
|
} catch (error) {
|
|
816
|
-
this.pluginLogger.error(`Discord
|
|
846
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 获取服务器信息失败:`, error);
|
|
817
847
|
throw error;
|
|
818
848
|
}
|
|
819
849
|
}
|
|
@@ -825,10 +855,10 @@ export class DiscordBot
|
|
|
825
855
|
const options: any = { name, autoArchiveDuration: autoArchiveDuration || 1440 };
|
|
826
856
|
if (messageId) options.startMessage = messageId;
|
|
827
857
|
const thread = await (channel as TextChannel).threads.create(options);
|
|
828
|
-
this.pluginLogger.info(`Discord
|
|
858
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 创建帖子 "${name}" (channel ${channelId})`);
|
|
829
859
|
return thread;
|
|
830
860
|
} catch (error) {
|
|
831
|
-
this.pluginLogger.error(`Discord
|
|
861
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 创建帖子失败:`, error);
|
|
832
862
|
throw error;
|
|
833
863
|
}
|
|
834
864
|
}
|
|
@@ -839,9 +869,9 @@ export class DiscordBot
|
|
|
839
869
|
if (!channel || !channel.isTextBased()) throw new Error(`Channel ${channelId} 不是文本频道`);
|
|
840
870
|
const message = await (channel as TextChannel).messages.fetch(messageId);
|
|
841
871
|
await message.react(emoji);
|
|
842
|
-
this.pluginLogger.info(`Discord
|
|
872
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 添加反应 ${emoji} (message ${messageId})`);
|
|
843
873
|
} catch (error) {
|
|
844
|
-
this.pluginLogger.error(`Discord
|
|
874
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 添加反应失败:`, error);
|
|
845
875
|
throw error;
|
|
846
876
|
}
|
|
847
877
|
}
|
|
@@ -863,7 +893,7 @@ export class DiscordBot
|
|
|
863
893
|
async $addReaction(messageId: string, emoji: string): Promise<string | null> {
|
|
864
894
|
const ref = this.resolveDiscordMessageRef(messageId);
|
|
865
895
|
if (!ref) {
|
|
866
|
-
this.pluginLogger.warn(`Discord
|
|
896
|
+
this.pluginLogger.warn(`Discord Endpoint ${this.$id} 无法根据 message_id=${messageId} 定位 channel_id,跳过 addReaction`);
|
|
867
897
|
return null;
|
|
868
898
|
}
|
|
869
899
|
|
|
@@ -871,7 +901,7 @@ export class DiscordBot
|
|
|
871
901
|
await this.addReaction(ref.channelId, ref.msgId, emoji);
|
|
872
902
|
return emoji;
|
|
873
903
|
} catch (error) {
|
|
874
|
-
this.pluginLogger.error(`Discord
|
|
904
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 添加 reaction 失败:`, error);
|
|
875
905
|
return null;
|
|
876
906
|
}
|
|
877
907
|
}
|
|
@@ -879,7 +909,7 @@ export class DiscordBot
|
|
|
879
909
|
async $removeReaction(messageId: string, reactionId: string): Promise<void> {
|
|
880
910
|
const ref = this.resolveDiscordMessageRef(messageId);
|
|
881
911
|
if (!ref) {
|
|
882
|
-
this.pluginLogger.warn(`Discord
|
|
912
|
+
this.pluginLogger.warn(`Discord Endpoint ${this.$id} 无法根据 message_id=${messageId} 定位 channel_id,跳过 removeReaction`);
|
|
883
913
|
return;
|
|
884
914
|
}
|
|
885
915
|
|
|
@@ -899,7 +929,7 @@ export class DiscordBot
|
|
|
899
929
|
await targetReaction.users.remove(this.user.id);
|
|
900
930
|
}
|
|
901
931
|
} catch (error) {
|
|
902
|
-
this.pluginLogger.error(`Discord
|
|
932
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 移除 reaction 失败:`, error);
|
|
903
933
|
}
|
|
904
934
|
}
|
|
905
935
|
|
|
@@ -909,10 +939,10 @@ export class DiscordBot
|
|
|
909
939
|
if (!channel || !channel.isTextBased()) throw new Error(`Channel ${channelId} 不是文本频道`);
|
|
910
940
|
const embed = this.createEmbedFromData(embedData);
|
|
911
941
|
const msg = await (channel as TextChannel).send({ embeds: [embed] });
|
|
912
|
-
this.pluginLogger.info(`Discord
|
|
942
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 发送 Embed 到 ${channelId}`);
|
|
913
943
|
return msg;
|
|
914
944
|
} catch (error) {
|
|
915
|
-
this.pluginLogger.error(`Discord
|
|
945
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 发送 Embed 失败:`, error);
|
|
916
946
|
throw error;
|
|
917
947
|
}
|
|
918
948
|
}
|
|
@@ -933,10 +963,10 @@ export class DiscordBot
|
|
|
933
963
|
if (tagIds.length) options.appliedTags = tagIds;
|
|
934
964
|
}
|
|
935
965
|
const thread = await forumChannel.threads.create(options);
|
|
936
|
-
this.pluginLogger.info(`Discord
|
|
966
|
+
this.pluginLogger.info(`Discord Endpoint ${this.$id} 创建论坛帖 "${name}" (channel ${channelId})`);
|
|
937
967
|
return thread;
|
|
938
968
|
} catch (error) {
|
|
939
|
-
this.pluginLogger.error(`Discord
|
|
969
|
+
this.pluginLogger.error(`Discord Endpoint ${this.$id} 创建论坛帖失败:`, error);
|
|
940
970
|
throw error;
|
|
941
971
|
}
|
|
942
972
|
}
|
|
@@ -1092,7 +1122,7 @@ export class DiscordBot
|
|
|
1092
1122
|
}
|
|
1093
1123
|
|
|
1094
1124
|
// ================================================================================================
|
|
1095
|
-
//
|
|
1125
|
+
// DiscordInteractionsEndpoint 类(Interactions 端点模式)
|
|
1096
1126
|
// ================================================================================================
|
|
1097
1127
|
|
|
1098
1128
|
import * as nacl from "tweetnacl";
|