From 16857ef14d9b82954cab8ff5326dc0498152fc01 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Sun, 31 Mar 2024 15:49:30 +0100 Subject: [PATCH] Create series command (#190) # Description Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. - Create series list command to let users view all series in the bot - Create series view command to let users view cards in a specific series - Both commands have a paginated event so the embeds don't get too big #99 ## Type of change Please delete options that are not relevant. - [x] New feature (non-breaking change which adds functionality) # How Has This Been Tested? Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration. # Checklist - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that provde my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/190 Reviewed-by: VylpesTester Co-authored-by: Ethan Lane Co-committed-by: Ethan Lane --- src/buttonEvents/Series.ts | 45 +++++++++++++++++ src/commands/series.ts | 71 ++++++++++++++++++++++++++ src/helpers/SeriesHelper.ts | 99 +++++++++++++++++++++++++++++++++++++ src/registry.ts | 4 ++ 4 files changed, 219 insertions(+) create mode 100644 src/buttonEvents/Series.ts create mode 100644 src/commands/series.ts create mode 100644 src/helpers/SeriesHelper.ts diff --git a/src/buttonEvents/Series.ts b/src/buttonEvents/Series.ts new file mode 100644 index 0000000..0d98bfb --- /dev/null +++ b/src/buttonEvents/Series.ts @@ -0,0 +1,45 @@ +import { ButtonInteraction } from "discord.js"; +import { ButtonEvent } from "../type/buttonEvent"; +import AppLogger from "../client/appLogger"; +import SeriesHelper from "../helpers/SeriesHelper"; + +export default class Series extends ButtonEvent { + public override async execute(interaction: ButtonInteraction) { + const subaction = interaction.customId.split(" ")[1]; + + switch(subaction) { + case "view": + await this.ViewSeries(interaction); + break; + case "list": + await this.ListSeries(interaction); + break; + default: + AppLogger.LogWarn("Commands/Series", `Subaction doesn't exist: ${subaction}`); + interaction.reply("Subaction doesn't exist."); + } + } + + private async ViewSeries(interaction: ButtonInteraction) { + const seriesid = interaction.customId.split(" ")[2]; + const page = interaction.customId.split(" ")[3]; + + const embed = SeriesHelper.GenerateSeriesViewPage(Number(seriesid), Number(page)); + + await interaction.update({ + embeds: [ embed!.embed ], + components: [ embed!.row ], + }); + } + + private async ListSeries(interaction: ButtonInteraction) { + const page = interaction.customId.split(" ")[2]; + + const embed = SeriesHelper.GenerateSeriesListPage(Number(page)); + + await interaction.update({ + embeds: [ embed!.embed ], + components: [ embed!.row ], + }); + } +} \ No newline at end of file diff --git a/src/commands/series.ts b/src/commands/series.ts new file mode 100644 index 0000000..2122355 --- /dev/null +++ b/src/commands/series.ts @@ -0,0 +1,71 @@ +import { CommandInteraction, SlashCommandBuilder } from "discord.js"; +import { Command } from "../type/command"; +import { CoreClient } from "../client/client"; +import AppLogger from "../client/appLogger"; +import SeriesHelper from "../helpers/SeriesHelper"; + +export default class Series extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("series") + .setDescription("View details on a series") + .addSubcommand(x => + x + .setName("view") + .setDescription("View a specifiic series by id") + .addStringOption(y => + y + .setName("id") + .setDescription("The series id") + .setRequired(true))) + .addSubcommand(x => + x + .setName("list") + .setDescription("List all series")) as SlashCommandBuilder; + } + + public override async execute(interaction: CommandInteraction) { + if (!interaction.isChatInputCommand()) return; + + switch (interaction.options.getSubcommand()) { + case "view": + await this.ViewSeries(interaction); + break; + case "list": + await this.ListSeries(interaction); + break; + default: + AppLogger.LogWarn("Commands/Series", `Subcommand doesn't exist: ${interaction.options.getSubcommand()}`); + await interaction.reply("Subcommand doesn't exist."); + } + } + + private async ViewSeries(interaction: CommandInteraction) { + const id = interaction.options.get("id"); + + AppLogger.LogSilly("Commands/Series/View", `Parameters: id=${id?.value}`); + + if (!id) return; + + const series = CoreClient.Cards.find(x => x.id == id.value); + + if (!series) { + AppLogger.LogVerbose("Commands/Series/View", "Series not found."); + + await interaction.reply("Series not found."); + return; + } + + const embed = SeriesHelper.GenerateSeriesViewPage(series.id, 0); + + await interaction.reply({ embeds: [ embed!.embed ], components: [ embed!.row ]}); + } + + private async ListSeries(interaction: CommandInteraction) { + const embed = SeriesHelper.GenerateSeriesListPage(0); + + await interaction.reply({ embeds: [ embed!.embed ], components: [ embed!.row ]}); + } +} \ No newline at end of file diff --git a/src/helpers/SeriesHelper.ts b/src/helpers/SeriesHelper.ts new file mode 100644 index 0000000..32b1405 --- /dev/null +++ b/src/helpers/SeriesHelper.ts @@ -0,0 +1,99 @@ +import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js"; +import AppLogger from "../client/appLogger"; +import cloneDeep from "clone-deep"; +import { CoreClient } from "../client/client"; +import EmbedColours from "../constants/EmbedColours"; +import { CardRarityToString } from "../constants/CardRarity"; + +export default class SeriesHelper { + public static GenerateSeriesViewPage(seriesId: number, page: number): { embed: EmbedBuilder, row: ActionRowBuilder } | null { + AppLogger.LogSilly("Helpers/SeriesHelper", `Parameters: seriesId=${seriesId}, page=${page}`); + + const itemsPerPage = 15; + + const series = cloneDeep(CoreClient.Cards) + .find(x => x.id == seriesId); + + if (!series) { + AppLogger.LogVerbose("Helpers/SeriesHelper", `Unable to find series: ${seriesId}`); + return null; + } + + const totalPages = Math.ceil(series.cards.length / itemsPerPage); + + if (page > totalPages) { + AppLogger.LogVerbose("Helpers/SeriesHelper", `Trying to find page greater than what exists for this series. Page: ${page} but there are only ${totalPages} pages`); + return null; + } + + const cardsOnPage = series.cards.splice(page * itemsPerPage, itemsPerPage); + + const description = cardsOnPage + .map(x => `[${x.id}] ${x.name} ${CardRarityToString(x.type).toUpperCase()}`) + .join("\n"); + + const embed = new EmbedBuilder() + .setTitle(series.name) + .setColor(EmbedColours.Ok) + .setDescription(description) + .setFooter({ text: `${series.id} · ${series.cards.length} cards · Page ${page + 1} of ${totalPages}` }); + + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`series view ${seriesId} ${page - 1}`) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + .setDisabled(page == 0), + new ButtonBuilder() + .setCustomId(`series view ${seriesId} ${page + 1}`) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + .setDisabled(page + 1 > totalPages)); + + return { embed, row }; + } + + public static GenerateSeriesListPage(page: number): { embed: EmbedBuilder, row: ActionRowBuilder } | null { + AppLogger.LogSilly("Helpers/InventoryHelper", `Parameters: page=${page}`); + + const itemsPerPage = 15; + + const series = cloneDeep(CoreClient.Cards) + .sort((a, b) => a.id - b.id); + + const totalPages = Math.ceil(series.length / itemsPerPage); + + if (page > totalPages) { + AppLogger.LogVerbose("Helpers/SeriesHelper", `Trying to find page greater than what exists for this series. Page: ${page} but there are only ${totalPages} pages`); + return null; + } + + const seriesOnPage = series.splice(page * itemsPerPage, itemsPerPage); + + const description = seriesOnPage + .map(x => `[${x.id}] ${x.name}`) + .join("\n"); + + const embed = new EmbedBuilder() + .setTitle("Series") + .setColor(EmbedColours.Ok) + .setDescription(description) + .setFooter({ text: `${CoreClient.Cards.length} series · Page ${page + 1} of ${totalPages}` }); + + const row = new ActionRowBuilder() + .addComponents( + new ButtonBuilder() + .setCustomId(`series list ${page - 1}`) + .setLabel("Previous") + .setStyle(ButtonStyle.Primary) + .setDisabled(page == 0), + new ButtonBuilder() + .setCustomId(`series list ${page + 1}`) + .setLabel("Next") + .setStyle(ButtonStyle.Primary) + .setDisabled(page + 1 > totalPages)); + + return { embed, row }; + } +} \ No newline at end of file diff --git a/src/registry.ts b/src/registry.ts index 1087cda..bb68685 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -8,6 +8,7 @@ import Gdrivesync from "./commands/gdrivesync"; import Give from "./commands/give"; import Inventory from "./commands/inventory"; import Resync from "./commands/resync"; +import Series from "./commands/series"; import Trade from "./commands/trade"; import View from "./commands/view"; @@ -19,6 +20,7 @@ import Droprarity from "./commands/stage/droprarity"; import Claim from "./buttonEvents/Claim"; import InventoryButtonEvent from "./buttonEvents/Inventory"; import Reroll from "./buttonEvents/Reroll"; +import SeriesEvent from "./buttonEvents/Series"; import TradeButtonEvent from "./buttonEvents/Trade"; export default class Registry { @@ -30,6 +32,7 @@ export default class Registry { CoreClient.RegisterCommand("give", new Give()); CoreClient.RegisterCommand("inventory", new Inventory()); CoreClient.RegisterCommand("resync", new Resync()); + CoreClient.RegisterCommand("series", new Series()); CoreClient.RegisterCommand("trade", new Trade()); CoreClient.RegisterCommand("view", new View()); @@ -46,6 +49,7 @@ export default class Registry { CoreClient.RegisterButtonEvent("claim", new Claim()); CoreClient.RegisterButtonEvent("inventory", new InventoryButtonEvent()); CoreClient.RegisterButtonEvent("reroll", new Reroll()); + CoreClient.RegisterButtonEvent("series", new SeriesEvent()); CoreClient.RegisterButtonEvent("trade", new TradeButtonEvent()); } } \ No newline at end of file