diff --git a/.dev.env b/.dev.env index 1635809..ca791ba 100644 --- a/.dev.env +++ b/.dev.env @@ -7,7 +7,7 @@ # any secret values. BOT_TOKEN= -BOT_VER=0.1.1 DEV +BOT_VER=0.1.4 DEV BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 @@ -26,4 +26,4 @@ DB_AUTH_PASS=dev DB_SYNC=true DB_LOGGING=true -DB_CARD_FILE=:memory: \ No newline at end of file +DB_CARD_FILE=:memory: diff --git a/.drone.yml b/.drone.yml index a2752f4..35df56b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -7,7 +7,7 @@ steps: - name: deploy image: appleboy/drone-ssh settings: - host: 192.168.68.121 + host: 192.168.68.120 username: vylpes password: from_secret: ssh_password @@ -28,7 +28,7 @@ steps: - name: stage image: appleboy/drone-ssh settings: - host: 192.168.68.121 + host: 192.168.68.120 username: vylpes password: from_secret: ssh_password diff --git a/.prod.env b/.prod.env index 17fc883..f1a644e 100644 --- a/.prod.env +++ b/.prod.env @@ -7,7 +7,7 @@ # any secret values. BOT_TOKEN= -BOT_VER=0.1.1 +BOT_VER=0.1.4 BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1093810443589529631 @@ -26,4 +26,4 @@ DB_AUTH_PASS=prod DB_SYNC=false DB_LOGGING=false -DB_CARD_FILE=:memory: \ No newline at end of file +DB_CARD_FILE=:memory: diff --git a/.stage.env b/.stage.env index 39afa54..60a01fc 100644 --- a/.stage.env +++ b/.stage.env @@ -7,7 +7,7 @@ # any secret values. BOT_TOKEN= -BOT_VER=0.1.1 BETA +BOT_VER=0.1.4 BETA BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1147976642942214235 @@ -26,4 +26,4 @@ DB_AUTH_PASS=stage DB_SYNC=false DB_LOGGING=false -DB_CARD_FILE=:memory: \ No newline at end of file +DB_CARD_FILE=:memory: diff --git a/database/0.1.5/1694609771821-CreateClaim/Up/01-CreateClaim.sql b/database/0.1.5/1694609771821-CreateClaim/Up/01-CreateClaim.sql new file mode 100644 index 0000000..bfd8057 --- /dev/null +++ b/database/0.1.5/1694609771821-CreateClaim/Up/01-CreateClaim.sql @@ -0,0 +1,8 @@ +CREATE TABLE `claim` ( + `Id` varchar(255) NOT NULL, + `WhenCreated` datetime NOT NULL, + `WhenUpdated` datetime NOT NULL, + `ClaimId` varchar(255) NOT NULL, + `InventoryId` varchar(255) NOT NULL, + PRIMARY KEY (`Id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; \ No newline at end of file diff --git a/database/0.1.5/1694609771821-CreateClaim/Up/02-MoveToClaim.sql b/database/0.1.5/1694609771821-CreateClaim/Up/02-MoveToClaim.sql new file mode 100644 index 0000000..c95401a --- /dev/null +++ b/database/0.1.5/1694609771821-CreateClaim/Up/02-MoveToClaim.sql @@ -0,0 +1,14 @@ +INSERT INTO claim ( + Id, + WhenCreated, + WhenUpdated, + ClaimId, + InventoryId +) +SELECT + UUID(), + NOW(), + NOW(), + ClaimId, + Id +FROM inventory; \ No newline at end of file diff --git a/database/0.1.5/1694609771821-CreateClaim/Up/03-AlterInventory.sql b/database/0.1.5/1694609771821-CreateClaim/Up/03-AlterInventory.sql new file mode 100644 index 0000000..7005ca3 --- /dev/null +++ b/database/0.1.5/1694609771821-CreateClaim/Up/03-AlterInventory.sql @@ -0,0 +1,2 @@ +ALTER TABLE inventory +DROP ClaimId; \ No newline at end of file diff --git a/package.json b/package.json index 92b174d..505b116 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "card-drop", - "version": "0.1.1", + "version": "0.1.5", "main": "./dist/bot.js", "typings": "./dist", "scripts": { diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts index 5412db8..6f9ae58 100644 --- a/src/buttonEvents/Claim.ts +++ b/src/buttonEvents/Claim.ts @@ -2,6 +2,7 @@ import { ButtonInteraction } from "discord.js"; import { ButtonEvent } from "../type/buttonEvent"; import Inventory from "../database/entities/app/Inventory"; import { CoreClient } from "../client/client"; +import { default as eClaim } from "../database/entities/app/Claim"; export default class Claim extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -9,30 +10,36 @@ export default class Claim extends ButtonEvent { const cardNumber = interaction.customId.split(' ')[1]; const claimId = interaction.customId.split(' ')[2]; + const droppedBy = interaction.customId.split(' ')[3]; const userId = interaction.user.id; - const claimed = await Inventory.FetchOneByClaimId(claimId); + const claimed = await eClaim.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'); + if (claimId == CoreClient.ClaimId && userId != droppedBy) { + await interaction.reply('The latest dropped card can only be claimed by the user who dropped it'); return; } let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); if (!inventory) { - inventory = new Inventory(userId, cardNumber, 1, claimId); + inventory = new Inventory(userId, cardNumber, 1); } else { inventory.SetQuantity(inventory.Quantity + 1); } await inventory.Save(Inventory, inventory); + const claim = new eClaim(claimId); + claim.SetInventory(inventory); + + await claim.Save(eClaim, claim); + await interaction.reply('Card claimed'); } } \ No newline at end of file diff --git a/src/buttonEvents/Reroll.ts b/src/buttonEvents/Reroll.ts index e5aeed9..bc91c90 100644 --- a/src/buttonEvents/Reroll.ts +++ b/src/buttonEvents/Reroll.ts @@ -28,6 +28,8 @@ export default class Reroll extends ButtonEvent { const image = readFileSync(randomCard.Path); + await interaction.deferReply(); + const attachment = new AttachmentBuilder(image, { name: randomCard.FileName }); const embed = new EmbedBuilder() @@ -43,7 +45,7 @@ export default class Reroll extends ButtonEvent { row.addComponents( new ButtonBuilder() - .setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) + .setCustomId(`claim ${randomCard.CardNumber} ${claimId} ${interaction.user.id}`) .setLabel("Claim") .setStyle(ButtonStyle.Primary), new ButtonBuilder() diff --git a/src/client/client.ts b/src/client/client.ts index b517a28..66907bb 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -9,7 +9,6 @@ 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"; diff --git a/src/commands/drop.ts b/src/commands/drop.ts index 5770903..7503bf7 100644 --- a/src/commands/drop.ts +++ b/src/commands/drop.ts @@ -51,7 +51,7 @@ export default class Drop extends Command { row.addComponents( new ButtonBuilder() - .setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) + .setCustomId(`claim ${randomCard.CardNumber} ${claimId} ${interaction.user.id}`) .setLabel("Claim") .setStyle(ButtonStyle.Primary), new ButtonBuilder() @@ -76,7 +76,6 @@ export default class Drop extends Command { } } - CoreClient.ClaimId = claimId; } } \ No newline at end of file diff --git a/src/database/entities/app/Claim.ts b/src/database/entities/app/Claim.ts new file mode 100644 index 0000000..b4cde5e --- /dev/null +++ b/src/database/entities/app/Claim.ts @@ -0,0 +1,31 @@ +import { Column, Entity, ManyToOne } from "typeorm"; +import AppBaseEntity from "../../../contracts/AppBaseEntity"; +import Inventory from "./Inventory"; +import AppDataSource from "../../dataSources/appDataSource"; + +@Entity() +export default class Claim extends AppBaseEntity { + constructor(claimId: string) { + super(); + + this.ClaimId = claimId; + } + + @Column() + ClaimId: string; + + @ManyToOne(() => Inventory, x => x.Claims) + Inventory: Inventory; + + public SetInventory(inventory: Inventory) { + this.Inventory = inventory; + } + + public static async FetchOneByClaimId(claimId: string): Promise { + const repository = AppDataSource.getRepository(Claim); + + const single = await repository.findOne({ where: { ClaimId: claimId }}); + + return single; + } +} \ No newline at end of file diff --git a/src/database/entities/app/Inventory.ts b/src/database/entities/app/Inventory.ts index c6319a9..adec824 100644 --- a/src/database/entities/app/Inventory.ts +++ b/src/database/entities/app/Inventory.ts @@ -1,16 +1,16 @@ -import { Column, Entity } from "typeorm"; +import { Column, Entity, OneToMany } from "typeorm"; import AppBaseEntity from "../../../contracts/AppBaseEntity"; import AppDataSource from "../../dataSources/appDataSource"; +import Claim from "./Claim"; @Entity() export default class Inventory extends AppBaseEntity { - constructor(userId: string, cardNumber: string, quantity: number, claimId: string) { + constructor(userId: string, cardNumber: string, quantity: number) { super(); this.UserId = userId; this.CardNumber = cardNumber; this.Quantity = quantity; - this.ClaimId = claimId; } @Column() @@ -22,13 +22,17 @@ export default class Inventory extends AppBaseEntity { @Column() Quantity: number; - @Column() - ClaimId: string; + @OneToMany(() => Claim, x => x.Inventory) + Claims: Claim[]; public SetQuantity(quantity: number) { this.Quantity = quantity; } + public AddClaim(claim: Claim) { + this.Claims.push(claim); + } + public static async FetchOneByCardNumberAndUserId(userId: string, cardNumber: string): Promise { const repository = AppDataSource.getRepository(Inventory); @@ -36,12 +40,4 @@ export default class Inventory extends AppBaseEntity { 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/migrations/app/0.1.5/1694609771821-CreateClaim.ts b/src/database/migrations/app/0.1.5/1694609771821-CreateClaim.ts new file mode 100644 index 0000000..22fe74c --- /dev/null +++ b/src/database/migrations/app/0.1.5/1694609771821-CreateClaim.ts @@ -0,0 +1,17 @@ +import { MigrationInterface, QueryRunner } from "typeorm" +import MigrationHelper from "../../../../helpers/MigrationHelper" + +export class CreateClaim1694609771821 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + MigrationHelper.Up('1694609771821-CreateClaim', '0.1.5', [ + '01-CreateClaim', + '02-MoveToClaim', + '03-AlterInventory', + ], queryRunner); + } + + public async down(queryRunner: QueryRunner): Promise { + } + +} diff --git a/src/helpers/CardDropHelper.ts b/src/helpers/CardDropHelper.ts index a7d0a02..d5d8743 100644 --- a/src/helpers/CardDropHelper.ts +++ b/src/helpers/CardDropHelper.ts @@ -4,13 +4,6 @@ import Series from "../database/entities/card/Series"; export default class CardDropHelper { public static async GetRandomCard(): Promise { - 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; @@ -24,6 +17,13 @@ export default class CardDropHelper { else if (randomRarity < goldChance) cardRarity = CardRarity.Gold; else cardRarity = CardRarity.Legendary; + const allSeries = await Series.FetchAll(Series, [ "Cards", "Cards.Series" ]); + const allSeriesWithCards = allSeries.filter(x => x.Cards.length > 0 && x.Cards.find(x => x.Rarity == cardRarity)); + + const randomSeriesIndex = Math.floor(Math.random() * allSeriesWithCards.length); + + const randomSeries = allSeriesWithCards[randomSeriesIndex]; + const allCards = randomSeries.Cards.filter(x => x.Rarity == cardRarity && x.Path && x.FileName); const randomCardIndex = Math.floor(Math.random() * allCards.length); diff --git a/yarn.lock b/yarn.lock index 3d97459..eda61a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -910,14 +910,14 @@ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== "@types/uuid@^9.0.0": - version "9.0.3" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.3.tgz#6cdd939b4316b4f81625de9f06028d848c4a1533" - integrity sha512-taHQQH/3ZyI3zP8M/puluDEIEvtQHVYcC6y3N8ijFtAd28+Ey/G4sg1u2gB01S8MwybLOKAp9/yCMu/uR5l3Ug== + version "9.0.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.4.tgz#e884a59338da907bda8d2ed03e01c5c49d036f1c" + integrity sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA== "@types/ws@^8.5.5": - version "8.5.5" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" - integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg== + version "8.5.6" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.6.tgz#e9ad51f0ab79b9110c50916c9fcbddc36d373065" + integrity sha512-8B5EO9jLVCy+B58PLHvLDuOD8DRVMgQzq8d55SjLCOn9kqGyqOvy27exVaTio1q1nX5zLu8/6N0n2ThSxOM6tg== dependencies: "@types/node" "*"