Add dropdown to /inventory command for quick navigation (#365)
- Add ability to handle dropdown menus with the bot - Add a dropdown to the inventoryhelper - Add handler for the dropdown to navigate to that page #344 Reviewed-on: #365 Reviewed-by: VylpesTester <tester@vylpes.com> Co-authored-by: Ethan Lane <ethan@vylpes.com> Co-committed-by: Ethan Lane <ethan@vylpes.com>
This commit is contained in:
parent
5ebc5ff27c
commit
1762b525b2
11 changed files with 146 additions and 7 deletions
|
@ -38,6 +38,7 @@ const client = new CoreClient([
|
||||||
|
|
||||||
Registry.RegisterCommands();
|
Registry.RegisterCommands();
|
||||||
Registry.RegisterButtonEvents();
|
Registry.RegisterButtonEvents();
|
||||||
|
Registry.RegisterStringDropdownEvents();
|
||||||
|
|
||||||
if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") {
|
if (!existsSync(`${process.env.DATA_DIR}/cards`) && process.env.GDRIVESYNC_AUTO && process.env.GDRIVESYNC_AUTO == "true") {
|
||||||
console.log("Card directory not found, syncing...");
|
console.log("Card directory not found, syncing...");
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default class Inventory extends ButtonEvent {
|
||||||
await interaction.editReply({
|
await interaction.editReply({
|
||||||
files: [ embed.image ],
|
files: [ embed.image ],
|
||||||
embeds: [ embed.embed ],
|
embeds: [ embed.embed ],
|
||||||
components: [ embed.row ],
|
components: [ embed.row1, embed.row2 ],
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`);
|
AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`);
|
||||||
|
|
|
@ -17,11 +17,14 @@ import AppLogger from "./appLogger";
|
||||||
import TimerHelper from "../helpers/TimerHelper";
|
import TimerHelper from "../helpers/TimerHelper";
|
||||||
import GiveCurrency from "../timers/GiveCurrency";
|
import GiveCurrency from "../timers/GiveCurrency";
|
||||||
import PurgeClaims from "../timers/PurgeClaims";
|
import PurgeClaims from "../timers/PurgeClaims";
|
||||||
|
import StringDropdownEventItem from "../contracts/StringDropdownEventItem";
|
||||||
|
import {StringDropdownEvent} from "../type/stringDropdownEvent";
|
||||||
|
|
||||||
export class CoreClient extends Client {
|
export class CoreClient extends Client {
|
||||||
private static _commandItems: ICommandItem[];
|
private static _commandItems: ICommandItem[];
|
||||||
private static _eventExecutors: EventExecutors;
|
private static _eventExecutors: EventExecutors;
|
||||||
private static _buttonEvents: IButtonEventItem[];
|
private static _buttonEvents: IButtonEventItem[];
|
||||||
|
private static _stringDropdowns: StringDropdownEventItem[];
|
||||||
|
|
||||||
private _events: Events;
|
private _events: Events;
|
||||||
private _util: Util;
|
private _util: Util;
|
||||||
|
@ -45,6 +48,10 @@ export class CoreClient extends Client {
|
||||||
return this._buttonEvents;
|
return this._buttonEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static get stringDropdowns(): StringDropdownEventItem[] {
|
||||||
|
return this._stringDropdowns;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(intents: number[]) {
|
constructor(intents: number[]) {
|
||||||
super({ intents: intents });
|
super({ intents: intents });
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
|
@ -59,6 +66,7 @@ export class CoreClient extends Client {
|
||||||
|
|
||||||
CoreClient._commandItems = [];
|
CoreClient._commandItems = [];
|
||||||
CoreClient._buttonEvents = [];
|
CoreClient._buttonEvents = [];
|
||||||
|
CoreClient._stringDropdowns = [];
|
||||||
|
|
||||||
this._events = new Events();
|
this._events = new Events();
|
||||||
this._util = new Util();
|
this._util = new Util();
|
||||||
|
@ -408,4 +416,19 @@ export class CoreClient extends Client {
|
||||||
AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`);
|
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}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import ChatInputCommand from "./interactionCreate/ChatInputCommand";
|
||||||
import Button from "./interactionCreate/Button";
|
import Button from "./interactionCreate/Button";
|
||||||
import AppLogger from "./appLogger";
|
import AppLogger from "./appLogger";
|
||||||
import NewUserDiscovery from "./interactionCreate/middleware/NewUserDiscovery";
|
import NewUserDiscovery from "./interactionCreate/middleware/NewUserDiscovery";
|
||||||
|
import StringDropdown from "./interactionCreate/StringDropdown";
|
||||||
|
|
||||||
export class Events {
|
export class Events {
|
||||||
public async onInteractionCreate(interaction: Interaction) {
|
public async onInteractionCreate(interaction: Interaction) {
|
||||||
|
@ -19,6 +20,11 @@ export class Events {
|
||||||
AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`);
|
AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`);
|
||||||
Button.onButtonClicked(interaction);
|
Button.onButtonClicked(interaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (interaction.isStringSelectMenu()) {
|
||||||
|
AppLogger.LogVerbose("Client", `StringDropdown: ${interaction.customId}`);
|
||||||
|
StringDropdown.onStringDropdownSelected(interaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit when bot is logged in and ready to use
|
// Emit when bot is logged in and ready to use
|
||||||
|
|
29
src/client/interactionCreate/StringDropdown.ts
Normal file
29
src/client/interactionCreate/StringDropdown.ts
Normal file
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ export default class Inventory extends Command {
|
||||||
await interaction.followUp({
|
await interaction.followUp({
|
||||||
files: [ embed.image ],
|
files: [ embed.image ],
|
||||||
embeds: [ embed.embed ],
|
embeds: [ embed.embed ],
|
||||||
components: [ embed.row ],
|
components: [ embed.row1, embed.row2 ],
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
AppLogger.LogError("Commands/Inventory", e as string);
|
AppLogger.LogError("Commands/Inventory", e as string);
|
||||||
|
|
10
src/contracts/StringDropdownEventItem.ts
Normal file
10
src/contracts/StringDropdownEventItem.ts
Normal file
|
@ -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;
|
|
@ -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 Inventory from "../database/entities/app/Inventory";
|
||||||
import { CoreClient } from "../client/client";
|
import { CoreClient } from "../client/client";
|
||||||
import EmbedColours from "../constants/EmbedColours";
|
import EmbedColours from "../constants/EmbedColours";
|
||||||
|
@ -24,7 +24,8 @@ interface InventoryPageCards {
|
||||||
|
|
||||||
interface ReturnedInventoryPage {
|
interface ReturnedInventoryPage {
|
||||||
embed: EmbedBuilder,
|
embed: EmbedBuilder,
|
||||||
row: ActionRowBuilder<ButtonBuilder>,
|
row1: ActionRowBuilder<ButtonBuilder>,
|
||||||
|
row2: ActionRowBuilder<StringSelectMenuBuilder>,
|
||||||
image: AttachmentBuilder,
|
image: AttachmentBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +100,7 @@ export default class InventoryHelper {
|
||||||
.setColor(EmbedColours.Ok)
|
.setColor(EmbedColours.Ok)
|
||||||
.setImage("attachment://page.png");
|
.setImage("attachment://page.png");
|
||||||
|
|
||||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
const row1 = new ActionRowBuilder<ButtonBuilder>()
|
||||||
.addComponents(
|
.addComponents(
|
||||||
new ButtonBuilder()
|
new ButtonBuilder()
|
||||||
.setCustomId(`inventory ${userid} ${page - 1}`)
|
.setCustomId(`inventory ${userid} ${page - 1}`)
|
||||||
|
@ -112,9 +113,23 @@ export default class InventoryHelper {
|
||||||
.setStyle(ButtonStyle.Primary)
|
.setStyle(ButtonStyle.Primary)
|
||||||
.setDisabled(page + 1 == pages.length));
|
.setDisabled(page + 1 == pages.length));
|
||||||
|
|
||||||
|
let pageNum = 0;
|
||||||
|
|
||||||
|
const row2 = new ActionRowBuilder<StringSelectMenuBuilder>()
|
||||||
|
.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 buffer = await ImageHelper.GenerateCardImageGrid(currentPage.cards.map(x => ({ id: x.id, path: x.path })));
|
||||||
const image = new AttachmentBuilder(buffer, { name: "page.png" });
|
const image = new AttachmentBuilder(buffer, { name: "page.png" });
|
||||||
|
|
||||||
return { embed, row, image };
|
return { embed, row1, row2, image };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@ import SeriesEvent from "./buttonEvents/Series";
|
||||||
import TradeButtonEvent from "./buttonEvents/Trade";
|
import TradeButtonEvent from "./buttonEvents/Trade";
|
||||||
import ViewButtonEvent from "./buttonEvents/View";
|
import ViewButtonEvent from "./buttonEvents/View";
|
||||||
|
|
||||||
|
// String Dropdown Event Imports
|
||||||
|
import InventoryStringDropdown from "./stringDropdowns/Inventory";
|
||||||
|
|
||||||
export default class Registry {
|
export default class Registry {
|
||||||
public static RegisterCommands() {
|
public static RegisterCommands() {
|
||||||
// Global Commands
|
// Global Commands
|
||||||
|
@ -64,4 +67,8 @@ export default class Registry {
|
||||||
CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent());
|
CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent());
|
||||||
CoreClient.RegisterButtonEvent("view", new ViewButtonEvent());
|
CoreClient.RegisterButtonEvent("view", new ViewButtonEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static RegisterStringDropdownEvents() {
|
||||||
|
CoreClient.RegisterStringDropdownEvent("inventory", new InventoryStringDropdown());
|
||||||
|
}
|
||||||
}
|
}
|
43
src/stringDropdowns/Inventory.ts
Normal file
43
src/stringDropdowns/Inventory.ts
Normal file
|
@ -0,0 +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) {
|
||||||
|
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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
src/type/stringDropdownEvent.ts
Normal file
5
src/type/stringDropdownEvent.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import {StringSelectMenuInteraction} from "discord.js";
|
||||||
|
|
||||||
|
export abstract class StringDropdownEvent {
|
||||||
|
abstract execute(interaction: StringSelectMenuInteraction): Promise<void>;
|
||||||
|
}
|
Loading…
Reference in a new issue