diff --git a/.dev.env b/.dev.env index 0089c5e..1e90070 100644 --- a/.dev.env +++ b/.dev.env @@ -7,7 +7,7 @@ # any secret values. BOT_TOKEN= -BOT_VER=0.1.0 DEV +BOT_VER=0.1.0 BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 diff --git a/.stage.env b/.stage.env index 19590a2..389c429 100644 --- a/.stage.env +++ b/.stage.env @@ -7,7 +7,7 @@ # any secret values. BOT_TOKEN= -BOT_VER=0.1.0 BETA +BOT_VER=0.1.0 BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1016767908740857949 diff --git a/src/Functions/CardSetupFunction.ts b/src/Functions/CardSetupFunctions.ts similarity index 87% rename from src/Functions/CardSetupFunction.ts rename to src/Functions/CardSetupFunctions.ts index a9098ec..8e7fbf4 100644 --- a/src/Functions/CardSetupFunction.ts +++ b/src/Functions/CardSetupFunctions.ts @@ -5,7 +5,7 @@ import Series from "../database/entities/card/Series"; import path from "path"; import { CardRarity } from "../constants/CardRarity"; -export default class CardSetupFunction { +export default class CardSetupFunctions { public async Execute() { await this.ClearDatabase(); await this.ReadSeries(); @@ -42,7 +42,7 @@ export default class CardSetupFunction { } private async ReadCards() { - const loadedSeries = await Series.FetchAll(Series, [ "Cards", "Cards.Series" ]); + const loadedSeries = await Series.FetchAll(Series); const cardRepository = CardDataSource.getRepository(Card); @@ -65,7 +65,7 @@ export default class CardSetupFunction { const cardId = filePart[0]; const cardName = filePart[0]; - const card = new Card(cardId, cardName, CardRarity.Bronze, path.join(path.join(process.cwd(), 'cards', series.Path, 'BRONZE', file)), series); + const card = new Card(cardId, cardName, CardRarity.Bronze); cardsToSave.push(card); } @@ -76,7 +76,7 @@ export default class CardSetupFunction { const cardId = filePart[0]; const cardName = filePart[0]; - const card = new Card(cardId, cardName, CardRarity.Gold, path.join(path.join(process.cwd(), 'cards', series.Path, 'GOLD', file)), series); + const card = new Card(cardId, cardName, CardRarity.Gold); cardsToSave.push(card); } @@ -87,7 +87,7 @@ export default class CardSetupFunction { const cardId = filePart[0]; const cardName = filePart[0]; - const card = new Card(cardId, cardName, CardRarity.Legendary, path.join(path.join(process.cwd(), 'cards', series.Path, 'LEGENDARY', file)), series); + const card = new Card(cardId, cardName, CardRarity.Legendary); cardsToSave.push(card); } @@ -98,7 +98,7 @@ export default class CardSetupFunction { const cardId = filePart[0]; const cardName = filePart[0]; - const card = new Card(cardId, cardName, CardRarity.Silver, path.join(path.join(process.cwd(), 'cards', series.Path, 'SILVER', file)), series); + const card = new Card(cardId, cardName, CardRarity.Silver); cardsToSave.push(card); } diff --git a/src/bot.ts b/src/bot.ts index e8c1dd3..baca574 100644 --- a/src/bot.ts +++ b/src/bot.ts @@ -32,6 +32,5 @@ const client = new CoreClient([ Registry.RegisterCommands(); Registry.RegisterEvents(); -Registry.RegisterButtonEvents(); client.start(); \ No newline at end of file diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts deleted file mode 100644 index 5412db8..0000000 --- a/src/buttonEvents/Claim.ts +++ /dev/null @@ -1,38 +0,0 @@ -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'); - } -} \ No newline at end of file diff --git a/src/buttonEvents/Reroll.ts b/src/buttonEvents/Reroll.ts deleted file mode 100644 index f1c4bcc..0000000 --- a/src/buttonEvents/Reroll.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ActionRowBuilder, AttachmentBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, CacheType, EmbedBuilder } from "discord.js"; -import { ButtonEvent } from "../type/buttonEvent"; -import CardDropHelper from "../helpers/CardDropHelper"; -import { readFileSync } from "fs"; -import { CardRarityToColour, CardRarityToString } from "../constants/CardRarity"; -import { v4 } from "uuid"; -import { CoreClient } from "../client/client"; - -export default class Reroll extends ButtonEvent { - public override async execute(interaction: ButtonInteraction) { - if (!interaction.guild || !interaction.guildId) return; - - const randomCard = await CardDropHelper.GetRandomCard(); - - const image = readFileSync(randomCard.Path); - - const attachment = new AttachmentBuilder(image, { name: `${randomCard.Id}.png` }); - - const embed = new EmbedBuilder() - .setTitle(randomCard.Name) - .setDescription(randomCard.Series.Name) - .setFooter({ text: CardRarityToString(randomCard.Rarity) }) - .setColor(CardRarityToColour(randomCard.Rarity)) - .setImage(`attachment://${randomCard.Id}.png`); - - const row = new ActionRowBuilder(); - - const claimId = v4(); - - row.addComponents( - new ButtonBuilder() - .setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) - .setLabel("Claim") - .setStyle(ButtonStyle.Primary), - new ButtonBuilder() - .setCustomId(`reroll`) - .setLabel("Reroll") - .setStyle(ButtonStyle.Secondary)); - - await interaction.reply({ - embeds: [ embed ], - files: [ attachment ], - components: [ row ], - }); - - CoreClient.ClaimId = claimId; - } -} \ No newline at end of file diff --git a/src/client/client.ts b/src/client/client.ts index b517a28..a928d3b 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -7,23 +7,14 @@ import { Command } from "../type/command"; import { Events } from "./events"; 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; @@ -33,21 +24,15 @@ 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(); - this._cardSetupFunc = new CardSetupFunction(); } public async start() { @@ -57,18 +42,12 @@ export class CoreClient extends Client { } 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)); + .then(() => console.log("Data Source Initialized")) + .catch((err) => console.error("Error Initialising Data Source", err)); super.on("interactionCreate", this._events.onInteractionCreate); super.on("ready", this._events.onReady); - await this._cardSetupFunc.Execute(); - await super.login(process.env.BOT_TOKEN); this._util.loadEvents(this, CoreClient._eventItems); @@ -93,13 +72,4 @@ 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); - } } diff --git a/src/client/events.ts b/src/client/events.ts index db6cfc4..bfbe7ec 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -1,18 +1,29 @@ import { Interaction } from "discord.js"; -import ChatInputCommand from "./interactionCreate/ChatInputCommand"; -import Button from "./interactionCreate/Button"; +import ICommandItem from "../contracts/ICommandItem"; +import { CoreClient } from "./client"; export class Events { public async onInteractionCreate(interaction: Interaction) { + if (!interaction.isChatInputCommand()) return; if (!interaction.guildId) return; - if (interaction.isChatInputCommand()) { - ChatInputCommand.onChatInput(interaction); + 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; } - if (interaction.isButton()) { - Button.onButtonClicked(interaction); - } + itemToUse.Command.execute(interaction); } // Emit when bot is logged in and ready to use diff --git a/src/client/interactionCreate/Button.ts b/src/client/interactionCreate/Button.ts deleted file mode 100644 index 165e426..0000000 --- a/src/client/interactionCreate/Button.ts +++ /dev/null @@ -1,17 +0,0 @@ -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); - } -} \ No newline at end of file diff --git a/src/client/interactionCreate/ChatInputCommand.ts b/src/client/interactionCreate/ChatInputCommand.ts deleted file mode 100644 index d483f1d..0000000 --- a/src/client/interactionCreate/ChatInputCommand.ts +++ /dev/null @@ -1,27 +0,0 @@ -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); - } -} \ No newline at end of file diff --git a/src/commands/drop.ts b/src/commands/drop.ts deleted file mode 100644 index 861fb18..0000000 --- a/src/commands/drop.ts +++ /dev/null @@ -1,54 +0,0 @@ -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() { - super(); - - super.CommandBuilder = new SlashCommandBuilder() - .setName('drop') - .setDescription('Summon a new card drop'); - } - - public override async execute(interaction: CommandInteraction) { - const randomCard = await CardDropHelper.GetRandomCard(); - - const image = readFileSync(randomCard.Path); - - const attachment = new AttachmentBuilder(image, { name: `${randomCard.Id}.png` }); - - const embed = new EmbedBuilder() - .setTitle(randomCard.Name) - .setDescription(randomCard.Series.Name) - .setFooter({ text: CardRarityToString(randomCard.Rarity) }) - .setColor(CardRarityToColour(randomCard.Rarity)) - .setImage(`attachment://${randomCard.Id}.png`); - - const row = new ActionRowBuilder(); - - const claimId = v4(); - - row.addComponents( - new ButtonBuilder() - .setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) - .setLabel("Claim") - .setStyle(ButtonStyle.Primary), - new ButtonBuilder() - .setCustomId(`reroll`) - .setLabel("Reroll") - .setStyle(ButtonStyle.Secondary)); - - await interaction.reply({ - embeds: [ embed ], - files: [ attachment ], - components: [ row ], - }); - - CoreClient.ClaimId = claimId; - } -} \ No newline at end of file diff --git a/src/constants/CardRarity.ts b/src/constants/CardRarity.ts index 92a5141..541ff36 100644 --- a/src/constants/CardRarity.ts +++ b/src/constants/CardRarity.ts @@ -1,34 +1,6 @@ -import EmbedColours from "./EmbedColours"; - export enum CardRarity { Bronze, Silver, Gold, Legendary, -} - -export function CardRarityToString(rarity: CardRarity): string { - switch (rarity) { - case CardRarity.Bronze: - return "Bronze"; - case CardRarity.Silver: - return "Silver"; - case CardRarity.Gold: - return "Gold"; - case CardRarity.Legendary: - return "Legendary"; - } -} - -export function CardRarityToColour(rarity: CardRarity): number { - switch (rarity) { - case CardRarity.Bronze: - return EmbedColours.BronzeCard; - case CardRarity.Silver: - return EmbedColours.SilverCard; - case CardRarity.Gold: - return EmbedColours.GoldCard; - case CardRarity.Legendary: - return EmbedColours.LegendaryCard; - } } \ No newline at end of file diff --git a/src/constants/EmbedColours.ts b/src/constants/EmbedColours.ts index d889f5d..023c77a 100644 --- a/src/constants/EmbedColours.ts +++ b/src/constants/EmbedColours.ts @@ -1,7 +1,3 @@ export default class EmbedColours { public static readonly Ok = 0x3050ba; - public static readonly BronzeCard = 0xcd7f32; - public static readonly SilverCard = 0xc0c0c0; - public static readonly GoldCard = 0xffd700; - public static readonly LegendaryCard = 0x50c878; } \ No newline at end of file diff --git a/src/contracts/IButtonEventItem.ts b/src/contracts/IButtonEventItem.ts deleted file mode 100644 index 6be9f6e..0000000 --- a/src/contracts/IButtonEventItem.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ButtonEvent } from "../type/buttonEvent"; - -export default interface IButtonEventItem { - ButtonId: string, - Event: ButtonEvent, -} \ No newline at end of file diff --git a/src/database/entities/app/.gitkeep b/src/database/entities/app/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/database/entities/app/Inventory.ts b/src/database/entities/app/Inventory.ts deleted file mode 100644 index c6319a9..0000000 --- a/src/database/entities/app/Inventory.ts +++ /dev/null @@ -1,47 +0,0 @@ -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 { - const repository = AppDataSource.getRepository(Inventory); - - const single = await repository.findOne({ where: { UserId: userId, CardNumber: cardNumber }}); - - return single; - } - - public static async FetchOneByClaimId(claimId: string): Promise { - const repository = AppDataSource.getRepository(Inventory); - - const single = await repository.findOne({ where: { ClaimId: claimId }}); - - return single; - } -} \ No newline at end of file diff --git a/src/database/entities/card/Card.ts b/src/database/entities/card/Card.ts index f354fd6..0a368f9 100644 --- a/src/database/entities/card/Card.ts +++ b/src/database/entities/card/Card.ts @@ -1,18 +1,17 @@ -import { Column, Entity, ManyToOne } from "typeorm"; +import { Column, Entity, OneToMany } from "typeorm"; import CardBaseEntity from "../../../contracts/CardBaseEntity"; import { CardRarity } from "../../../constants/CardRarity"; import Series from "./Series"; +import CardDataSource from "../../dataSources/cardDataSource"; @Entity() export default class Card extends CardBaseEntity { - constructor(cardNumber: string, name: string, rarity: CardRarity, path: string, series: Series) { + constructor(cardNumber: string, name: string, rarity: CardRarity) { super(); this.CardNumber = cardNumber; this.Name = name; this.Rarity = rarity; - this.Path = path; - this.Series = series; } @Column() @@ -24,9 +23,14 @@ export default class Card extends CardBaseEntity { @Column() Rarity: CardRarity; - @Column() - Path: string - - @ManyToOne(() => Series, x => x.Cards) + @OneToMany(() => Series, x => x.Cards) Series: Series; + + public static async FetchAllByRarity(rarity: CardRarity): Promise { + const repository = CardDataSource.getRepository(Card); + + const all = await repository.find({ where: { Rarity: rarity }}); + + return all; + } } \ No newline at end of file diff --git a/src/database/entities/card/Series.ts b/src/database/entities/card/Series.ts index eb990cc..5a8dca3 100644 --- a/src/database/entities/card/Series.ts +++ b/src/database/entities/card/Series.ts @@ -1,4 +1,4 @@ -import { Column, Entity, OneToMany } from "typeorm"; +import { Column, Entity, ManyToOne } from "typeorm"; import CardBaseEntity from "../../../contracts/CardBaseEntity"; import Card from "./Card"; @@ -18,6 +18,12 @@ export default class Series extends CardBaseEntity { @Column() Path: string; - @OneToMany(() => Card, x => x.Series) + @ManyToOne(() => Card, x => x.Series) Cards: Card[]; + + public async AddCard(card: Card) { + if (!this.Cards) return; + + this.Cards.push(card); + } } \ No newline at end of file diff --git a/src/helpers/CardDropHelper.ts b/src/helpers/CardDropHelper.ts deleted file mode 100644 index 9ab63ca..0000000 --- a/src/helpers/CardDropHelper.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { CardRarity } from "../constants/CardRarity"; -import CardDataSource from "../database/dataSources/cardDataSource"; -import Card from "../database/entities/card/Card"; -import Series from "../database/entities/card/Series"; - -export default class CardDropHelper { - public static async GetRandomCard(): Promise { - const seriesRepository = CardDataSource.getRepository(Series); - - const allSeries = await Series.FetchAll(Series, [ "Cards", "Cards.Series" ]); - const allSeriesWithCards = allSeries.filter(x => x.Cards.length > 0); - - const randomSeriesIndex = Math.floor(Math.random() * allSeriesWithCards.length); - - const randomSeries = allSeriesWithCards[randomSeriesIndex]; - - const randomRarity = Math.random() * 100; - - let cardRarity: CardRarity; - - const bronzeChance = 62; - const silverChance = bronzeChance + 31; - const goldChance = silverChance + 6.4; - - if (randomRarity < bronzeChance) cardRarity = CardRarity.Bronze; - else if (randomRarity < silverChance) cardRarity = CardRarity.Silver; - else if (randomRarity < goldChance) cardRarity = CardRarity.Gold; - else cardRarity = CardRarity.Legendary; - - const allCards = randomSeries.Cards.filter(x => x.Rarity == cardRarity); - - const randomCardIndex = Math.floor(Math.random() * allCards.length); - - const randomCard = allCards[randomCardIndex]; - - return randomCard; - } -} \ No newline at end of file diff --git a/src/registry.ts b/src/registry.ts index c517af3..774015a 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -1,23 +1,13 @@ import { CoreClient } from "./client/client"; import About from "./commands/about"; -import Drop from "./commands/drop"; - -import Claim from "./buttonEvents/Claim"; -import Reroll from "./buttonEvents/Reroll"; export default class Registry { public static RegisterCommands() { CoreClient.RegisterCommand('about', new About()); - CoreClient.RegisterCommand('drop', new Drop()); } public static RegisterEvents() { } - - public static RegisterButtonEvents() { - CoreClient.RegisterButtonEvent('claim', new Claim()); - CoreClient.RegisterButtonEvent('reroll', new Reroll()); - } } \ No newline at end of file diff --git a/src/type/buttonEvent.ts b/src/type/buttonEvent.ts deleted file mode 100644 index 3a691cf..0000000 --- a/src/type/buttonEvent.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ButtonInteraction } from "discord.js"; - -export class ButtonEvent { - public execute(interaction: ButtonInteraction) { - - } -} \ No newline at end of file