From af14c7598e64a19f43e48af66a37bc415cfdce06 Mon Sep 17 00:00:00 2001 From: Vermium Sifell Date: Thu, 1 Jun 2023 15:01:33 +0200 Subject: [PATCH] fix: :sparkles: throw error if user tries to execute same command while one is processing If a user tries to execute same command twice at same time, then throw error on one of them to prevent them from go around the cooldown system --- .../handleCommandInteraction/index.ts | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts index c4004ee..68a2271 100644 --- a/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts +++ b/src/events/interactionCreate/interactionTypes/handleCommandInteraction/index.ts @@ -5,6 +5,9 @@ import generateCooldownName from "../../../../helpers/generateCooldownName"; import handleCooldown from "./handlers/handleCooldown"; import handleUnavailableCommand from "./handlers/handleUnavailableCommand"; +// Create a map to store locks for each identifier (guild ID + user ID + cooldown item) +const commandLocks = new Map(); + const cooldownManager = new CooldownManager(); export default async function handleCommandInteraction( @@ -24,6 +27,14 @@ export default async function handleCommandInteraction( try { const cooldownItem = await generateCooldownName(interaction); + + // Check if the identifier is already locked + if (commandLocks.has(cooldownItem)) { + throw new Error( + "You are unable to execute the same command simultaneously." + ); + } + const { guildCooldown, userCooldown, guildMemberCooldown } = await cooldownManager.checkCooldowns(cooldownItem, guild, user); @@ -38,10 +49,23 @@ export default async function handleCommandInteraction( userCooldown, guildMemberCooldown ); - } else { - await currentCommand.execute(interaction); + return; } + + // Create a promise that represents the current command execution + const commandExecutionPromise = currentCommand.execute(interaction); + + // Acquire the lock for the identifier and store the command execution promise + commandLocks.set(cooldownItem, commandExecutionPromise); + + // Wait for the current command execution to complete + await commandExecutionPromise; } catch (error) { await interactionErrorHandler(interaction, error); + } finally { + const cooldownItem = await generateCooldownName(interaction); + + // Release the lock for the identifier + commandLocks.delete(cooldownItem); } }