From c5fc99d658c73bc258cc70064218e19ee275c4c7 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Fri, 20 Sep 2024 18:08:27 +0100 Subject: [PATCH 1/6] Add the dropdown menu to the interaction output --- src/buttonEvents/Inventory.ts | 4 ++-- src/commands/inventory.ts | 2 +- src/helpers/InventoryHelper.ts | 21 +++++++++++++++++---- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/buttonEvents/Inventory.ts b/src/buttonEvents/Inventory.ts index 8356305..73c7019 100644 --- a/src/buttonEvents/Inventory.ts +++ b/src/buttonEvents/Inventory.ts @@ -11,7 +11,7 @@ export default class Inventory extends ButtonEvent { const page = interaction.customId.split(" ")[2]; AppLogger.LogSilly("Button/Inventory", `Parameters: userid=${userid}, page=${page}`); - + await interaction.deferUpdate(); const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid); @@ -34,7 +34,7 @@ export default class Inventory extends ButtonEvent { await interaction.editReply({ files: [ embed.image ], embeds: [ embed.embed ], - components: [ embed.row ], + components: [ embed.row1, embed.row2 ], }); } catch (e) { AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`); diff --git a/src/commands/inventory.ts b/src/commands/inventory.ts index 8d2ef2c..deb4735 100644 --- a/src/commands/inventory.ts +++ b/src/commands/inventory.ts @@ -47,7 +47,7 @@ export default class Inventory extends Command { await interaction.followUp({ files: [ embed.image ], embeds: [ embed.embed ], - components: [ embed.row ], + components: [ embed.row1, embed.row2 ], }); } catch (e) { AppLogger.LogError("Commands/Inventory", e as string); diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 8b8ffa1..9075b30 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -1,4 +1,4 @@ -import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuOptionBuilder } from "discord.js"; import Inventory from "../database/entities/app/Inventory"; import { CoreClient } from "../client/client"; import EmbedColours from "../constants/EmbedColours"; @@ -24,7 +24,8 @@ interface InventoryPageCards { interface ReturnedInventoryPage { embed: EmbedBuilder, - row: ActionRowBuilder, + row1: ActionRowBuilder, + row2: ActionRowBuilder, image: AttachmentBuilder, } @@ -99,7 +100,7 @@ export default class InventoryHelper { .setColor(EmbedColours.Ok) .setImage("attachment://page.png"); - const row = new ActionRowBuilder() + const row1 = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId(`inventory ${userid} ${page - 1}`) @@ -112,9 +113,21 @@ export default class InventoryHelper { .setStyle(ButtonStyle.Primary) .setDisabled(page + 1 == pages.length)); + const row2 = new ActionRowBuilder() + .addComponents( + new StringSelectMenuBuilder() + .setCustomId("inventory") + .setPlaceholder(`${currentPage.name} (${currentPage.seriesSubpage + 1})`) + .addOptions(...pages.map(x => + new StringSelectMenuOptionBuilder() + .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) + .setDescription("Quick navigate to page...") + .setDefault(currentPage.id == x.id) + .setValue(x.id.toString())))); + const buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path }))); const image = new AttachmentBuilder(buffer, { name: "page.png" }); - return { embed, row, image }; + return { embed, row1, row2, image }; } } -- 2.43.4 From 39d44cf8dd6a154d936a7f6d0fc1c3d9689882b9 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 21 Sep 2024 12:25:10 +0100 Subject: [PATCH 2/6] Add support to handle string dropdowns --- src/bot.ts | 1 + src/client/client.ts | 23 +++++++++++++++ src/client/events.ts | 4 +++ .../interactionCreate/StringDropdown.ts | 29 +++++++++++++++++++ src/contracts/StringDropdownEventItem.ts | 10 +++++++ src/registry.ts | 3 ++ src/type/stringDropdownEvent.ts | 5 ++++ 7 files changed, 75 insertions(+) create mode 100644 src/client/interactionCreate/StringDropdown.ts create mode 100644 src/contracts/StringDropdownEventItem.ts create mode 100644 src/type/stringDropdownEvent.ts diff --git a/src/bot.ts b/src/bot.ts index e5e25a3..871b927 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -38,6 +38,7 @@ const client = new CoreClient([ Registry.RegisterCommands(); Registry.RegisterButtonEvents(); +Registry.RegisterStringDropdownEvents(); if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") { console.log("Card directory not found, syncing..."); diff --git a/src/client/client.ts b/src/client/client.ts index 117bdb9..87b496e 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -17,11 +17,14 @@ import AppLogger from "./appLogger"; import TimerHelper from "../helpers/TimerHelper"; import GiveCurrency from "../timers/GiveCurrency"; import PurgeClaims from "../timers/PurgeClaims"; +import StringDropdownEventItem from "../contracts/StringDropdownEventItem"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; export class CoreClient extends Client { private static _commandItems: ICommandItem[]; private static _eventExecutors: EventExecutors; private static _buttonEvents: IButtonEventItem[]; + private static _stringDropdowns: StringDropdownEventItem[]; private _events: Events; private _util: Util; @@ -45,6 +48,10 @@ export class CoreClient extends Client { return this._buttonEvents; } + public static get stringDropdowns(): StringDropdownEventItem[] { + return this._stringDropdowns; + } + constructor(intents: number[]) { super({ intents: intents }); dotenv.config(); @@ -59,6 +66,7 @@ export class CoreClient extends Client { CoreClient._commandItems = []; CoreClient._buttonEvents = []; + CoreClient._stringDropdowns = []; this._events = new Events(); this._util = new Util(); @@ -408,4 +416,19 @@ export class CoreClient extends Client { AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`); } } + + public static RegisterStringDropdownEvent(dropdownId: string, event: StringDropdownEvent, environment: Environment = Environment.All) { + const item: StringDropdownEventItem = { + DropdownId: dropdownId, + Event: event, + Environment: environment, + }; + + if ((environment & CoreClient.Environment) == CoreClient.Environment) { + CoreClient._stringDropdowns.push(item); + + AppLogger.LogVerbose("Client", `Registered String Dropdown Event: ${dropdownId}`); + } + } } + diff --git a/src/client/events.ts b/src/client/events.ts index f02fb9c..d5a1441 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -19,6 +19,10 @@ export class Events { AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`); Button.onButtonClicked(interaction); } + + if (interaction.isStringSelectMenu()) { + AppLogger.LogVerbose("Client", `StringDropdown: ${interaction.customId}`); + } } // Emit when bot is logged in and ready to use diff --git a/src/client/interactionCreate/StringDropdown.ts b/src/client/interactionCreate/StringDropdown.ts new file mode 100644 index 0000000..608b81b --- /dev/null +++ b/src/client/interactionCreate/StringDropdown.ts @@ -0,0 +1,29 @@ +import {StringSelectMenuInteraction} from "discord.js"; +import {CoreClient} from "../client"; +import AppLogger from "../appLogger"; + +export default class StringDropdown { + public static async onStringDropdownSelected(interaction: StringSelectMenuInteraction) { + if (!interaction.isStringSelectMenu()) return; + + const item = CoreClient.stringDropdowns.find(x => x.DropdownId == interaction.customId.split(" ")[0]); + + if (!item) { + AppLogger.LogVerbose("StringDropdown", `Event not found: ${interaction.customId}`); + + await interaction.reply("Event not found"); + return; + } + + try { + AppLogger.LogDebug("StringDropdown", `Executing ${interaction.customId}`); + + item.Event.execute(interaction); + } catch (e) { + AppLogger.LogError("StringDropdown", `Error occurred while executing event: ${interaction.customId}`); + AppLogger.LogError("StringDropdown", e as string); + + await interaction.reply("An error occurred while executing the event"); + } + } +} diff --git a/src/contracts/StringDropdownEventItem.ts b/src/contracts/StringDropdownEventItem.ts new file mode 100644 index 0000000..1a7b0aa --- /dev/null +++ b/src/contracts/StringDropdownEventItem.ts @@ -0,0 +1,10 @@ +import {Environment} from "../constants/Environment"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; + +interface StringDropdownEventItem { + DropdownId: string, + Event: StringDropdownEvent, + Environment: Environment, +} + +export default StringDropdownEventItem; diff --git a/src/registry.ts b/src/registry.ts index 1f7f509..f49f97c 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -64,4 +64,7 @@ export default class Registry { CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent()); CoreClient.RegisterButtonEvent("view", new ViewButtonEvent()); } + + public static RegisterStringDropdownEvents() { + } } \ No newline at end of file diff --git a/src/type/stringDropdownEvent.ts b/src/type/stringDropdownEvent.ts new file mode 100644 index 0000000..c097cda --- /dev/null +++ b/src/type/stringDropdownEvent.ts @@ -0,0 +1,5 @@ +import {StringSelectMenuInteraction} from "discord.js"; + +export abstract class StringDropdownEvent { + abstract execute(interaction: StringSelectMenuInteraction): Promise; +} -- 2.43.4 From a71b33d8792dcf64dda0fb16d57afb488b946705 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 21 Sep 2024 12:35:32 +0100 Subject: [PATCH 3/6] Create base inventory dropdown class --- src/client/events.ts | 2 ++ src/registry.ts | 4 ++++ src/stringDropdowns/Inventory.ts | 8 ++++++++ 3 files changed, 14 insertions(+) create mode 100644 src/stringDropdowns/Inventory.ts diff --git a/src/client/events.ts b/src/client/events.ts index d5a1441..5f61da5 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -3,6 +3,7 @@ import ChatInputCommand from "./interactionCreate/ChatInputCommand"; import Button from "./interactionCreate/Button"; import AppLogger from "./appLogger"; import NewUserDiscovery from "./interactionCreate/middleware/NewUserDiscovery"; +import StringDropdown from "./interactionCreate/StringDropdown"; export class Events { public async onInteractionCreate(interaction: Interaction) { @@ -22,6 +23,7 @@ export class Events { if (interaction.isStringSelectMenu()) { AppLogger.LogVerbose("Client", `StringDropdown: ${interaction.customId}`); + StringDropdown.onStringDropdownSelected(interaction); } } diff --git a/src/registry.ts b/src/registry.ts index f49f97c..67936c8 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -31,6 +31,9 @@ import SeriesEvent from "./buttonEvents/Series"; import TradeButtonEvent from "./buttonEvents/Trade"; import ViewButtonEvent from "./buttonEvents/View"; +// String Dropdown Event Imports +import InventoryStringDropdown from "./stringDropdowns/Inventory"; + export default class Registry { public static RegisterCommands() { // Global Commands @@ -66,5 +69,6 @@ export default class Registry { } public static RegisterStringDropdownEvents() { + CoreClient.RegisterStringDropdownEvent("inventory", new InventoryStringDropdown()); } } \ No newline at end of file diff --git a/src/stringDropdowns/Inventory.ts b/src/stringDropdowns/Inventory.ts new file mode 100644 index 0000000..65d16f6 --- /dev/null +++ b/src/stringDropdowns/Inventory.ts @@ -0,0 +1,8 @@ +import {StringSelectMenuInteraction} from "discord.js"; +import {StringDropdownEvent} from "../type/stringDropdownEvent"; + +export default class Inventory extends StringDropdownEvent { + public override async execute(interaction: StringSelectMenuInteraction) { + await interaction.reply(`Test: ${interaction.customId}, ${interaction.values.join(",")}`); + } +} -- 2.43.4 From c115cd92a193f1de1604ac3e41ab1c9a97e1baa0 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 21 Sep 2024 15:12:11 +0100 Subject: [PATCH 4/6] Fix the dropdown having the wrong page value --- src/helpers/InventoryHelper.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 9075b30..714fb96 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -113,6 +113,8 @@ export default class InventoryHelper { .setStyle(ButtonStyle.Primary) .setDisabled(page + 1 == pages.length)); + let pageNum = 0; + const row2 = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() @@ -123,7 +125,7 @@ export default class InventoryHelper { .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) .setDescription("Quick navigate to page...") .setDefault(currentPage.id == x.id) - .setValue(x.id.toString())))); + .setValue((pageNum++).toString())))); const buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path }))); const image = new AttachmentBuilder(buffer, { name: "page.png" }); -- 2.43.4 From 680e627f7a690d6bfeffa3eeb654f4976551696b Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 21 Sep 2024 15:24:17 +0100 Subject: [PATCH 5/6] Handle dropdown --- src/helpers/InventoryHelper.ts | 4 ++-- src/stringDropdowns/Inventory.ts | 37 +++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 714fb96..4b3a500 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -123,9 +123,9 @@ export default class InventoryHelper { .addOptions(...pages.map(x => new StringSelectMenuOptionBuilder() .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) - .setDescription("Quick navigate to page...") + .setDescription(`Page ${pageNum + 1}`) .setDefault(currentPage.id == x.id) - .setValue((pageNum++).toString())))); + .setValue(`${userid} ${pageNum++}`)))); const buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path }))); const image = new AttachmentBuilder(buffer, { name: "page.png" }); diff --git a/src/stringDropdowns/Inventory.ts b/src/stringDropdowns/Inventory.ts index 65d16f6..2a218ea 100644 --- a/src/stringDropdowns/Inventory.ts +++ b/src/stringDropdowns/Inventory.ts @@ -1,8 +1,43 @@ import {StringSelectMenuInteraction} from "discord.js"; import {StringDropdownEvent} from "../type/stringDropdownEvent"; +import AppLogger from "../client/appLogger"; +import InventoryHelper from "../helpers/InventoryHelper"; export default class Inventory extends StringDropdownEvent { public override async execute(interaction: StringSelectMenuInteraction) { - await interaction.reply(`Test: ${interaction.customId}, ${interaction.values.join(",")}`); + if (!interaction.guild) return; + + const userid = interaction.values[0].split(" ")[0]; + const page = interaction.values[0].split(" ")[1]; + + AppLogger.LogDebug("StringDropdown/Inventory", `Parameters: userid=${userid}, page=${page}`); + + await interaction.deferUpdate(); + + const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid); + + if (!member) { + await interaction.reply("Unable to find user."); + return; + } + + try { + const embed = await InventoryHelper.GenerateInventoryPage(member.user.username, member.user.id, Number(page)); + + if (!embed) { + await interaction.followUp("No page for user found."); + return; + } + + await interaction.editReply({ + files: [ embed.image ], + embeds: [ embed.embed ], + components: [ embed.row1, embed.row2 ], + }); + } catch (e) { + AppLogger.LogError("StringDropdown/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`); + + await interaction.followUp("An error has occurred running this command."); + } } } -- 2.43.4 From 2732b849389bd1e650ce473d1c2c4e3f06ae96a8 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sat, 21 Sep 2024 15:26:02 +0100 Subject: [PATCH 6/6] Fix lint issues --- src/helpers/InventoryHelper.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 4b3a500..3a7fbff 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -116,16 +116,16 @@ export default class InventoryHelper { let pageNum = 0; const row2 = new ActionRowBuilder() - .addComponents( - new StringSelectMenuBuilder() - .setCustomId("inventory") - .setPlaceholder(`${currentPage.name} (${currentPage.seriesSubpage + 1})`) - .addOptions(...pages.map(x => - new StringSelectMenuOptionBuilder() - .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) - .setDescription(`Page ${pageNum + 1}`) - .setDefault(currentPage.id == x.id) - .setValue(`${userid} ${pageNum++}`)))); + .addComponents( + new StringSelectMenuBuilder() + .setCustomId("inventory") + .setPlaceholder(`${currentPage.name} (${currentPage.seriesSubpage + 1})`) + .addOptions(...pages.map(x => + new StringSelectMenuOptionBuilder() + .setLabel(`${x.name} (${x.seriesSubpage + 1})`.substring(0, 100)) + .setDescription(`Page ${pageNum + 1}`) + .setDefault(currentPage.id == x.id) + .setValue(`${userid} ${pageNum++}`)))); const buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path }))); const image = new AttachmentBuilder(buffer, { name: "page.png" }); -- 2.43.4