How to make a clearinterval/stop in discord.js? - discord

I cant get it so if I do !stop it stops the interval and it just really annoys me.
client.on('message', msg => {
if (msg.guild && msg.content.startsWith('!messageall')) {
let text = msg.content.slice('!messageall'.length); // cuts off the /private part
setInterval(function(){
msg.guild.members.forEach(member => {
if (member.id != client.user.id && !member.user.bot) member.send("Message Here");
msg.channel.send(`Sent a message to <#${member.id}> `)
});
console.log("Started.")
}, 60000);
}
if (msg.guild && msg.content.startsWith('!stopall')) {
clearInterval()
}
});
I dont know how it will work

You need to have a reference to setInterval(), I also suggest you use client.setInterval() instead, so what you should do is:
const timer = client.setInterval(function(), 60000);
if (msg.guild && msg.content.startsWith('!stopall')) clearInterval(timer)

Related

Discord.js V.13 collect once with Collector

I'm making a suggest system for my bot which starts of with the user pressing a button in a channel which then prompts them to say what they want to suggest and then their suggestion gets sent to a different channel where others can vote on it. So what I want to make it do is I want it to create a createMessageComponentCollector and then register all the good/bad votes under a a period of 24h, if the suggestion got 10 good votes it's approved, otherwise it's not. Here is my code for it so far but what I'm having issue with is to start the ComponentCollector one time and then make it register the votes for each suggestion. this is the part of my code that I'm having trouble with
client.channels.cache.get("909420357285474334").send({ embeds:[embed], components:[row] })
const filter1 = m => m.customId === "Yes" && i.messageId === interaction.messageId
collector1 = interaction.channel.createMessageComponentCollector({filter: filter1, time: 86400000});
const filter2 = m => m.customId === "No" && i.messageId === interaction.messageId
collector2 = interaction.channel.createMessageComponentCollector({filter: filter2, time: 86400000});
if (interaction.customId === "Yes") {
collector1.on('collect', async i => {
client.logger("collector1 collected")
});
collector1.on('end', collected => {
client.logger(collected.size)
// if (collected.size < 10) {
// }
});
}
if (interaction.customId === "No") {
collector2.on('collect', async i => {
client.logger("collector2 collected")
});
collector2.on('end', collected => {
client.logger(collected.size)
// if (collected.size < 10) {
// }
});
}
your question is a little bit unclear but I think I get what your looking for, if you want to check if a user already has pressed a button you could add them to a Set() constructor, now you need to set a new Set() which you can define in your startup file like this:
client.alreadyPressed = new Set()
and when you've done that one possible way to do it in your suggestion code could be like this:
collector1.on('collect', async i => {
client.logger("collector1 collected")
if (client.alreadyPressed.has(interaction.user.id)) {
i.reply({ content: `You've already voted ${i.user.username}!`, ephemeral: true })
return;
} else {
i.reply({ content: `Thank you for your vote ${i.user.username}!`, ephemeral: true });
}
client.alreadyPressed.add(i.user.id)
});
collector1.on('end', collected => {
client.logger(collected.size)
// if (collected.size < 10) {
// }
});
collector2.on('collect', async i => {
client.logger("collector2 collected")
if (client.alreadyPressed.has(interaction.user.id)) {
i.reply({ content: `You've already voted ${i.user.username}!`, ephemeral: true })
return;
} else {
i.reply({ content: `Thank you for your vote ${i.user.username}!`, ephemeral: true });
}
client.alreadyPressed.add(i.user.id)
});
collector2.on('end', collected => {
client.logger(collected.size)
// if (collected.size < 10) {
// }
});
one problem with this is that they only can vote once in the whole channel which im not sure if that's what you wanted

Discord await messages timing out | Discord V12

I am stuck on a problem. When "Player 2" (player[1]) types !yes in the channel then reason it times out. I'm not sure what I am doing wrong. player[1] is defined as msg.mentions.members.first();
let answer = true;
if (players[1].user.bot) {
return;
} else {
answer = await msg.channel.awaitMessages((msg) => {
console.log(msg.author.id === players[1].id && msg.content === `!yes`) // returns true
if (msg.author.id === players[1].id && msg.content === `!yes`) {
console.log("Player has accepted") // The console does print "Player has accepted"
return true;
}
return false;
}, {maxMatches: 1, time: 30000, errors: ['time']})
.catch(() => {
console.log("Timed out!") // The console does print "Timed Out as well"
return false;
});
}
// if user refuses to play
if (!answer) {
return channel.send(`${players[1]} preferred to run away.`);
}
You have incorrect syntax for awaitMessages() - the first argument should be a CollectorFilter (see here), not a callback.
Consider using createMessageCollector() instead. It reads much more nicely than awaitMessages() and makes more sense than forcing async/await into a collector. Should look something like this:
const filter = m => (m.author.id===players[1].id && m.content==="!yes");
const collector = msg.channel.createMessageCollector(filter, {max: 1, time: 30000});
collector.on("collect", (m) => {
// Player has accepted... do whatever
});
collector.on("end", (reason) => {
if(reason === "time") {
// Ran out of time
}
});

How can I determine the time to send the message

How can I set the duration of the message Example:
if (message.content === 'test') {
message.channel.send (`he say test in 22seconds`)
}
If you're looking for the time it took to the bot to receive the message, use:
if (message.content === 'test') {
const seconds = ((Date.now()-message.createdTimestamp)/1000).toFixed(2);
message.channel.send (`he say test in ${seconds} seconds`)
}
What you are looking for is setTimeout() function.
if (message.content === 'test') {
setTimeout(function(){
message.channel.send (`it took me 22seconds to send this message.`);
}, 22000);
}
Hmm.. the question is not too clear but I'm guessing you mean once the user types a command, the bot says something and then the user can reply with test and the bot tells you how long it took you to type test? (Give the code a try and if its not what you wanted you can take parts out. :) )
The code:
const prefix = ''; //Put whatever prefix you want in the `(prefix goes here)`
var intervals;
bot.on("message", msg => {
let args = msg.content.substring(prefix.length).split(" ");
switch (args[0]) {
case "test": // You can call the command whatever you want
let timer = 3;
msg.channel.send("Get ready").then(msg => {
intervals = setInterval(function() {
msg.edit(`Type test in the chat in **${timer--}**..`);
}, 1000);
});
setTimeout(() => {
clearInterval(intervals);
msg.channel
.send(`Type test in the chat`)
.then(() => {
const time = Date.now();
msg.channel
.awaitMessages(
function(userMsg) {
if (userMsg.content === "test") return true;
},
{
max: 1,
time: 10000,
errors: ["time"]
}
)
.then(function(collected) {
const endTime = Date.now();
let successMsg = "Congratulations!\n";
let collectedArr = Array.from(collected.values());
for (let msg of collectedArr) {
let timeDiff = (endTime - msg.createdTimestamp) / 100;
successMsg += `You took ${timeDiff} seconds to type test.\n`;
}
msg.channel.send(successMsg);
})
.catch(function(collected) {
msg.channel.send(`You did not answer in time!`);
});
})
.catch(function(err) {
console.log(err);
});
}, 5000);
break;
}
});
I'm not too sure what you're asking for but hope this is it! Again, give it a try and see if it works.
Im guessing you need the bot to send that message in 22 seconds. If thats the case then do this
if (message.content === 'test') {
setTimeout(() => { // setTimeout function dalays code inside of it for a set period of time
message.channel.send (`he say test in 22seconds`); // Your code
}, 22000); // The amount of time it should be delayed for. 22000 (milliseconds) = 22 seconds
}

can someone explain the change to bulkDelete (discord.js)

Here is the code I have right now
module.exports ={
name:'purge',
description:'Clears the number of messages you set in a seccond ARG.',
aliases:['clear','nuke'],
execute(msg, args)
{
if(!msg.member.hasPermission("MANAGE_MESSAGES")) {
return msg.reply("You do not have permission to run this command").then(msg => msg.delete(5000));
}
if (!isNaN(args[0]) || parseInt(args[0]) <= 0) {
return msg.reply("That is not a number").then(msg => msg.delete(5000));
}
if(!msg.guild.me.hasPermission("MANAGE_MESSAGES")) {
return msg.reply("Sorry I can't messages please make sure i have the correct permissions").then(msg => msg.delete());
}
let deleteAmount;
if(parseInt(args[0]) > 100) {
deleteAmount = 100;
} else {
deleteAmount = parseInt(args[0]);
}
msg.channel.bulkDelete(deleteAmount, true);
}
}
Error:
(node:25048) UnhandledPromiseRejectionWarning: TypeError [MESSAGE_BULK_DELETE_TYPE]: The messages must be an Array, Collection, or number.
at TextChannel.bulkDelete (C:\StrangeOccBot\node_modules\discord.js\src\structures\interfaces\TextBasedChannel.js:364:11)
at Object.execute (C:\StrangeOccBot\commands\purge.js:27:21)
at Client.<anonymous> (C:\StrangeOccBot\index.js:46:39)
at Client.emit (events.js:315:20)
at WebSocketShard.onPacket (C:\StrangeOccBot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:436:22)
at WebSocketShard.onMessage (C:\StrangeOccBot\node_modules\discord.js\src\client\websocket\WebSocketShard.js:293:10)
at WebSocket.onMessage (C:\StrangeOccBot\node_modules\ws\lib\event-target.js:120:16)
So I'm not sure if an int is still the way to do it with bulkDelete()
but as far as I know, you can fetch messages in a channel and pass those to the method!
msg.channel.messages.fetch({ limit: deleteAmount }).then(messages => {
msg.channel.bulkDelete(messages).then(deleted => {
msg.channel.send(`${deleted.size} messages pruged!`).then(msg => msg.delete(5000));
})
})
This is the way how I have done it for the last few times I created functions like what you try to archive.
Also you can add .catch() methods to the .then() methods so you can check if something went wrong or not!
Edit: I changed your code a little bit especially at the end so you have an idea how I would have done it to archive what you wanna archive
module.exports ={
name:'purge',
description:'Clears the number of messages you set in a seccond ARG.',
aliases:['clear','nuke'],
execute(msg, args) {
if (!msg.member.hasPermission("MANAGE_MESSAGES")) {
return msg.reply("You do not have permission to run this command").then(msg => msg.delete(5000));
}
if (!msg.guild.me.hasPermission("MANAGE_MESSAGES")) {
return msg.reply("Sorry I can't messages please make sure i have the correct permissions").then(msg => msg.delete());
}
if (!isNaN(args[0]) || parseInt(args[0]) <= 0) {
return msg.reply("That is not a number").then(msg => msg.delete(5000));
}
// I changed this slightly to how I would do it!
let deleteAmount = 100;
if (parseInt(args[0]) < 100) {
deleteAmount = parseInt(args[0])
}
// If I'm not mistaken, the bulkDelete() method also works with fetched messages in an variable.
// To archive this, you can use `msg.channel.messages.fetch()` as I will show below!
// Ofcourse I did not use the .catch() method, so if something isn't correctly done it can cause issues!
msg.channel.messages.fetch({ limit: deleteAmount }).then(messages => {
msg.channel.bulkDelete(messages).then(deleted => {
msg.reply(`${deleted.size} messages pruged!`).then(msg => msg.delete(5000));
})
})
}
}

Unsubscribe from timer in rxjs

Hi I have a timer running which is like it should show a component for 30sec after every 10 seconds. My code is like this`
import { timer } from "rxjs";
componentWillReceiveProps(nextProps, nextState) {
console.log("RECEIVED PROPS");
if (this.props.venuesBonusOfferDuration === 0) {
this.subscribe.unsubscribe();
}
this.firstTimerSubscription;
this.secondTimerSubscription;
// if (this.state.isMounted) {
if (
nextProps.showBonusObj &&
(!nextProps.exitVenue.exitVenueSuccess || nextProps.enterVenues)
) {
// console.log("isMounted" + this.state.isMounted);
//if (this.state.isMounted) {
let milliseconds = nextProps.venuesBonusOfferDuration * 1000;
this.source = timer(milliseconds);
this.firstTimerSubscription = this.source.subscribe(val => {
console.log("hiding bonus offer");
this.firstTimerSubscription.unsubscribe();
this.props.hideBonusOffer();
this.secondTimerSubscription = bonusApiTimer.subscribe(val => {
console.log("caling timer" + val);
this.props.getVenuesBonusOffer(
this.props.venues.venues.id,
this.props.uid,
this.props.accessToken
);
});
});
//}
} else {
try {
if (this.secondTimerSubscription != undefined) {
this.secondTimerSubscription.unsubscribe();
console.log("secondTimer UNSUBSCRIBED");
}
if (this.firstTimerSubscription != undefined) {
this.firstTimerSubscription.unsubscribe();
console.log("firstTimer UNSUBSCRIBED");
}
} catch (error) {
console.log(
"error when removing bonusoffer timer" + JSON.stringify(error)
);
}
//}
}
}
`
Problem is if I try to unsubscribe this * this.firstTimerSubscription* and this.secondTimerSubscription like this
try {
if (this.secondTimerSubscription != undefined) {
this.secondTimerSubscription.unsubscribe();
console.log("secondTimerunmount UNSUBSCRIBED");
}
if (this.firstTimerSubscription != undefined) {
this.firstTimerSubscription.unsubscribe();
console.log("firstTimerunmount UNSUBSCRIBED");
}
} catch (error) {
console.log("error bonusoffer timer" + JSON.stringify(error));
}
its still prints logs within timer like "hiding bonus offer" and "calling timer".
Can someone please point out the issue. It been a day since am into this.
Any help is appreciated.
The problem is that you subscribe multiple times (whenever component receives props) and reassign newest subscription to firstTimerSubscription or secondTimerSubscription references. But doing that, subscriptions does not magically vanish. To see how it works here is a demo:
const source = timer(1000, 1000);
let subscribe;
subscribe = source.subscribe(val => console.log(val));
subscribe = source.subscribe(val => console.log(val));
setTimeout(() => {
subscribe.unsubscribe();
}, 2000)
Even though you unsubscribed, the first subscription keeps emiting. And the problem is that you lost a reference to it, so you can't unsubscribe now.
Easy fix could be to check whether you already subscribed and unsubscribe if so, before subscribing:
this.firstTimerSubscription ? this.firstTimerSubscription.unsubscribe: false;
this.firstTimerSubscription = this.source.subscribe(...
I wouldn't use a second timer. Just do a interval of 10 seconds. The interval emits the iteration number 1, 2, 3..... You can use the modulo operator on that tick. Following example code (for example with 1 second interval) prints true and false in console. After true it needs 3 seconds to show false. After false it needs 1 second to show true.
interval(1000).pipe(
map(tick => tick % 4 !== 0),
distinctUntilChanged(),
).subscribe(x => console.log(x));

Resources