Moved deployment code to class

This commit is contained in:
Michel Fedde 2025-06-17 19:43:33 +02:00
parent aef26b1cc3
commit 83209f642c
6 changed files with 61 additions and 39 deletions

View file

@ -0,0 +1,37 @@
import {DiscordClient} from "./DiscordClient";
import {Logger} from "log4js";
import {Routes, Snowflake} from "discord.js";
export class CommandDeployer {
constructor(
private readonly client: DiscordClient,
private readonly logger: Logger
) {
}
public async deployAvailableServers() {
const commandInfos = [];
this.client.Commands.allCommands.forEach((command) => {
commandInfos.push(command.definition().toJSON())
})
const guilds = await this.client.RESTClient.get(Routes.userGuilds());
const deployments = guilds.map(guild => {
return this.deployServer(commandInfos, guild.id)
})
await Promise.all(deployments);
}
private async deployServer(commandInfos: object[], serverId: Snowflake) {
this.logger.log(`Started refreshing ${commandInfos.length} application (/) commands for ${serverId}.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await this.client.RESTClient.put(
Routes.applicationGuildCommands(this.client.ApplicationId, serverId),
{ body: commandInfos },
);
this.logger.log(`Successfully reloaded ${commandInfos.length} application (/) commands for ${serverId}.`);
}
}

View file

@ -1,20 +1,16 @@
import { import {
SlashCommandBuilder, SlashCommandBuilder,
Interaction,
CommandInteraction,
ChatInputCommandInteraction, ChatInputCommandInteraction,
MessageFlags, MessageFlags,
GuildMemberRoleManager,
InteractionReplyOptions, InteractionReplyOptions,
GuildMember, GuildMember,
EmbedBuilder, EmbedBuilder,
AutocompleteInteraction, AutocompleteInteraction,
formatEmoji, roleMention, time, userMention roleMention, time, userMention
} from "discord.js"; } from "discord.js";
import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command"; import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command";
import {GroupModel} from "../../Models/GroupModel"; import {GroupModel} from "../../Models/GroupModel";
import {GroupRepository} from "../../Repositories/GroupRepository"; import {GroupRepository} from "../../Repositories/GroupRepository";
import {DatabaseConnection} from "../../Database/DatabaseConnection";
import {Container} from "../../Container/Container"; import {Container} from "../../Container/Container";
import {GroupSelection} from "../CommandPartials/GroupSelection"; import {GroupSelection} from "../CommandPartials/GroupSelection";
import {UserError} from "../UserError"; import {UserError} from "../UserError";
@ -25,9 +21,6 @@ import {GroupConfigurationTransformers} from "../../Groups/GroupConfigurationTra
import {GroupConfigurationRepository} from "../../Repositories/GroupConfigurationRepository"; import {GroupConfigurationRepository} from "../../Repositories/GroupConfigurationRepository";
import {IconCache} from "../../Icons/IconCache"; import {IconCache} from "../../Icons/IconCache";
import {PlaydateRepository} from "../../Repositories/PlaydateRepository"; import {PlaydateRepository} from "../../Repositories/PlaydateRepository";
import playdate from "../../Database/tables/Playdate";
import Commands from "./Commands";
import Groups from "../../Database/tables/Groups";
export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand { export class GroupCommand implements Command, ChatInteractionCommand, AutocompleteCommand {
private static GOODBYE_MESSAGES: string[] = [ private static GOODBYE_MESSAGES: string[] = [

View file

@ -53,6 +53,10 @@ export class DiscordClient {
}); });
}) })
this.client.on(Events.GuildAvailable, () => {
Container.get<Logger>("logger").info("Joined Guild?")
})
this.client.on(Events.InteractionCreate, async (interaction: Interaction) => { this.client.on(Events.InteractionCreate, async (interaction: Interaction) => {
const method = this.findCommandMethod(interaction); const method = this.findCommandMethod(interaction);
if (!method) { if (!method) {

View file

@ -2,7 +2,6 @@ import {EventHandler, TimedEvent} from "./EventHandler";
import {Container} from "../Container/Container"; import {Container} from "../Container/Container";
import {ReminderEvent} from "./ReminderEvent"; import {ReminderEvent} from "./ReminderEvent";
import {ElementCreatedEvent} from "./ElementCreatedEvent"; import {ElementCreatedEvent} from "./ElementCreatedEvent";
import {ClassNamed} from "../types/Class";
import {sendCreatedNotificationEventHandler} from "./Handlers/SendCreatedNotification"; import {sendCreatedNotificationEventHandler} from "./Handlers/SendCreatedNotification";
import {PlaydateModel} from "../Models/PlaydateModel"; import {PlaydateModel} from "../Models/PlaydateModel";

View file

@ -13,10 +13,10 @@ import {
InteractionCallbackResponse, InteractionCallbackResponse,
InteractionEditReplyOptions, InteractionEditReplyOptions,
InteractionReplyOptions, InteractionReplyOptions,
InteractionUpdateOptions, italic, InteractionUpdateOptions, italic, MessageFlags,
SelectMenuBuilder, SelectMenuBuilder,
StringSelectMenuBuilder, StringSelectMenuBuilder,
StringSelectMenuOptionBuilder, StringSelectMenuOptionBuilder, TextBasedChannel,
UserSelectMenuBuilder UserSelectMenuBuilder
} from "discord.js"; } from "discord.js";
import {Logger} from "log4js"; import {Logger} from "log4js";
@ -35,6 +35,8 @@ import {RuntimeGroupConfiguration} from "./RuntimeGroupConfiguration";
import {ChannelId} from "../types/DiscordTypes"; import {ChannelId} from "../types/DiscordTypes";
import {IconCache} from "../Icons/IconCache"; import {IconCache} from "../Icons/IconCache";
import {ifError} from "node:assert"; import {ifError} from "node:assert";
import {DiscordClient} from "../Discord/DiscordClient";
import {channel} from "node:diagnostics_channel";
type UIElementCollection = Record<string, UIElement>; type UIElementCollection = Record<string, UIElement>;
type UIElement = { type UIElement = {
@ -100,7 +102,6 @@ export class GroupConfigurationRenderer {
public async setup(interaction: ChatInputCommandInteraction) { public async setup(interaction: ChatInputCommandInteraction) {
let response = await interaction.reply(this.getReplyOptions()); let response = await interaction.reply(this.getReplyOptions());
let exit = false; let exit = false;
let eventResponse; let eventResponse;
const filter = i => i.user.id === interaction.user.id; const filter = i => i.user.id === interaction.user.id;
@ -111,15 +112,15 @@ export class GroupConfigurationRenderer {
} }
try { try {
eventResponse = await response.resource?.message?.awaitMessageComponent({ eventResponse = await response.resource?.message?.awaitMessageComponent({
dispose: true, dispose: true,
filter: filter, filter: filter,
time: 60_000 time: 60_000
}); });
} catch (e) { } catch (e) {
Container.get<Logger>("logger").error("awaiting message component failed: ", e) break;
} }
if (!eventResponse || eventResponse.customId === 'exit') { if (!eventResponse || eventResponse.customId === 'exit') {
exit = true; exit = true;
continue; continue;
@ -157,8 +158,13 @@ export class GroupConfigurationRenderer {
return; return;
} }
if (interaction.replied) { const message = response.resource?.message
await interaction.deleteReply(); if (!message) {
return;
}
if (message.deletable) {
await message.delete()
} }
} }
@ -190,6 +196,7 @@ export class GroupConfigurationRenderer {
embeds: [embed], embeds: [embed],
components: [...this.createActionRowBuildersForMenu(), actionrow], components: [...this.createActionRowBuildersForMenu(), actionrow],
withResponse: true, withResponse: true,
flags: MessageFlags.Ephemeral
}; };
} }

View file

@ -6,11 +6,10 @@ import Definitions from "./Database/definitions";
import {Container} from "./Container/Container"; import {Container} from "./Container/Container";
import {ServiceHint, Services} from "./Container/Services"; import {ServiceHint, Services} from "./Container/Services";
import {Logger} from "log4js"; import {Logger} from "log4js";
import {REST, Routes} from 'discord.js';
import {IconDeployer} from "./Icons/IconDeployer"; import {IconDeployer} from "./Icons/IconDeployer";
import {DiscordClient} from "./Discord/DiscordClient"; import {DiscordClient} from "./Discord/DiscordClient";
import {IconCache} from "./Icons/IconCache"; import {IconCache} from "./Icons/IconCache";
import {CommandDeployer} from "./Discord/CommandDeployer";
const container = Container.getInstance(); const container = Container.getInstance();
Services.setup(container, ServiceHint.Deploy) Services.setup(container, ServiceHint.Deploy)
@ -23,30 +22,13 @@ const logger = container.get<Logger>("logger");
const client = container.get<DiscordClient>(DiscordClient.name); const client = container.get<DiscordClient>(DiscordClient.name);
client.connectRESTClient(environment.discord.token) client.connectRESTClient(environment.discord.token)
const commands = client.Commands.allCommands; logger.log("Deploying Commands...")
// and deploy your commands! const deployer = new CommandDeployer(client, logger);
(async () => { (async () => {
try { await deployer.deployAvailableServers()
const commandInfos = []; })()
commands.forEach((command) => {
commandInfos.push(command.definition().toJSON())
})
logger.log(`Started refreshing ${commandInfos.length} application (/) commands.`);
// The put method is used to fully refresh all commands in the guild with the current set
const data = await client.RESTClient.put(
Routes.applicationGuildCommands(environment.discord.clientId, environment.discord.guildId),
{ body: commandInfos },
);
logger.log(`Successfully reloaded ${commandInfos.length} application (/) commands.`);
} catch (error) {
// And of course, make sure you catch and log any errors!
logger.error(error);
}
})();
logger.log("Ensuring Database..."); logger.log("Ensuring Database...");
const updater = new DatabaseUpdater(container.get<DatabaseConnection>(DatabaseConnection.name)); const updater = new DatabaseUpdater(container.get<DatabaseConnection>(DatabaseConnection.name));