From 7d870f06fb5b43fb72391a4332a465318f48f80e Mon Sep 17 00:00:00 2001 From: Daryl Ronningen Date: Wed, 30 Jun 2021 18:32:27 -0500 Subject: [PATCH] feat(commands): added cooldowns --- src/commands/general/help.ts | 2 -- src/index.ts | 30 ++++++++++++++++++++++++++++++ src/lib/structures/command.ts | 1 + src/lib/utils/types.ts | 1 + translations/en-US/commands.json | 3 ++- translations/owo/commands.json | 3 ++- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/commands/general/help.ts b/src/commands/general/help.ts index 7bb13ba..0ee5ce5 100644 --- a/src/commands/general/help.ts +++ b/src/commands/general/help.ts @@ -19,8 +19,6 @@ import config from 'config'; import { Client, Message, MessageButton, MessageEmbed, MessageSelectMenu, MessageSelectOptionData } from 'discord.js'; import i18next from 'i18next'; -// TODO: Redo this mf - export default class extends Command { public constructor(client: Client, file: string) { super(client, file, { diff --git a/src/index.ts b/src/index.ts index bf83111..7c9e82a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -24,6 +24,7 @@ import { ECommandRunIn, ELoggingScope } from '@utils/types'; import { walkDir } from '@utils/utils'; import chalk from 'chalk'; import config from 'config'; +import { Collection } from 'discord.js'; import figlet from 'figlet'; import gradient from 'gradient-string'; import i18next from 'i18next'; @@ -36,6 +37,7 @@ import { Validator } from 'jsonschema'; import { DateTime } from 'luxon'; import process from 'process'; +const commandCooldowns: Collection> = new Collection(); let isBotReady = false; info('Starting bot... Please wait!', ELoggingScope.Startup); @@ -89,19 +91,47 @@ client.on('message', async (msg) => { if(findCommand.options.ownerOnly && msg.author.id !== config.get('owner')) { await msg.reply(i18next.t('commands:errors.ownerOnly')); + msg.channel.stopTyping(); return; } if((findCommand.options.runIn === ECommandRunIn.DM) && msg.channel.type !== 'dm') { await msg.reply(i18next.t('commands:errors.dmsOnly')); + msg.channel.stopTyping(); return; } if((findCommand.options.runIn === ECommandRunIn.Server) && msg.channel.type !== 'text') { await msg.reply(i18next.t('commands:errors.serverOnly')); + msg.channel.stopTyping(); return; } + if(msg.author.id !== config.get('owner')) { + if(!commandCooldowns.has(findCommand.options.name!)) { + commandCooldowns.set(findCommand.options.name!, new Collection()); + } + + const now = Date.now(); + const timestamps = commandCooldowns.get(findCommand.options.name!); + const cooldownAmount = findCommand.options.cooldown! * 1000; + + if(timestamps!.has(msg.author.id)) { + const expirationTime = timestamps!.get(msg.author.id)! + cooldownAmount; + + if(now < expirationTime) { + const timeLeft = (expirationTime - now) / 1000; + + await msg.reply(i18next.t('commands:errors.cooldownError', { time: timeLeft.toFixed(1), command: findCommand.options.name })); + msg.channel.stopTyping(); + return; + } + } + + timestamps!.set(msg.author.id, now); + setTimeout(() => timestamps!.delete(msg.author.id), cooldownAmount); + } + try { info(`Command ${findCommand.options.name} is being ran in ${msg.guild ? msg.guild.name : 'DMs'} by ${msg.author.username}`, ELoggingScope.Command); await findCommand.run(msg, ...args); diff --git a/src/lib/structures/command.ts b/src/lib/structures/command.ts index 6d67c5d..cd08fcf 100644 --- a/src/lib/structures/command.ts +++ b/src/lib/structures/command.ts @@ -31,6 +31,7 @@ export default abstract class Command { const defaultOptions: ICommandOptions = { name: path.basename(this.file, path.extname(this.file)), group: path.basename(path.dirname(this.file)) === 'commands' ? '' : path.basename(path.dirname(this.file)), + cooldown: 5, }; this.options = config.util.extendDeep(defaultOptions, options); diff --git a/src/lib/utils/types.ts b/src/lib/utils/types.ts index 36cd516..012890b 100644 --- a/src/lib/utils/types.ts +++ b/src/lib/utils/types.ts @@ -37,6 +37,7 @@ export interface ICommandOptions { extendedDescription?: string; usage?: string; ownerOnly?: boolean; + cooldown?: number; runIn?: ECommandRunIn; args?: { name: string; diff --git a/translations/en-US/commands.json b/translations/en-US/commands.json index b8e4602..efd2dcd 100644 --- a/translations/en-US/commands.json +++ b/translations/en-US/commands.json @@ -25,7 +25,8 @@ "ownerOnly": "Only the bot owner can run this command!", "dmsOnly": "You can only run this command in DMs!", "serverOnly": "You can only run this command in a server!", - "runError": "I'm sorry but an error has occurred while running this command! Please file an issue to https://code.relms.dev/Relms/ArgonBot!\n```{ $error }```" + "runError": "I'm sorry but an error has occurred while running this command! Please file an issue to https://code.relms.dev/Relms/ArgonBot!\n```{ $error }```", + "cooldownError": "Please wait { $time } more second(s) before reusing the `{ $command }` command." }, "generic": { "noShortDescription": "No short description given!", diff --git a/translations/owo/commands.json b/translations/owo/commands.json index 3fc413b..9404854 100644 --- a/translations/owo/commands.json +++ b/translations/owo/commands.json @@ -25,7 +25,8 @@ "ownerOnly": "Onwy the bot ownyew can wun this command ^w^", "dmsOnly": "You can onwy wun this command in DMs owo", "serverOnly": "You can onwy wun this command in a sewvew owo", - "runError": "I'm sowwy but an ewwow has occuwwed whiwe wunnying this command ;;w;; Pwease fiwe an issue to https://code.relms.dev/Relms/ArgonBot!\n```{ $error }```" + "runError": "I'm sowwy but an ewwow has occuwwed whiwe wunnying this command ;;w;; Pwease fiwe an issue to https://code.relms.dev/Relms/ArgonBot!\n```{ $error }```", + "cooldownError": "Pwease wait { $time } mowe second(s) befowe weusing the `{ $command }` command." }, "generic": { "noShortDescription": "Nyo showt descwiption given >w<",