Skip to content

Commit 7d5d023

Browse files
author
xyzjesper
committed
Updated command for discords API.
1 parent c0ed861 commit 7d5d023

28 files changed

Lines changed: 302 additions & 195 deletions

File tree

src/helper/CommandHelper.ts

Lines changed: 130 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import colors from "colors";
2-
import {Guild, REST, Routes} from "discord.js";
2+
import {ChatInputCommandInteraction, Guild, REST, Routes, SlashCommandBuilder} from "discord.js";
33
import fs from "fs";
44
import path from "path";
55
import {pathToFileURL} from "url";
@@ -10,12 +10,16 @@ import {Logger} from "../main/logger.js";
1010
import {Config} from "../main/config.js";
1111
import {database} from "../main/database.js";
1212
import {cli} from "winston/lib/winston/config/index.js";
13+
import {IDisBotCommand} from "../types/Interaction.js";
14+
import {DisBotInteractionType} from "../enums/disBotInteractionType.js";
1315

1416
colors.enable();
1517

1618
export class CommandHelper {
1719

18-
public static async loadCommandsForGuild(client: ExtendedClient, guild: Guild) {
20+
public static async loadCommandsForGuild(client: ExtendedClient, guildId: string) {
21+
22+
Logger.info(`Starting Command loading for ${guildId}....`.gray.italic)
1923

2024
let cmdlist: any[] = [];
2125
const stats = {
@@ -105,103 +109,94 @@ export class CommandHelper {
105109
throw new Error("Missing Config variables: DiscordApplicationId or DiscordBotToken");
106110
}
107111

108-
const restClient = new REST({version: "10"}).setToken(Config.Bot.DiscordBotToken);
109-
110-
// Clear Guild Commands
111-
await restClient.put(Routes.applicationGuildCommands(Config.Bot.DiscordApplicationId, guild.id), {
112-
body: [],
113-
});
114-
115112
const buildInCommandOverrides = await database.buildInCommands.findMany({
116113
where: {
117-
GuildCommandMangerId: guild.id
114+
GuildCommandMangerId: guildId
118115
}
119116
})
120-
try {
121-
cmdlist = cmdlist
122-
.filter(cmd => {
123-
const override = buildInCommandOverrides.find(o => o.CodeName === cmd.name);
124-
return !(override && override.IsEnabled === false);
125-
})
126-
.map(cmd => {
127-
const override = buildInCommandOverrides.find(o => o.CodeName === cmd.name);
128-
if (override) {
129-
return {
130-
...cmd,
131-
name: override.CustomName,
132-
description: override.Description ?? client.commands.get(override.CodeName).command.description,
133-
default_member_permissions: override.Permissions ?? client.commands.get(override.CodeName).command.default_member_permissions
134-
};
135-
}
136-
return cmd;
137-
})
138117

139-
await restClient.put(Routes.applicationGuildCommands(Config.Bot.DiscordApplicationId, guild.id), {
140-
body: cmdlist,
141-
});
118+
// TODO: ADD COMMAND_OVERWRITES
142119

143-
const ticketCommands = await database.ticketSetups.findMany({
144-
where: {
145-
GuildId: guild.id
146-
}
120+
Logger.info(`Sending commands to guild ${guildId} for client ${client.user.username}`);
121+
122+
try {
123+
const commandReq = await fetch(`https://discord.com/api/v10/applications/${client.user.id}/guilds/${guildId}/commands`, {
124+
method: "PUT",
125+
headers: {
126+
"Content-Type": "application/json",
127+
Authorization: `Bot ${Config.Bot.DiscordBotToken}`
128+
},
129+
body: JSON.stringify(cmdlist)
147130
})
131+
const data = await commandReq.json()
132+
console.log(JSON.stringify(data))
133+
134+
} catch (e) {
135+
Logger.error(`Failed to load commands: ${e}`)
136+
}
137+
138+
const ticketCommands = await database.ticketSetups.findMany({
139+
where: {
140+
GuildId: guildId
141+
}
142+
})
148143

144+
if (ticketCommands.length > 0) {
149145
for (const ticketCommand of ticketCommands) {
150-
const clientGuild = await client.guilds.fetch(guild.id);
146+
const clientGuild = await client.guilds.fetch(guildId);
151147

152148
let guildCommand = null;
153149
try {
154150
guildCommand = await clientGuild.commands.fetch(ticketCommand.SlashCommandId);
155-
} catch {
151+
} catch (e) {
152+
Logger.error(`Failed to load commands: ${e}`)
156153
}
157154

158155
if (!guildCommand) {
159-
guildCommand = await clientGuild.commands.create({
160-
name: ticketCommand.SlashCommandName ?? `open-${ticketCommand.CustomId}-ticket`,
161-
description: ticketCommand.SlashCommandDescription ?? ticketCommand.CustomId,
162-
});
156+
try {
157+
guildCommand = await clientGuild.commands.create({
158+
name: ticketCommand.SlashCommandName ?? `open-${ticketCommand.CustomId}-ticket`,
159+
description: ticketCommand.SlashCommandDescription ?? ticketCommand.CustomId,
160+
});
163161

164-
await database.ticketSetups.update({
165-
where: {
166-
CustomId: ticketCommand.CustomId,
167-
},
168-
data: {
169-
SlashCommandId: guildCommand.id,
170-
},
171-
});
162+
await database.ticketSetups.update({
163+
where: {
164+
CustomId: ticketCommand.CustomId,
165+
},
166+
data: {
167+
SlashCommandId: guildCommand.id,
168+
},
169+
});
170+
} catch (e) {
171+
Logger.error(`Failed to load commands: ${e}`)
172+
}
172173
} else {
173174
if (
174175
guildCommand.name !== ticketCommand.SlashCommandName ||
175176
guildCommand.description !== ticketCommand.SlashCommandDescription
176177
) {
177-
const updated = await guildCommand.edit({
178-
name: ticketCommand.SlashCommandName ?? guildCommand.name,
179-
description: ticketCommand.SlashCommandDescription ?? guildCommand.description,
180-
});
181-
182-
await database.ticketSetups.update({
183-
where: {CustomId: ticketCommand.CustomId},
184-
data: {SlashCommandId: updated.id},
185-
});
178+
try {
179+
const updated = await guildCommand.edit({
180+
name: ticketCommand.SlashCommandName ?? guildCommand.name,
181+
description: ticketCommand.SlashCommandDescription ?? guildCommand.description,
182+
});
183+
184+
await database.ticketSetups.update({
185+
where: {CustomId: ticketCommand.CustomId},
186+
data: {SlashCommandId: updated.id},
187+
});
188+
} catch (e) {
189+
Logger.error(`Failed to load commands: ${e}`)
190+
}
186191
}
187192
}
188193
}
189-
} catch (e) {
190-
Logger.error({
191-
timestamp: new Date().toISOString(),
192-
level: "error",
193-
label: "CommandHelper",
194-
message: `Command loading failed with error: ${e} - Commands failed at ${cmdlist.map((c) => c.name)} commands on Guild \"${guild.name}\" (${guild.id})`,
195-
botType: Config.BotType.toString() || "Unknown",
196-
action: LoggingAction.Command,
197-
});
198194
}
199-
200195
Logger.info({
201196
timestamp: new Date().toISOString(),
202197
level: "info",
203198
label: "CommandHelper",
204-
message: `Discord added ${cmdlist.length} commands (${stats.subCommands} subCommands, ${stats.subCommandGroups} subCommandGroups), ${stats.userInstall} userInstall commands, ${stats.contextMenus} context menu commands from ${moduleDirectories.length} module(s) for \"${guild.name}\" (${guild.id})`,
199+
message: `Discord added ${cmdlist.length} commands (${stats.subCommands} subCommands, ${stats.subCommandGroups} subCommandGroups), ${stats.userInstall} userInstall commands, ${stats.contextMenus} context menu commands from ${moduleDirectories.length} module(s) for ${guildId}`,
205200
botType: Config.BotType.toString() || "Unknown",
206201
action: LoggingAction.Command,
207202
});
@@ -329,11 +324,72 @@ export class CommandHelper {
329324

330325
const guilds = await client.guilds.fetch()
331326
guilds.map(async (guild) => {
332-
const clientGuild = await client.guilds.fetch(guild.id)
333-
await this.loadCommandsForGuild(client, clientGuild)
334-
setTimeout(() => {
335-
}, 1500)
336-
console.log("NEXT GUILD")
327+
await this.loadCommandsForGuild(client, guild.id)
328+
})
329+
}
330+
331+
public static async loadCustomAdminCommands(client: ExtendedClient) {
332+
const guild = await client.guilds.fetch(Config.Bot.AdminGuildId)
333+
334+
const commands = [
335+
{
336+
interactionName: "Load Guild Commands",
337+
type: DisBotInteractionType.Command,
338+
command: new SlashCommandBuilder()
339+
.setName("loadcommands")
340+
.setDescription("Load Commands for all Guilds."),
341+
execute: async (interaction: ChatInputCommandInteraction, client: ExtendedClient) => {
342+
await interaction.deferReply();
343+
344+
const guilds = await client.guilds.fetch();
345+
const guildArray = Array.from(guilds.values());
346+
347+
const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
348+
349+
let processedCount = 0;
350+
let successCount = 0;
351+
let errorCount = 0;
352+
const BATCH_SIZE = 5;
353+
const DELAY_MS = 3000;
354+
355+
for (const guild of guildArray) {
356+
try {
357+
if (processedCount > 0 && processedCount % BATCH_SIZE === 0) {
358+
await interaction.editReply({
359+
content: `-# 📡 Loading commands... (${processedCount}/${guilds.size}) - ⏸️ Waiting 3s...`
360+
});
361+
await delay(DELAY_MS);
362+
}
363+
364+
await CommandHelper.loadCommandsForGuild(client, guild.id);
365+
successCount++;
366+
367+
if (processedCount % 3 === 0 || processedCount === guildArray.length - 1) {
368+
await interaction.editReply({
369+
content: `-# 📡 Loading commands... (${processedCount + 1}/${guilds.size})`
370+
});
371+
}
372+
} catch (error) {
373+
errorCount++;
374+
console.error(`Failed to load commands for guild ${guild.id}:`, error);
375+
} finally {
376+
processedCount++;
377+
}
378+
}
379+
380+
await interaction.editReply({
381+
content: `-# ✅ Commands loaded for ${successCount}/${guilds.size} guild(s)${errorCount > 0 ? ` (${errorCount} failed)` : ''}`
382+
});
383+
}
384+
} as IDisBotCommand
385+
]
386+
387+
388+
commands.map((commandData) => {
389+
client.guildCommands.set(commandData.command.name, commandData)
337390
})
391+
await guild.commands.set(
392+
commands.map((commandData) => commandData.command)
393+
)
338394
}
339395
}

src/main/bot.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
GatewayIntentBits,
77
Guild,
88
Partials,
9-
PresenceStatusData,
9+
PresenceStatusData, SlashCommandBuilder,
1010
} from "discord.js";
1111
import {loadButtons} from "../handler/files/buttons.js";
1212
import {loadCommands} from "../handler/files/commands.js";
@@ -26,6 +26,9 @@ import {versionData} from "./version.js";
2626
import {vote} from "../api/services/vote.js";
2727
import {app} from "../api/services/app.js";
2828
import {vanityAPI} from "../api/services/vanity.js";
29+
import {ConicGradient} from "discord-welcome-card";
30+
import {IDisBotCommand} from "../types/Interaction.js";
31+
import {DisBotInteractionType} from "../enums/disBotInteractionType.js";
2932

3033
colors.enable();
3134

@@ -54,7 +57,7 @@ export const disbotClient = new ExtendedClient(
5457
GatewayIntentBits.GuildScheduledEvents,
5558
GatewayIntentBits.AutoModerationConfiguration,
5659
GatewayIntentBits.GuildModeration,
57-
GatewayIntentBits.GuildMessagePolls,
60+
GatewayIntentBits.GuildMessagePolls
5861
],
5962
partials: Object.keys(Partials).map(key => Partials[key]),
6063
})
@@ -77,11 +80,11 @@ await disbotClient
7780
process.setMaxListeners(0);
7881
disbotClient.setMaxListeners(0);
7982

80-
// Database init (Default)
83+
// Database init (Default)
8184
await initDataToDatabase(disbotClient)
82-
85+
8386
// Load Commands
84-
await CommandHelper.loadCommands(disbotClient);
87+
// await CommandHelper.loadCommands(disbotClient);
8588

8689
// API && Version
8790
await api(disbotClient);
@@ -95,7 +98,7 @@ await disbotClient
9598

9699
})
97100
.catch((err) => {
98-
Logger.error(`Failed to login: ${err instanceof Error ? err.message : String(err)}`);
101+
Logger.error(`Failed to login: ${err}`);
99102
process.exit(1);
100103
});
101104

src/modules/automation/commands/automation.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
ActionRowBuilder,
2+
ActionRowBuilder, ApplicationIntegrationType,
33
ChannelType,
44
ChatInputCommandInteraction,
55
ContainerBuilder,
@@ -33,6 +33,7 @@ export default {
3333
.setDescriptionLocalizations({
3434
de: "Automatisierungen verwalten",
3535
})
36+
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
3637
.setContexts(InteractionContextType.Guild)
3738
.setDefaultMemberPermissions(PermissionFlagsBits.ManageChannels),
3839
help: {

src/modules/backup/commands/backups.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
ActionRowBuilder,
2+
ActionRowBuilder, ApplicationIntegrationType,
33
ButtonBuilder,
44
ButtonStyle,
55
ChatInputCommandInteraction, ContainerBuilder,
@@ -28,6 +28,7 @@ export default {
2828
.setDescriptionLocalizations({
2929
de: "Backups verwalten",
3030
})
31+
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
3132
.setContexts(InteractionContextType.Guild)
3233
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
3334
options: {

src/modules/bot/commands/help.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
ApplicationIntegrationType,
23
ButtonBuilder,
34
ButtonStyle,
45
ChatInputCommandInteraction,
@@ -24,6 +25,7 @@ export default {
2425
.setName("help")
2526
.setDescription("Use this command to get help about the bot")
2627
.setContexts(InteractionContextType.Guild)
28+
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
2729
.setDefaultMemberPermissions(PermissionsBitField.Flags.Administrator),
2830
async execute(interaction: ChatInputCommandInteraction, client: ExtendedClient) {
2931
if (!client.user) throw new Error("Client user not found");

src/modules/bot/events/bot-join.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ export default {
3737
botType: Config.BotType.toString() || "Unknown",
3838
action: LoggingAction.Event,
3939
});
40-
await CommandHelper.loadCommandsForGuild(client, guild);
40+
await CommandHelper.loadCommandsForGuild(client, guild.id);
4141
await initGuildToDatabase(client, guild)
42-
guild.members.cache.forEach(async (member) => {
42+
guild.members.cache.map(async (member) => {
4343
await initUsersToDatabase(client, member.user)
4444
})
4545
}

src/modules/bot/events/bot-ready.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export default {
2525
async execute(client: ExtendedClient) {
2626
try {
2727

28+
// Load Admin Guild Commands
29+
await CommandHelper.loadCustomAdminCommands(client);
30+
2831
// Invite Tracker Fetch
2932
client.guilds.cache.forEach(async (guild: Guild) => {
3033
guildFetcher(client, guild);

src/modules/commands/commands/commands.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {InteractionContextType, PermissionsBitField, SlashCommandBuilder} from "discord.js";
1+
import {ApplicationIntegrationType, InteractionContextType, PermissionsBitField, SlashCommandBuilder} from "discord.js";
22
import {
33
ActionRowBuilder,
44
ButtonBuilder,
@@ -21,6 +21,7 @@ export default {
2121
.setName("commands")
2222
.setDescription("Create, Manage, and use the Command Manager!")
2323
.setContexts(InteractionContextType.Guild)
24+
.setIntegrationTypes(ApplicationIntegrationType.GuildInstall)
2425
.setDefaultMemberPermissions(PermissionFlagsBits.ManageGuild),
2526
options: {
2627
once: false,

0 commit comments

Comments
 (0)