diff --git a/source/Discord/CommandDeployer.ts b/source/Discord/CommandDeployer.ts new file mode 100644 index 0000000..8635562 --- /dev/null +++ b/source/Discord/CommandDeployer.ts @@ -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}.`); + } +} \ No newline at end of file diff --git a/source/Discord/Commands/Groups.ts b/source/Discord/Commands/Groups.ts index bc03974..6b07693 100644 --- a/source/Discord/Commands/Groups.ts +++ b/source/Discord/Commands/Groups.ts @@ -1,20 +1,16 @@ import { SlashCommandBuilder, - Interaction, - CommandInteraction, ChatInputCommandInteraction, MessageFlags, - GuildMemberRoleManager, InteractionReplyOptions, GuildMember, EmbedBuilder, AutocompleteInteraction, - formatEmoji, roleMention, time, userMention + roleMention, time, userMention } from "discord.js"; import {AutocompleteCommand, ChatInteractionCommand, Command} from "./Command"; import {GroupModel} from "../../Models/GroupModel"; import {GroupRepository} from "../../Repositories/GroupRepository"; -import {DatabaseConnection} from "../../Database/DatabaseConnection"; import {Container} from "../../Container/Container"; import {GroupSelection} from "../CommandPartials/GroupSelection"; import {UserError} from "../UserError"; @@ -25,9 +21,6 @@ import {GroupConfigurationTransformers} from "../../Groups/GroupConfigurationTra import {GroupConfigurationRepository} from "../../Repositories/GroupConfigurationRepository"; import {IconCache} from "../../Icons/IconCache"; 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 { private static GOODBYE_MESSAGES: string[] = [ diff --git a/source/Discord/DiscordClient.ts b/source/Discord/DiscordClient.ts index 92c0fc8..89ba606 100644 --- a/source/Discord/DiscordClient.ts +++ b/source/Discord/DiscordClient.ts @@ -53,6 +53,10 @@ export class DiscordClient { }); }) + this.client.on(Events.GuildAvailable, () => { + Container.get("logger").info("Joined Guild?") + }) + this.client.on(Events.InteractionCreate, async (interaction: Interaction) => { const method = this.findCommandMethod(interaction); if (!method) { diff --git a/source/Events/DefaultEvents.ts b/source/Events/DefaultEvents.ts index caee973..538cff5 100644 --- a/source/Events/DefaultEvents.ts +++ b/source/Events/DefaultEvents.ts @@ -2,7 +2,6 @@ import {EventHandler, TimedEvent} from "./EventHandler"; import {Container} from "../Container/Container"; import {ReminderEvent} from "./ReminderEvent"; import {ElementCreatedEvent} from "./ElementCreatedEvent"; -import {ClassNamed} from "../types/Class"; import {sendCreatedNotificationEventHandler} from "./Handlers/SendCreatedNotification"; import {PlaydateModel} from "../Models/PlaydateModel"; diff --git a/source/Groups/GroupConfigurationRenderer.ts b/source/Groups/GroupConfigurationRenderer.ts index 17478be..750e5c0 100644 --- a/source/Groups/GroupConfigurationRenderer.ts +++ b/source/Groups/GroupConfigurationRenderer.ts @@ -13,10 +13,10 @@ import { InteractionCallbackResponse, InteractionEditReplyOptions, InteractionReplyOptions, - InteractionUpdateOptions, italic, + InteractionUpdateOptions, italic, MessageFlags, SelectMenuBuilder, StringSelectMenuBuilder, - StringSelectMenuOptionBuilder, + StringSelectMenuOptionBuilder, TextBasedChannel, UserSelectMenuBuilder } from "discord.js"; import {Logger} from "log4js"; @@ -35,6 +35,8 @@ import {RuntimeGroupConfiguration} from "./RuntimeGroupConfiguration"; import {ChannelId} from "../types/DiscordTypes"; import {IconCache} from "../Icons/IconCache"; import {ifError} from "node:assert"; +import {DiscordClient} from "../Discord/DiscordClient"; +import {channel} from "node:diagnostics_channel"; type UIElementCollection = Record; type UIElement = { @@ -100,7 +102,6 @@ export class GroupConfigurationRenderer { public async setup(interaction: ChatInputCommandInteraction) { let response = await interaction.reply(this.getReplyOptions()); - let exit = false; let eventResponse; const filter = i => i.user.id === interaction.user.id; @@ -111,15 +112,15 @@ export class GroupConfigurationRenderer { } try { - eventResponse = await response.resource?.message?.awaitMessageComponent({ dispose: true, filter: filter, time: 60_000 }); } catch (e) { - Container.get("logger").error("awaiting message component failed: ", e) + break; } + if (!eventResponse || eventResponse.customId === 'exit') { exit = true; continue; @@ -157,8 +158,13 @@ export class GroupConfigurationRenderer { return; } - if (interaction.replied) { - await interaction.deleteReply(); + const message = response.resource?.message + if (!message) { + return; + } + + if (message.deletable) { + await message.delete() } } @@ -190,6 +196,7 @@ export class GroupConfigurationRenderer { embeds: [embed], components: [...this.createActionRowBuildersForMenu(), actionrow], withResponse: true, + flags: MessageFlags.Ephemeral }; } diff --git a/source/deploy.ts b/source/deploy.ts index 52a8f0a..a2f3db9 100644 --- a/source/deploy.ts +++ b/source/deploy.ts @@ -6,11 +6,10 @@ import Definitions from "./Database/definitions"; import {Container} from "./Container/Container"; import {ServiceHint, Services} from "./Container/Services"; import {Logger} from "log4js"; - -import {REST, Routes} from 'discord.js'; import {IconDeployer} from "./Icons/IconDeployer"; import {DiscordClient} from "./Discord/DiscordClient"; import {IconCache} from "./Icons/IconCache"; +import {CommandDeployer} from "./Discord/CommandDeployer"; const container = Container.getInstance(); Services.setup(container, ServiceHint.Deploy) @@ -23,30 +22,13 @@ const logger = container.get("logger"); const client = container.get(DiscordClient.name); 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 () => { - try { - const commandInfos = []; - commands.forEach((command) => { - commandInfos.push(command.definition().toJSON()) - }) - - logger.log(`Started refreshing ${commandInfos.length} application (/) commands.`); + await deployer.deployAvailableServers() +})() - // 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..."); const updater = new DatabaseUpdater(container.get(DatabaseConnection.name));