diff --git a/database/0.6/1715967355818-daily/Up/01-table/User.sql b/database/0.6/1715967355818-daily/Up/01-table/User.sql new file mode 100644 index 0000000..8699650 --- /dev/null +++ b/database/0.6/1715967355818-daily/Up/01-table/User.sql @@ -0,0 +1,2 @@ +ALTER TABLE `user` +ADD LastUsedDaily datetime null; \ No newline at end of file diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts index f15e1ae..a643905 100644 --- a/src/buttonEvents/Claim.ts +++ b/src/buttonEvents/Claim.ts @@ -8,6 +8,7 @@ import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import { readFileSync } from "fs"; import path from "path"; import User from "../database/entities/app/User"; +import CardConstants from "../constants/CardConstants"; export default class Claim extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -42,11 +43,11 @@ export default class Claim extends ButtonEvent { await inventory.Save(Inventory, inventory); - const user = await User.FetchOneById(User, userId) || new User(userId, 300); + const user = await User.FetchOneById(User, userId) || new User(userId, CardConstants.StartingCurrency); AppLogger.LogSilly("Button/Claim", `${user.Id} has ${user.Currency} currency`); - if (!user.RemoveCurrency(10)) { + if (!user.RemoveCurrency(CardConstants.ClaimCost)) { await interaction.reply(`Not enough currency! You need 10 currency, you have ${user.Currency}`); return; } diff --git a/src/buttonEvents/Sacrifice.ts b/src/buttonEvents/Sacrifice.ts index 6c4a1a6..a82ba81 100644 --- a/src/buttonEvents/Sacrifice.ts +++ b/src/buttonEvents/Sacrifice.ts @@ -24,6 +24,11 @@ export default class Sacrifice extends ButtonEvent { const userId = interaction.customId.split(" ")[2]; const cardNumber = interaction.customId.split(" ")[3]; + if (userId != interaction.user.id) { + await interaction.reply("Only the user who created this sacrifice can confirm it."); + return; + } + const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); if (!cardInInventory) { @@ -67,8 +72,8 @@ export default class Sacrifice extends ButtonEvent { const embed = new EmbedBuilder() .setTitle("Card Sacrificed") .setDescription(description.join("\n")) - .setColor(EmbedColours.Ok) - .setFooter({ text: `${interaction.user.username} · ${cardData.card.name}` }); + .setColor(EmbedColours.Green) + .setFooter({ text: `${interaction.user.username}` }); const row = new ActionRowBuilder() .addComponents([ @@ -94,6 +99,11 @@ export default class Sacrifice extends ButtonEvent { const userId = interaction.customId.split(" ")[2]; const cardNumber = interaction.customId.split(" ")[3]; + if (userId != interaction.user.id) { + await interaction.reply("Only the user who created this sacrifice can cancel it."); + return; + } + const cardInInventory = await Inventory.FetchOneByCardNumberAndUserId(userId, cardNumber); if (!cardInInventory) { @@ -122,8 +132,8 @@ export default class Sacrifice extends ButtonEvent { const embed = new EmbedBuilder() .setTitle("Sacrifice Cancelled") .setDescription(description.join("\n")) - .setColor(EmbedColours.Error) - .setFooter({ text: `${interaction.user.username} · ${cardData.card.name}` }); + .setColor(EmbedColours.Grey) + .setFooter({ text: `${interaction.user.username}` }); const row = new ActionRowBuilder() .addComponents([ diff --git a/src/commands/daily.ts b/src/commands/daily.ts new file mode 100644 index 0000000..172b942 --- /dev/null +++ b/src/commands/daily.ts @@ -0,0 +1,43 @@ +import { CommandInteraction, SlashCommandBuilder } from "discord.js"; +import { Command } from "../type/command"; +import User from "../database/entities/app/User"; +import CardConstants from "../constants/CardConstants"; +import TimeLengthInput from "../helpers/TimeLengthInput"; + +export default class Daily extends Command { + constructor() { + super(); + + this.CommandBuilder = new SlashCommandBuilder() + .setName("daily") + .setDescription("Gain bonus currency, once a day"); + } + + public override async execute(interaction: CommandInteraction) { + const user = await User.FetchOneById(User, interaction.user.id) ?? new User(interaction.user.id, CardConstants.StartingCurrency); + + const dayAgo = new Date(Date.now() - (1000 * 60 * 60 * 24)); + + if (user.LastUsedDaily && user.LastUsedDaily > dayAgo) { + const timeNow = Date.now(); + const timeLength = 24 * 60 * 60 * 1000; // 1 day + + const timeLeft = Math.ceil(((timeLength - (timeNow - user.LastUsedDaily.getTime()))) / 1000 / 60); + + const timeLeftHours = Math.floor(timeLeft / 60); + const timeLeftMinutes = timeLeft % 60; + + const timeLeftString = new TimeLengthInput(`${timeLeftHours}h ${timeLeftMinutes}m`); + + await interaction.reply(`You have already used the daily command! You can use it again in **${timeLeftString.GetLength()}**.`); + return; + } + + user.AddCurrency(CardConstants.DailyCurrency); + user.UpdateLastUsedDaily(new Date()); + + await user.Save(User, user); + + await interaction.reply(`Given ${CardConstants.DailyCurrency} currency to ${interaction.user.username}`); + } +} \ No newline at end of file diff --git a/src/commands/sacrifice.ts b/src/commands/sacrifice.ts index c6dc7b3..4d1c51a 100644 --- a/src/commands/sacrifice.ts +++ b/src/commands/sacrifice.ts @@ -50,8 +50,8 @@ export default class Sacrifice extends Command { const embed = new EmbedBuilder() .setTitle("Sacrifice") .setDescription(description.join("\n")) - .setColor(EmbedColours.Grey) - .setFooter({ text: `${interaction.user.username} · ${cardData.card.name}` }); + .setColor(EmbedColours.Error) + .setFooter({ text: `${interaction.user.username}` }); const row = new ActionRowBuilder() .addComponents([ diff --git a/src/constants/CardConstants.ts b/src/constants/CardConstants.ts new file mode 100644 index 0000000..dfc89b8 --- /dev/null +++ b/src/constants/CardConstants.ts @@ -0,0 +1,5 @@ +export default class CardConstants { + public static readonly ClaimCost = 10; + public static readonly DailyCurrency = 100; + public static readonly StartingCurrency = 300; +} \ No newline at end of file diff --git a/src/constants/EmbedColours.ts b/src/constants/EmbedColours.ts index 36777e3..f270eef 100644 --- a/src/constants/EmbedColours.ts +++ b/src/constants/EmbedColours.ts @@ -1,8 +1,14 @@ export default class EmbedColours { + // General public static readonly Ok = 0x3050ba; public static readonly Success = 0x50c878; public static readonly Error = 0xff0000; + + // Colours public static readonly Grey = 0xd3d3d3; + public static readonly Green = 0x228B22; + + // Card Types public static readonly BronzeCard = 0xcd7f32; public static readonly SilverCard = 0xc0c0c0; public static readonly GoldCard = 0xffd700; diff --git a/src/database/entities/app/User.ts b/src/database/entities/app/User.ts index a909552..c3d8437 100644 --- a/src/database/entities/app/User.ts +++ b/src/database/entities/app/User.ts @@ -13,6 +13,9 @@ export default class User extends AppBaseEntity { @Column() Currency: number; + @Column() + LastUsedDaily?: Date; + public AddCurrency(amount: number) { this.Currency += amount; } @@ -24,4 +27,8 @@ export default class User extends AppBaseEntity { return true; } + + public UpdateLastUsedDaily(lastUsedDaily: Date) { + this.LastUsedDaily = lastUsedDaily; + } } \ No newline at end of file diff --git a/src/database/migrations/app/0.6/1715967355818-daily.ts b/src/database/migrations/app/0.6/1715967355818-daily.ts new file mode 100644 index 0000000..1c81d18 --- /dev/null +++ b/src/database/migrations/app/0.6/1715967355818-daily.ts @@ -0,0 +1,15 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; +import MigrationHelper from "../../../../helpers/MigrationHelper"; + +export class Daily1715967355818 implements MigrationInterface { + + public async up(queryRunner: QueryRunner): Promise { + MigrationHelper.Up("1715967355818-daily", "0.6", [ + "01-table/User", + ], queryRunner); + } + + public async down(): Promise { + } + +} diff --git a/src/registry.ts b/src/registry.ts index 15202c5..dc2770d 100644 --- a/src/registry.ts +++ b/src/registry.ts @@ -3,6 +3,7 @@ import { Environment } from "./constants/Environment"; // Global Command Imports import About from "./commands/about"; +import Daily from "./commands/daily"; import Drop from "./commands/drop"; import Gdrivesync from "./commands/gdrivesync"; import Give from "./commands/give"; @@ -29,6 +30,7 @@ export default class Registry { public static RegisterCommands() { // Global Commands CoreClient.RegisterCommand("about", new About()); + CoreClient.RegisterCommand("daily", new Daily()); CoreClient.RegisterCommand("drop", new Drop()); CoreClient.RegisterCommand("gdrivesync", new Gdrivesync()); CoreClient.RegisterCommand("give", new Give());