feature/5-drop-command #17

Merged
Vylpes merged 4 commits from feature/5-drop-command into develop 2023-09-03 20:27:31 +01:00
12 changed files with 197 additions and 20 deletions
Showing only changes of commit 08e99ee2d7 - Show all commits

View file

@ -32,5 +32,6 @@ const client = new CoreClient([
Registry.RegisterCommands();
Registry.RegisterEvents();
Registry.RegisterButtonEvents();
client.start();

38
src/buttonEvents/Claim.ts Normal file
View file

@ -0,0 +1,38 @@
import { ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent";
import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client";
export default class Claim extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) {
if (!interaction.guild || !interaction.guildId) return;
const cardNumber = interaction.customId.split(' ')[1];
const claimId = interaction.customId.split(' ')[2];
const userId = interaction.user.id;
const claimed = await Inventory.FetchOneByClaimId(claimId);
if (claimed) {
await interaction.reply('This card has already been claimed');
return;
}
if (claimId != CoreClient.ClaimId) {
await interaction.reply('This card has expired');
return;
}
let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber);
if (!inventory) {
inventory = new Inventory(userId, cardNumber, 1, claimId);
} else {
inventory.SetQuantity(inventory.Quantity + 1);
}
await inventory.Save(Inventory, inventory);
await interaction.reply('Card claimed');
}
}

View file

@ -10,15 +10,21 @@ import { Util } from "./util";
import CardSetupFunction from "../Functions/CardSetupFunction";
import CardDataSource from "../database/dataSources/cardDataSource";
import CardDropHelper from "../helpers/CardDropHelper";
import IButtonEventItem from "../contracts/IButtonEventItem";
import { ButtonEvent } from "../type/buttonEvent";
import AppDataSource from "../database/dataSources/appDataSource";
export class CoreClient extends Client {
private static _commandItems: ICommandItem[];
private static _eventItems: IEventItem[];
private static _buttonEvents: IButtonEventItem[];
private _events: Events;
private _util: Util;
private _cardSetupFunc: CardSetupFunction;
public static ClaimId: string;
public static get commandItems(): ICommandItem[] {
return this._commandItems;
}
@ -27,12 +33,17 @@ export class CoreClient extends Client {
return this._eventItems;
}
public static get buttonEvents(): IButtonEventItem[] {
return this._buttonEvents;
}
constructor(intents: number[]) {
super({ intents: intents });
dotenv.config();
CoreClient._commandItems = [];
CoreClient._eventItems = [];
CoreClient._buttonEvents = [];
this._events = new Events();
this._util = new Util();
@ -45,6 +56,10 @@ export class CoreClient extends Client {
return;
}
await AppDataSource.initialize()
.then(() => console.log("App Data Source Initialised"))
.catch(err => console.error("Error initialising App Data Source", err));
await CardDataSource.initialize()
.then(() => console.log("Card Data Source Initialised"))
.catch(err => console.error("Error initialising Card Data Source", err));
@ -78,4 +93,13 @@ export class CoreClient extends Client {
CoreClient._eventItems.push(item);
}
public static RegisterButtonEvent(buttonId: string, event: ButtonEvent) {
const item: IButtonEventItem = {
ButtonId: buttonId,
Event: event,
};
CoreClient._buttonEvents.push(item);
}
}

View file

@ -1,29 +1,18 @@
import { Interaction } from "discord.js";
import ICommandItem from "../contracts/ICommandItem";
import { CoreClient } from "./client";
import ChatInputCommand from "./interactionCreate/ChatInputCommand";
import Button from "./interactionCreate/Button";
export class Events {
public async onInteractionCreate(interaction: Interaction) {
if (!interaction.isChatInputCommand()) return;
if (!interaction.guildId) return;
const item = CoreClient.commandItems.find(x => x.Name == interaction.commandName && !x.ServerId);
const itemForServer = CoreClient.commandItems.find(x => x.Name == interaction.commandName && x.ServerId == interaction.guildId);
let itemToUse: ICommandItem;
if (!itemForServer) {
if (!item) {
await interaction.reply('Command not found');
return;
if (interaction.isChatInputCommand()) {
ChatInputCommand.onChatInput(interaction);
}
itemToUse = item;
} else {
itemToUse = itemForServer;
if (interaction.isButton()) {
Button.onButtonClicked(interaction);
}
itemToUse.Command.execute(interaction);
}
// Emit when bot is logged in and ready to use

View file

@ -0,0 +1,17 @@
import { ButtonInteraction, Interaction } from "discord.js";
import { CoreClient } from "../client";
export default class Button {
public static async onButtonClicked(interaction: ButtonInteraction) {
if (!interaction.isButton) return;
const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(' ')[0]);
if (!item) {
await interaction.reply('Event not found');
return;
}
item.Event.execute(interaction);
}
}

View file

@ -0,0 +1,27 @@
import { Interaction } from "discord.js";
import { CoreClient } from "../client";
import ICommandItem from "../../contracts/ICommandItem";
export default class ChatInputCommand {
public static async onChatInput(interaction: Interaction) {
if (!interaction.isChatInputCommand()) return;
const item = CoreClient.commandItems.find(x => x.Name == interaction.commandName && !x.ServerId);
const itemForServer = CoreClient.commandItems.find(x => x.Name == interaction.commandName && x.ServerId == interaction.guildId);
let itemToUse: ICommandItem;
if (!itemForServer) {
if (!item) {
await interaction.reply('Command not found');
return;
}
itemToUse = item;
} else {
itemToUse = itemForServer;
}
itemToUse.Command.execute(interaction);
}
}

View file

@ -1,8 +1,10 @@
import { AttachmentBuilder, CommandInteraction, EmbedBuilder, SlashCommandBuilder } from "discord.js";
import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command";
import CardDropHelper from "../helpers/CardDropHelper";
import { CardRarityToColour, CardRarityToString } from "../constants/CardRarity";
import { readFileSync } from "fs";
import { CoreClient } from "../client/client";
import { v4 } from "uuid";
export default class Drop extends Command {
constructor() {
@ -27,9 +29,22 @@ export default class Drop extends Command {
.setColor(CardRarityToColour(randomCard.Rarity))
.setImage(`attachment://${randomCard.Id}.png`);
await interaction.reply({
const row = new ActionRowBuilder<ButtonBuilder>();
const claimId = v4();
row.addComponents(
new ButtonBuilder()
.setCustomId(`claim ${randomCard.CardNumber} ${claimId}`)
.setLabel("Claim")
.setStyle(ButtonStyle.Primary));
const message = await interaction.reply({
embeds: [ embed ],
files: [ attachment ],
components: [ row ],
});
CoreClient.ClaimId = claimId;
}
}

View file

@ -0,0 +1,6 @@
import { ButtonEvent } from "../type/buttonEvent";
export default interface IButtonEventItem {
ButtonId: string,
Event: ButtonEvent,
}

View file

@ -0,0 +1,47 @@
import { Column, Entity } from "typeorm";
import AppBaseEntity from "../../../contracts/AppBaseEntity";
import AppDataSource from "../../dataSources/appDataSource";
@Entity()
export default class Inventory extends AppBaseEntity {
constructor(userId: string, cardNumber: string, quantity: number, claimId: string) {
super();
this.UserId = userId;
this.CardNumber = cardNumber;
this.Quantity = quantity;
this.ClaimId = claimId;
}
@Column()
UserId: string;
@Column()
CardNumber: string;
@Column()
Quantity: number;
@Column()
ClaimId: string;
public SetQuantity(quantity: number) {
this.Quantity = quantity;
}
public static async FetchOneByCardNumberAndUserId(userId: string, cardNumber: string): Promise<Inventory | null> {
const repository = AppDataSource.getRepository(Inventory);
const single = await repository.findOne({ where: { UserId: userId, CardNumber: cardNumber }});
return single;
}
public static async FetchOneByClaimId(claimId: string): Promise<Inventory | null> {
const repository = AppDataSource.getRepository(Inventory);
const single = await repository.findOne({ where: { ClaimId: claimId }});
return single;
}
}

View file

@ -3,6 +3,8 @@ import { CoreClient } from "./client/client";
import About from "./commands/about";
import Drop from "./commands/drop";
import Claim from "./buttonEvents/Claim";
export default class Registry {
public static RegisterCommands() {
CoreClient.RegisterCommand('about', new About());
@ -12,4 +14,8 @@ export default class Registry {
public static RegisterEvents() {
}
public static RegisterButtonEvents() {
CoreClient.RegisterButtonEvent('claim', new Claim());
}
}

7
src/type/buttonEvent.ts Normal file
View file

@ -0,0 +1,7 @@
import { ButtonInteraction } from "discord.js";
export class ButtonEvent {
public execute(interaction: ButtonInteraction) {
}
}