Here is my code, I want it to send a message if the command has been used twice within like 10 seconds. Idk but it is very wrong
var bumpEmbedTwo = new Discord.MessageEmbed()
.setTitle('Cool Down!!!')
.setColor(0xFF0000)
.setDescription('Please waitt 30 more seconds before you use this command again')
setTimeout(() => {
message.channel.send(bumpEmbedTwo)
}, 5000)
var bumpEmbed = new Discord.MessageEmbed()
.setTitle('Time to Bump!')
.setColor(0xFF0000)
.setDescription('Please use the command `!d bump` to bump the server!!!')
setTimeout(() => {
message.channel.send('<#&812133021590880316>')
message.channel.send(bumpEmbed)
}, 1000)
The code you have provided isn't correct as your doing a set timeout without an await so it would completely ignore the purpose of the timeout. Also, whenever the .on('message') function is used, it would still carry out the command, what you have to do is to create an object: const cooldowns = new Discord.Collection(); and whenever the 'message' event is triggered, you would have to add whatever amount of cool down you want.
So here's the code:
const now = Date.now();
let cooldownAmount = 5 * 1000; // In this case, it is 5 seconds
if (cooldowns.has(message.author.id)) {
const expirationTime = cooldowns.get(message.author.id) + cooldownAmount;
if (now < expirationTime) {
const timeLeft = (expirationTime - now) / 1000;
return message.channel.send(`Please wait ${timeLeft.toFixed(1)} more second(s) before using another command`);
}
}
if(!cooldowns.has(message.author.id)){
<command>.run() // Be sure to edit <command to whatever the fetched command is> and add to the (), e.g. message, args, bot, etc.
}
cooldowns.set(message.author.id, now);
setTimeout(() => cooldowns.delete(message.author.id), cooldownAmount);
PS: the client in the arrow symbols are for you to change.
If there are any extra questions, you can comment in this post! Or dm me on discord: N̷i̷g̷h̷t̷m̷a̷r̷e̷ ̷ Jeff#2616
One way to approach this problem would be to save user+command+time in DB or in some global variable.
And then perform a check.
Pseudo-code:
var storage = {
"/command": {
"user-id-123": "22/02/2021 5:27pm"
"user-id-345": "22/02/2021 3:12pm"
}
};
Chat.on("/command", (user) => {
if (!storage["/command"].hasOwnProperty(user.id)) {
storage["/command"][user.id] = Date.now();
}
if (storage["/command"][user.id] > Date.now() + 10 seconds) {
return "Please wait more";
} else {
return "I'm running your command";
}
});
Related
So I have a new discord bot and newish to programming, like I kinda understand it but can't do it on my own. but on to the question. The bot is all in the .js (I do have the config.json) but I have yet to get event handler to work. but my code is.
client.on("message", (message) => {
if (message.author.bot) return;
if (message.content.includes ("John")) {
message.channel.send ("Oh yeah, that guy...");
}
}
How can I get a global cooldown? I want the cooldown so if a convo about John occurs, the bot isn't gonna respond to every message.
Easiest thing to do is create a variable outside the listener, with a timestamp, and compare current timestamp to the one set outside the scope, like so
var lastReply = 0;
client.on("message", (message) => {
if (Date.now() - lastReply < 10000) return; // don't respond within 10 seconds
lastReply = Date.now();
if (message.author.bot) return;
if (message.content.includes ("John")) {
message.channel.send ("Oh yeah, that guy...");
}
}
I've set it to 10 seconds, but you can of course get this from a config, or change it yourself. For clarity (easy reading) you can also set a value like this (for lets say, 5 minutes): lastReply < 5 * 60 * 1000
var cooldown = false;
client.on("message", (message) => {
if (message.author.bot) return;
if (message.content.includes("John")) {
if (cooldown == true) {
//Bot is on a cooldown
return;
} else {
message.channel.send("Oh yeah, that guy...");
cooldown = true;
setTimeout(() => {
cooldown = false
}, 60000); //Timeout for a minute
}
}
}
Kinda new to discord programming myself but this is similar to what I used.
I am looking to make a cool down system for discord bot commands using discord.js. I am looking for it to show the time remaining left on the cool down when the user tries to do the command. Currently I have it so it does a cool down using the command handler so that I just have to add "timeout: '10000'," although I cant seem to find a way to get it show the time remaining by using this system.
This is the code that I currently have in my message.js file so that is can be used with the command handler so that I do not have to write the timeout code on every command file. Code below is the whole message.js file.
const Timeout = new Set();
const { MessageEmbed } = require('discord.js')
const {prefix} = require('../../config.json')
const ms = require('ms')
module.exports=async(bot, message)=>{
if(message.author.bot) return;
if(!message.content.toLowerCase().startsWith(prefix)) return;
if(!message.member) message.member = await message.guild.fetchMember(messsage);
if(!message.guild) return;
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const cmd = args.shift().toLowerCase();
if(cmd.length === 0) return;
let command = bot.commands.get(cmd);
if(!command) command = bot.commands.get(bot.aliases.get(cmd));
if(command){
if(command.timeout){
if(Timeout.has(`${message.author.id}${command.name}`)){
return message.reply(`**Slow down, you can only use this command every ${ms(command.timeout)}!**`)
} else {
command.run(bot, message, args);
Timeout.add(`${message.author.id}${command.name}`)
setTimeout(() => {
Timeout.delete(`${message.author.id}${command.name}`)
}, command.timeout);
}
} else {
command.run(bot, message, args)
}
}
}
Current response is above in bold text.
For reference, the message.js file is referenced in the following code in my index.js file.
bot.on('message', async message =>{
require('./events/guild/message')(bot, message)
})
The following is what I have to put at the beginning of each command file, with a simple command example shown for reference.
const Discord = require('discord.js');
module.exports={
name: 'test',
category: 'info',
timeout: '15000', //This would result in a 15 second cooldown as time is in ms.
run: async(bot, message, args) =>{
message.channel.send(`test`)
}
}
To conclude, I am looking to keep my system, but instead of it saying "Slow down, you can only use this command every 15000! (For example above) I would like it to say something in the lines of "Slow it down, you can use this command again in 10s.
The default cooldown is 15s.
If I'm not mistaken you want to convert every 15000 into every 15s?
You already have the ms module so looks like you are just confused how to use it:
If it receives a string it converts it into ms, if it receives a number it converts it into a readable format like 1d 2h 3m,
In your module.exports you have it a string, so make it a number and everything is fixed.
That string might also intercept with setTimeout(func, time)
If for some reason you don't want to change the module.exports.timeout into a string, before you call ms, you will have to do parseInt(command.timeout)
code:
let command = bot.commands.get(cmd) || bot.commands.get(bot.aliases.get(cmd));
if (!command) return;
if (!command.timeout) return command.run(bot, message, args);
//if you changed it to a number in module.exports you don't have to parseInt it
const timeout = parseInt(command.timeout);
if (Timeout.has(`${message.author.id}${command.name}`)) {
return message.reply(`**Slow down, you can only use this command every ${ms(timeout)}!**`)
} else {
command.run(bot, message, args);
Timeout.add(`${message.author.id}${command.name}`)
setTimeout(() => {
Timeout.delete(`${message.author.id}${command.name}`)
}, timeout);
}
Second part:
You will need to track when you set the timeout, the issue with using the Set class is that it's
not a key value based, so there's two options:
Set.add({ key: key, time: Date.now()}) or use Discord.Collection / Map
First: still using Set, setting objects instead:
const timeout = command.timeout;
const key = message.author.id + command.name;
let found;
for(const e of Timeout) {
if(e.key === key) {
found = e;
//possibly bad practice, arguable
break;
}
}
if(found) {
const timePassed = Date.now() - found.time;
const timeLeft = timeout - timePassed;
//the part at this command has a default cooldown of, did you want to hard code 15s? or have it be the commands.config.timeout?
return message.reply(`**Slow down, you can use this command again in ${ms(timeLeft)} This command has a default cooldown of ${timeout}!**`)
} else {
command.run(bot, message, args);
Timeout.add({ key, time: Date.now() });
setTimeout(() => {
Timeout.delete(key);
}, timeout);
}
Second: Discord.Collection or Map works too since its just an extended class from that
I'm going with Map, if you use Collection just do:
const { MessageEmbed, Collection } = require("discord.js");
const Timeout = new Collection();
Map code:
const Timeout = new Map();
After code:
const timeout = command.timeout;
const key = message.author.id + command.name;
const found = Timeout.get(key);
if(found) {
const timePassed = Date.now() - found;
const timeLeft = timeout - timePassed;
//the part at this command has a default cooldown of, did you want to hard code 15s? or have it be the commands.config.timeout?
return message.reply(`**Slow down, you can use this command again in ${ms(timeLeft)} This command has a default cooldown of ${timeout}!**`);
} else {
command.run(bot, message, args);
Timeout.set(key, Date.now());
setTimeout(() => {
Timeout.delete(key);
}, timeout);
}
I've made a discord bot, here the code
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("ready", () => {
console.log("I am ready!");
});
client.on("message", (message) => {
if (message.content.startsWith("!kevin")) {
message.channel.send("i'm kevin");
}
if (message.content.startsWith("!thomas")) {
message.channel.send("random text blabla");
}
Basically, when I type !something, my bot answer in the chat by the proper line, my current issue is my discord is kinda big nowadays, and I would like to restrict the bot to only X messages per minutes, but I can't find an easy function to do that
my question :
Is it possible to get a timer between 2 messages to send by the bot, because without that my bot is just spamming answer to each users typing !somethingsomething, I would like my bot to as soon as someone type !something, the bot lock itself of replying to any other !something for X amount of time
Example,
User 1 : !thomas
User 2 : !thomas
User 3 : !thomas
But the bot only reply to one of them and put a timer to himself before being able to send a new !message reply
So basically, is it any way to make the bot reply to X amounts of !cmd each minutes, or to limits the cooldown between 2 messages the bot send
here my script : https://i.imgur.com/Q7w98Rm.jpg ( i know its terrible especially since it have over 9000 differents !cmd , but i converted quickly a old MIRC script and im terrible at javascript)
Cooldown for the users and/or bot
So I found out from your comments that you want the bot to only run a command only every "X" amount of time. I don't recommend this, I recommend just preventing USERS from registering a cmd every "X" amount of time. I've included both in this example.
let lastCmdSentTime = {};
let waitTimeForUser = 60000 * 5; //Users can only run a command once every 5 minutes
let botLastSent = false;
let timeBetweenEachCmd = 60000; //Bot will only respond once a minute.
client.on("message", (message) => {
if(botLastSent !== false ? message.createdTimestamp - botLastSent < timeBetweenEachCmd : false) return; //don't let the bot run a cmd every [timeBetweenEachCmd]
let userLastSent = lastCmdSentTime[message.author.id] || false;
if(userLastSent !== false ? message.createdTimestamp - userLastSent < waitTimeForUser : false) return; //don't let the user run a cmd every [waitTimeForUser]
lastCmdSentTime[message.author.id] = message.createdTimestamp;
botLastSent = message.createdTimestamp;
//RUN COMMANDS
});
Cooldown for commands
Simply store the date the command was ran, then check if a certain amount has passed since the date was set.
Example:
Edited to support multiple commands
let date = false;
let commandsTimers = {
"!kevin":{
waitTime: 5 * 60000, // 5 minutes wait for this particular command.
lastUsed: false,
}
}
let defaultWaitTime = 60000 * 2; //User needs to wait 2 minutes for each command unless specified
client.on("message", (message) => {
let msgSentDate = Date.now();
let commandWaitTimer = commandsTimers[message.content.split(" ")[0]] || {waitTime:defaultWaitTime, lastUsed:false};
if((commandWaitTimer.lastUsed !== false ? msgSentDate - commandWaitTimer.lastUsed < commandWaitTimer.waitTime : false)){
console.log('User needs to wait: ' + (commandWaitTimer.waitTime - (msgSentDate - commandWaitTimer .lastUsed)) / 1000 + ' seconds');
return
}
commandsTimers[message.content.split(" ")[0]].lastUsed = msgSentDate;
if (message.content.startsWith("!thomas")) {
message.channel.send("random text blabla");
}
if (message.content.startsWith("!kevin")) {
message.channel.send("Kevin!");
}
});
When a bot joins a server, it is triggering 2 events. 1st is the guildCreate event, and the second is the channelCreate event.
Here is my events loader:
const ascii = require("ascii-table");
let table = new ascii("Events");
table.setHeading("Event", "Load status");
const load = async () => {
const evtFiles = await readdir("./events");
var total = 0;
evtFiles.forEach(file => {
if (file.split(".").slice(-1)[0] !== "js") return;
const evtName = file.split(".")[0];
const event = require(`./events/${file}`);
table.addRow(file, '✅');
client.on(evtName, event.bind(null, client));
delete require.cache[require.resolve(`./events/${file}`)];
total = total +1;
})
console.log(table.toString());
console.log(`Total no of events ${total} loaded ✅`);
}
load();
Here is my guildCreate event:
const Discord = require("discord.js");
const fs = require("fs");
const config1 = require("../config.json");
module.exports = (client, message,guild) => {
console.log(`Hi, ${client.user.username} is now serving in ${client.guilds.size} servers and serving ${client.guilds.reduce((c, p) => c + p.memberCount, 0)} users!.`);
}
Here is my channelCreate event:
const Discord = require("discord.js");
module.exports = async ( client , channel ) => {
// event firing when it joins a guild
var log = channel.guild.channels.find(ch => ch.name.includes('member-log'))
var sEmbed = new Discord.RichEmbed()
.setColor("RANDOM")
.setTitle(`:information_source: A channel Was Created!`)
.setDescription(`**Name**\n${channel}`)
.addField(`**Type**`,`${channel.type}`)
.setFooter(`ChannelID:${channel.id} | CreatedAT:${channel.createdAt}`);
log.send(sEmbed);
}
What can I do to stop this channelCreate event from firing when joining a guild?
got it Date.now()/1000+2 wont work it was a bit before than this event even triggered XD .I did this and its working its better as sometimes if the server has too many channel then its better to increase time up to 30 sec its safer
client.on("channelCreate", (channel) => {
let x = channel.guild.me.joinedTimestamp / 1000
if(x <= (x+10)) return; // if the bot just joined the server the channelcreate event will get activated after 10 sec
console.log("Valid event!");
});
There was an issue in the Discord.js repository yesterday about it. The only way I find it's to check if the bot joined the server less than 2 seconds ago. For example:
client.on("channelCreate", (channel) => {
if((channel.guild.me.joinedTimestamp / 1000) < (Date.now()/1000+2)) return;
console.log("Valid event!");
});
Note you can also check if the channel was created less than x seconds. For example if the event receive a channel which was created 2 years ago... it's not a valid event.
I'm trying to make the bot writing messages at specific times. Example:
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("ready", () => {
console.log("Online!");
});
var now = new Date();
var hour = now.getUTCHours();
var minute = now.getUTCMinutes();
client.on("message", (message) => {
if (hour === 10 && minute === 30) {
client.channels.get("ChannelID").send("Hello World!");
}
});
Unfortunately, it only works once I trigger another command like:
if (message.content.startsWith("!ping")) {
message.channel.send("pong!");
}
my message: !ping (at 10:10 o'clock)
-> pong!
-> Hello World!
I guess it needs something that constantly checks the time variables.
I would use cron: with this package you can set functions to be executed if the date matches the given pattern.
When building the pattern, you can use * to indicate that it can be executed with any value of that parameter and ranges to indicate only specific values: 1-3, 7 indicates that you accept 1, 2, 3, 7.
These are the possible ranges:
Seconds: 0-59
Minutes: 0-59
Hours: 0-23
Day of Month: 1-31
Months: 0-11 (Jan-Dec)
Day of Week: 0-6 (Sun-Sat)
Here's an example:
var cron = require("cron");
function test() {
console.log("Action executed.");
}
let job1 = new cron.CronJob('01 05 01,13 * * *', test); // fires every day, at 01:05:01 and 13:05:01
let job2 = new cron.CronJob('00 00 08-16 * * 1-5', test); // fires from Monday to Friday, every hour from 8 am to 16
// To make a job start, use job.start()
job1.start();
// If you want to pause your job, use job.stop()
job1.stop();
In your case, I would do something like this:
const cron = require('cron');
client.on('message', ...); // You don't need to add anything to the message event listener
let scheduledMessage = new cron.CronJob('00 30 10 * * *', () => {
// This runs every day at 10:30:00, you can do anything you want
let channel = yourGuild.channels.get('id');
channel.send('You message');
});
// When you want to start it, use:
scheduledMessage.start()
// You could also make a command to pause and resume the job
As Federico stated, that is the right way to solve this problem but the syntax has changed and now with the new update of discord.js (v12) it would be like:
// Getting Discord.js and Cron
const Discord = require('discord.js');
const cron = require('cron');
// Creating a discord client
const client = new Discord.Client();
// We need to run it just one time and when the client is ready
// Because then it will get undefined if the client isn't ready
client.once("ready", () => {
console.log(`Online as ${client.user.tag}`);
let scheduledMessage = new cron.CronJob('00 30 10 * * *', () => {
// This runs every day at 10:30:00, you can do anything you want
// Specifing your guild (server) and your channel
const guild = client.guilds.cache.get('id');
const channel = guild.channels.cache.get('id');
channel.send('You message');
});
// When you want to start it, use:
scheduledMessage.start()
};
// You could also make a command to pause and resume the job
But still credits to Federico, he saved my life!