Compare commits

...

2 commits

Author SHA1 Message Date
Ethan Lane 8ccd7c33d4 Prevent users from being able to claim the latest card unless you were the one to drop it
All checks were successful
continuous-integration/drone/push Build is passing
2023-09-13 15:06:53 +01:00
Ethan Lane ad505b3ea2 Fix users being able to claim a card twice if the user has multiple of it already 2023-09-13 14:37:17 +01:00
9 changed files with 90 additions and 20 deletions

View file

@ -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;

View file

@ -0,0 +1,10 @@
INSERT INTO claim (
Id,
ClaimId,
InventoryId
)
SELECT
UUID(),
ClaimId,
Id
FROM inventory;

View file

@ -0,0 +1,2 @@
ALTER TABLE inventory
DROP ClaimId;

View file

@ -2,6 +2,7 @@ import { ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent"; import { ButtonEvent } from "../type/buttonEvent";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client"; import { CoreClient } from "../client/client";
import { default as eClaim } from "../database/entities/app/Claim";
export default class Claim extends ButtonEvent { export default class Claim extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) { public override async execute(interaction: ButtonInteraction) {
@ -9,30 +10,36 @@ export default class Claim extends ButtonEvent {
const cardNumber = interaction.customId.split(' ')[1]; const cardNumber = interaction.customId.split(' ')[1];
const claimId = interaction.customId.split(' ')[2]; const claimId = interaction.customId.split(' ')[2];
const droppedBy = interaction.customId.split(' ')[3];
const userId = interaction.user.id; const userId = interaction.user.id;
const claimed = await Inventory.FetchOneByClaimId(claimId); const claimed = await eClaim.FetchOneByClaimId(claimId);
if (claimed) { if (claimed) {
await interaction.reply('This card has already been claimed'); await interaction.reply('This card has already been claimed');
return; return;
} }
if (claimId != CoreClient.ClaimId) { if (claimId == CoreClient.ClaimId && userId != droppedBy) {
await interaction.reply('This card has expired'); await interaction.reply('The latest dropped card can only be claimed by the user who dropped it');
return; return;
} }
let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); let inventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber);
if (!inventory) { if (!inventory) {
inventory = new Inventory(userId, cardNumber, 1, claimId); inventory = new Inventory(userId, cardNumber, 1);
} else { } else {
inventory.SetQuantity(inventory.Quantity + 1); inventory.SetQuantity(inventory.Quantity + 1);
} }
await inventory.Save(Inventory, inventory); await inventory.Save(Inventory, inventory);
const claim = new eClaim(claimId);
claim.SetInventory(inventory);
await claim.Save(eClaim, claim);
await interaction.reply('Card claimed'); await interaction.reply('Card claimed');
} }
} }

View file

@ -45,7 +45,7 @@ export default class Reroll extends ButtonEvent {
row.addComponents( row.addComponents(
new ButtonBuilder() new ButtonBuilder()
.setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) .setCustomId(`claim ${randomCard.CardNumber} ${claimId} ${interaction.user.id}`)
.setLabel("Claim") .setLabel("Claim")
.setStyle(ButtonStyle.Primary), .setStyle(ButtonStyle.Primary),
new ButtonBuilder() new ButtonBuilder()

View file

@ -51,7 +51,7 @@ export default class Drop extends Command {
row.addComponents( row.addComponents(
new ButtonBuilder() new ButtonBuilder()
.setCustomId(`claim ${randomCard.CardNumber} ${claimId}`) .setCustomId(`claim ${randomCard.CardNumber} ${claimId} ${interaction.user.id}`)
.setLabel("Claim") .setLabel("Claim")
.setStyle(ButtonStyle.Primary), .setStyle(ButtonStyle.Primary),
new ButtonBuilder() new ButtonBuilder()
@ -76,7 +76,6 @@ export default class Drop extends Command {
} }
} }
CoreClient.ClaimId = claimId; CoreClient.ClaimId = claimId;
} }
} }

View file

@ -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<Claim | null> {
const repository = AppDataSource.getRepository(Claim);
const single = await repository.findOne({ where: { ClaimId: claimId }});
return single;
}
}

View file

@ -1,16 +1,16 @@
import { Column, Entity } from "typeorm"; import { Column, Entity, OneToMany } from "typeorm";
import AppBaseEntity from "../../../contracts/AppBaseEntity"; import AppBaseEntity from "../../../contracts/AppBaseEntity";
import AppDataSource from "../../dataSources/appDataSource"; import AppDataSource from "../../dataSources/appDataSource";
import Claim from "./Claim";
@Entity() @Entity()
export default class Inventory extends AppBaseEntity { export default class Inventory extends AppBaseEntity {
constructor(userId: string, cardNumber: string, quantity: number, claimId: string) { constructor(userId: string, cardNumber: string, quantity: number) {
super(); super();
this.UserId = userId; this.UserId = userId;
this.CardNumber = cardNumber; this.CardNumber = cardNumber;
this.Quantity = quantity; this.Quantity = quantity;
this.ClaimId = claimId;
} }
@Column() @Column()
@ -22,13 +22,17 @@ export default class Inventory extends AppBaseEntity {
@Column() @Column()
Quantity: number; Quantity: number;
@Column() @OneToMany(() => Claim, x => x.Inventory)
ClaimId: string; Claims: Claim[];
public SetQuantity(quantity: number) { public SetQuantity(quantity: number) {
this.Quantity = quantity; this.Quantity = quantity;
} }
public AddClaim(claim: Claim) {
this.Claims.push(claim);
}
public static async FetchOneByCardNumberAndUserId(userId: string, cardNumber: string): Promise<Inventory | null> { public static async FetchOneByCardNumberAndUserId(userId: string, cardNumber: string): Promise<Inventory | null> {
const repository = AppDataSource.getRepository(Inventory); const repository = AppDataSource.getRepository(Inventory);
@ -36,12 +40,4 @@ export default class Inventory extends AppBaseEntity {
return single; 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

@ -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<void> {
MigrationHelper.Up('1694609771821-CreateClaim', '0.1.5', [
'01-CreateClaim',
'02-MoveToClaim',
'03-AlterInventory',
], queryRunner);
}
public async down(queryRunner: QueryRunner): Promise<void> {
}
}