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