Discord.js Ping Pong command with cooldown - javascript

I'm very new to coding so it's probably horrible. Here's the code
let userCooldown = {};
client.on("message", message => {
if (message.content.includes('ping'))
if (userCooldown[message.author.id]) {
userCooldown[message.author.id] = false;
message.reply('Pong');
setTimeout(() => {
userCooldown[message.author.id] = true;
}, 5000) // 5 sec
}
})
the plan would be for the bot not to respond to the message for 5 seconds until it's written again

Not sure why you set the cooldown to false if it's true when someone sends a message and why you set it to true after five seconds.
If your userCooldown includes the users who currently can't execute the function, you need to check if they are already on that list. If they are, don't execute the function. If they are not, execute the function, add them to the list and use setTimeout to remove them after five seconds. Try to run the snippet below:
let userCooldown = {};
function onMessage(message) {
console.log(`onMessage fired with message: "${message.content}"`);
if (message.content.includes('ping')) {
// if user can't execute the fucntion, just exit
if (userCooldown[message.author.id]) return;
// if they can, add them to userCooldown
userCooldown[message.author.id] = true;
console.log('Pong!');
// and remove them after 5 seconds
setTimeout(() => {
userCooldown[message.author.id] = false;
}, 5000);
}
}
// run it every second to test it :)
let message = { content: '!ping', author: { id: 'authorID' } };
setInterval(() => onMessage(message), 2000)

Related

How can I stop the interval?

I'm making a setInterval method in my discord bot, but I have an issue in stopping the Interval.
Look at my code:
const Discord = require('discord.js');
const client = new Discord.Client();
client.once('ready', () => {
console.log('Im online');
});
client.on('message', async msg => {
var interval;
if(msg.content == '!spam')
{
interval = setInterval(() => {
msg.channel.send('test');
}, 2000);
}
if(msg.content.startsWith('!stop'))
{
clearInterval(interval);
}
});
That should definitely work, right?
If you know the answer please help me!!
The problem is:
client.on('message', async msg => {
var interval;
This creates a new variable binding interval every single time the message handler runs. Inside any single message handler, either
interval = setInterval(() => {
msg.channel.send('test');
}, 2000);
will run, or
if (msg.content.startsWith('!stop')) {
clearInterval(interval);
}
will run (or neither will run). But the interval is not persistent outside of the function, so further messages will be attempting to clear a different interval binding.
Make interval persistent instead, and also check that you don't start an interval while one is already going on:
let interval;
client.on('message', (msg) => {
if (msg.content == '!spam' && !interval) {
interval = setInterval(() => {
msg.channel.send('test');
}, 2000);
}
if (msg.content.startsWith('!stop')) {
clearInterval(interval);
interval = null;
}
});

How to stop a setInterval function on discord.js? [duplicate]

This question already has answers here:
Stop setInterval call in JavaScript
(7 answers)
Closed 2 years ago.
I've been wanting to add a feature to my script, which can enable me to stop the setInterval function through a simple command, but the real problem is that I do not know how to do it.
client.on('message', async (message) => {
if (message.author.username === 'username')
if (message.content === '*shiba inu pupper') {
const attachment = new Discord.MessageAttachment('shiba doggo');
setInterval(() => {
message.channel.send(attachment);
}, 20000);
}
});
Ex: Your interval function:
let intervalFunc = setInterval(() => {
// code .....
}, 20000);
After that When you want to stop the interval time, use the below function:
clearInterval(intervalFunc);
Above function will clear your interval time
add my_interval global variable in your js file :
var my_interval;
then:
client.on('message', async (message) => {
if (message.author.username === 'username')
if (message.content === '*shiba inu pupper') {
const attachment = new Discord.MessageAttachment('shiba doggo');
my_interval = setInterval(() => {
message.channel.send(attachment);
}, 20000);
}
});
and whenever you went to stop that interval just call:
clearInterval(my_interval);

How to add setTimeout to this code for 1 minute?

how could i add a 1 minute timeout to this code before it answers?
//cd test
client.on("message", (msg) => {
if(msg.content.toLowerCase().startsWith(`${PREFIX}1cd`)) {
let user = message.mentions.roles.first();
message.channel.send(`1 minute has passed <#${msg.author.id}>`)
}
});
//cd test
Like this:
setTimeout(() => {
// Code goes here
}, 60000)
See setTimeout()
https://www.w3schools.com/jsref/met_win_settimeout.asp
client.on("message", (msg) => {
if(msg.content.toLowerCase().startsWith(`${PREFIX}1cd`)) {
//pass the code that you want to execute later as a callback function
setTimeout(() => {
let user = message.mentions.roles.first();
message.channel.send(`1 minute has passed <#${msg.author.id}>`)
}, 60000); //60s is 60000 ms, and it takes the amount of time as milliseconds
}
});

Discord bot's no spamming feature isn't working

So I have been attempting to make an anti-spam function on a discord bot, but have look over my code and it all seems to work, but it doesn't. I am new to javascript, so I'm not sure whats wrong... Everything else works on my bot, just not this. I am only pasting the part of my code involving the antispam:
const Discord = require('discord.js');
const client = new Discord.Client();
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
function antispam() {
var spam = 0;
}
client.on('ready', () => {
setInterval(antispam(), 5000);
});
client.on('message', msg => {
if (spam > 10) {
client.channels.get('546117125702680596').send('Hey! You are sending messages too quickly!');
}
});
function antispam() {
var spam = 0;
}
client.on('message', msg => {
var spam = spam + 1;
});
client.login('token');
Help would be appreciated!
Hi and welcome to Stack Overfow!
Several issue here:
You're declaring antispam twice, declare functions always once
Your interval doesn't do anything. It calls antispam what creates spam inside the scope of antispam what gets deleted immediately after antispam finishes executing
You're declaring client.on('message'... twice. Again, just do it once
You're declaring `client.on('ready'...) twice.
If you increase spam inside client.on('message'...) that spam variable will be useless just as in antispam. You don't access it anywhere (you also couldn't if you would try to)
So here's a solution that should work:
// To count the "spam level"
const spam = 0;
// Increase spam everytime someone writes something
client.on('message', msg => {
// Check if spam level is already too high
if (spam > 10) {
client.channels.get('546117125702680596').send('Hey! You are sending messages too quickly!');
} else {
spam++;
}
});
// Decrease the spam level, otherwise nobody can't send message until the bot gets restarted
setInterval(() => {
if (spam > 0) {
spam--;
}
}, 10000); // Let's decrease it every 10 seconds
Your whole code:
const Discord = require('discord.js');
const client = new Discord.Client();
// To count the "spam level"
const spam = 0;
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
// Increase spam everytime someone writes something
client.on('message', msg => {
// Check if spam level is already too high
if (spam > 10) {
client.channels.get('546117125702680596').send('Hey! You are sending messages too quickly!');
} else {
spam++;
}
});
// Decrease the spam level, otherwise nobody can't send message until the bot gets restarted
setInterval(() => {
if (spam > 0) {
spam--;
}
}, 10000); // Let's decrease it every 10 seconds
client.login('token');
// To count the "spam level"
const spam = 0;
// Increase spam everytime someone writes something
client.on('message', msg => {
if(msg.author.bot) return
// Check if spam level is already too high
if (spam > 10) {
client.channels.get('546117125702680596').send('Hey! You are sending messages too quickly!');
} else {
spam++;
}
});
// Decrease the spam level, otherwise nobody can't send message until the bot gets restarted
setInterval(() => {
if (spam > 0) {
spam--;
}
}, 10000); // Let's decrease it every 10 seconds
The code provided by CodeF0x is good , but make sure to add:
if(msg.author.bot) return
If the message being sent was by a bot, it will ignore them. IF YOU DO NOT add this to your code, get prepared for your bot to spam. It will respond to itself due to that if statement missing (especially since every time one sends a message, the spam variable will increase). So yeah, happy coding!

How can I unsubscribe or cancel the filtering of a large array that is an RxJS observable?

My understanding is that an entire array is pushed to a subscriber, unlike say an interval observer that can be unsubscribed/cancelled.
For example the following cancellation works...
// emit a value every second for approx 10 seconds
let obs = Rx.Observable.interval(1000)
.take(10)
let sub = obs.subscribe(console.log);
// but cancel after approx 4 seconds
setTimeout(() => {
console.log('cancelling');
sub.unsubscribe()
}, 4000);
<script src="https://unpkg.com/rxjs#5.5.10/bundles/Rx.min.js"></script>
However, replacing the interval with an array doesn't.
// emit a range
let largeArray = [...Array(9999).keys()];
let obs = Rx.Observable.from(largeArray)
let sub = obs.subscribe(console.log);
// but cancel after approx 1ms
setTimeout(() => {
console.log('cancelling');
sub.unsubscribe()
}, 1);
// ... doesn't cancel
<script src="https://unpkg.com/rxjs#5.5.10/bundles/Rx.min.js"></script>
Does each element need to be made asynchronous somehow, for example by wrapping it in setTimeout(..., 0)? Perhaps I've been staring at this problem too long and I'm totally off course in thinking that the processing of an array can be cancelled?
When using from(...) on an array all of the values will be emitted synchronously which doesn't allow any execution time to be granted to the setTimeout that you are using to unsubscribe. Infact, it finishes emitting before the line for the setTimeout is even reached. To allow the emits to not hog the thread you could use the async scheduler (from(..., Rx.Scheduler.async)) which will schedule work using setInterval.
Here are the docs: https://github.com/ReactiveX/rxjs/blob/master/doc/scheduler.md#scheduler-types
Here is a running example. I had to up the timeout to 100 to allow more room to breath. This will slow down your execution of-course. I don't know the reason that you are attempting this. We could probably provide some better advice if you could share the exact use-case.
// emit a range
let largeArray = [...Array(9999).keys()];
let obs = Rx.Observable.from(largeArray, Rx.Scheduler.async);
let sub = obs.subscribe(console.log);
// but cancel after approx 1ms
setTimeout(() => {
console.log('cancelling');
sub.unsubscribe()
}, 100);
// ... doesn't cancel
<script src="https://unpkg.com/rxjs#5.5.10/bundles/Rx.min.js"></script>
I've marked #bygrace's answer correct. Much appreciated! As mentioned in the comment to his answer, I'm posting a custom implementation of an observable that does support such cancellation for interest ...
const observable = stream => {
let timerID;
return {
subscribe: observer => {
timerID = setInterval(() => {
if (stream.length === 0) {
observer.complete();
clearInterval(timerID);
timerID = undefined;
}
else {
observer.next(stream.shift());
}
}, 0);
return {
unsubscribe: () => {
if (timerID) {
clearInterval(timerID);
timerID = undefined;
observer.cancelled();
}
}
}
}
}
}
// will count to 9999 in the console ...
let largeArray = [...Array(9999).keys()];
let obs = observable(largeArray);
let sub = obs.subscribe({
next: a => console.log(a),
cancelled: () => console.log('cancelled')
});
// except I cancel it here
setTimeout(sub.unsubscribe, 200);

Categories

Resources