Command to allow the user to buy more effects (#424)
All checks were successful
Deploy To Stage / build (push) Successful in 54s
Deploy To Stage / deploy (push) Successful in 15s

# Description

- Create a command to generate an embed for the user to be able to buy more effects
- This embed will contain the details about the effect as well as 2 buttons; Confirm and Cancel
- The confirm button will call the button event to:
    - Remove the currency from the user
    - Give the user the effect to their inventory
- The cancel button will just disable the buttons, so the user can't accidentally use it if they don't want to.

#381

## Type of change

Please delete options that are not relevant.

- [x] New feature (non-breaking change which adds functionality)

# How Has This Been Tested?

- Have created unit tests and tested locally

# 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: #424
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:
Ethan Lane 2025-03-26 18:30:16 +00:00 committed by Vylpes
parent c6b458199c
commit 5089ad6ab6
20 changed files with 942 additions and 97 deletions

View file

@ -3,6 +3,7 @@ import { ButtonEvent } from "../type/buttonEvent";
import List from "./Effects/List";
import Use from "./Effects/Use";
import AppLogger from "../client/appLogger";
import Buy from "./Effects/Buy";
export default class Effects extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
@ -15,6 +16,9 @@ export default class Effects extends ButtonEvent {
case "use":
await Use.Execute(interaction);
break;
case "buy":
await Buy.Execute(interaction);
break;
default:
AppLogger.LogError("Buttons/Effects", `Unknown action, ${action}`);
}

View file

@ -0,0 +1,120 @@
import {ButtonInteraction} from "discord.js";
import AppLogger from "../../client/appLogger";
import EffectHelper from "../../helpers/EffectHelper";
import EmbedColours from "../../constants/EmbedColours";
import User from "../../database/entities/app/User";
import {EffectDetails} from "../../constants/EffectDetails";
export default class Buy {
public static async Execute(interaction: ButtonInteraction) {
const subaction = interaction.customId.split(" ")[2];
switch (subaction) {
case "confirm":
await this.Confirm(interaction);
break;
case "cancel":
await this.Cancel(interaction);
break;
default:
AppLogger.LogError("Buy", `Unknown subaction, effects ${subaction}`);
}
}
private static async Confirm(interaction: ButtonInteraction) {
const id = interaction.customId.split(" ")[3];
const quantity = interaction.customId.split(" ")[4];
if (!id || !quantity) {
AppLogger.LogError("Buy Confirm", "Not enough parameters");
return;
}
const effectDetail = EffectDetails.get(id);
if (!effectDetail) {
AppLogger.LogError("Buy Confirm", "Effect detail not found!");
return;
}
const quantityNumber = Number(quantity);
if (!quantityNumber || quantityNumber < 1) {
AppLogger.LogError("Buy Confirm", "Invalid number");
return;
}
const totalCost = effectDetail.cost * quantityNumber;
const user = await User.FetchOneById(User, interaction.user.id);
if (!user) {
AppLogger.LogError("Buy Confirm", "Unable to find user");
return;
}
if (user.Currency < totalCost) {
interaction.reply(`You don't have enough currency to buy this! You have \`${user.Currency} Currency\` and need \`${totalCost} Currency\`!`);
return;
}
user.RemoveCurrency(totalCost);
await user.Save(User, user);
await EffectHelper.AddEffectToUserInventory(interaction.user.id, id, quantityNumber);
const generatedEmbed = await EffectHelper.GenerateEffectBuyEmbed(interaction.user.id, id, quantityNumber, true);
if (typeof generatedEmbed == "string") {
await interaction.reply(generatedEmbed);
return;
}
generatedEmbed.embed.setColor(EmbedColours.Success);
generatedEmbed.embed.setFooter({ text: "Purchased" });
await interaction.update({
embeds: [ generatedEmbed.embed ],
components: [ generatedEmbed.row ],
});
}
private static async Cancel(interaction: ButtonInteraction) {
const id = interaction.customId.split(" ")[3];
const quantity = interaction.customId.split(" ")[4];
if (!id || !quantity) {
AppLogger.LogError("Buy Cancel", "Not enough parameters");
return;
}
const effectDetail = EffectDetails.get(id);
if (!effectDetail) {
AppLogger.LogError("Buy Cancel", "Effect detail not found!");
return;
}
const quantityNumber = Number(quantity);
if (!quantityNumber || quantityNumber < 1) {
AppLogger.LogError("Buy Cancel", "Invalid number");
return;
}
const generatedEmbed = await EffectHelper.GenerateEffectBuyEmbed(interaction.user.id, id, quantityNumber, true);
if (typeof generatedEmbed == "string") {
await interaction.reply(generatedEmbed);
return;
}
generatedEmbed.embed.setColor(EmbedColours.Error);
generatedEmbed.embed.setFooter({ text: "Cancelled" });
await interaction.update({
embeds: [ generatedEmbed.embed ],
components: [ generatedEmbed.row ],
});
}
}

View file

@ -11,7 +11,7 @@ export default async function List(interaction: ButtonInteraction) {
return;
}
const result = await EffectHelper.GenerateEffectEmbed(interaction.user.id, page);
const result = await EffectHelper.GenerateEffectListEmbed(interaction.user.id, page);
await interaction.update({
embeds: [ result.embed ],