Discord await messages timing out | Discord V12 - discord.js

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
}
});

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

SlowMode for one person is possible ? discord.js

I would like to know if it is possible to do some sort of "SlowMode" for a specific person on Discord.
The reason is that I have a "spammer" friend, and I would like to calm him down with a command that might slow him down when he speaks for "x" secondes.
So I would like to know if this is possible? and if yes, how?
Thank you for your kindness =) (and sorry for this english i use GoogleTraductor)
Here's how I'd do that.
let ratelimits = [];
client.on("message", (msg) => {
// APPLYING RATELIMITS
const appliedRatelimit = ratelimits.find(
(value) =>
value.user === msg.author.id && value.channel === msg.channel.id
);
if (appliedRatelimit) {
// Can they post the message?
const canPostMessage =
msg.createdAt.getTime() - appliedRatelimit.ratelimit >=
appliedRatelimit.lastMessage;
// They can
if (canPostMessage)
return (ratelimits[
ratelimits.indexOf(appliedRatelimit)
].lastMessage = msg.createdAt.getTime());
// They can't
msg.delete({ reason: "Enforcing ratelimit." });
}
// SET RATELIMIT
if (msg.content === "!ratelimit") {
// Checking it's you
if (msg.author.id !== "your id") return msg.reply("You can't do that.");
// You can change these values in function of the received message
const targetedUserId = "whatever id you want";
const targetedChannelId = msg.channel.id;
const msRateLimit = 2000; // 2 seconds
// Delete existant ratelimit if any for this user on this channel
ratelimits = ratelimits.filter(
(value) =>
!(
value.user === targetedUserId &&
value.channel === targetedChannelId
)
);
// Add ratelimit
ratelimits.push({
user: targetedUserId,
channel: targetedChannelId,
ratelimit: msRateLimit,
lastMessage: 0,
});
}
// CLEAR RATELIMITS
if (msg.content === "!clearRatelimits") {
// Checking it's you
if (msg.author.id !== "your id") return msg.reply("You can't do that.");
// Clearing all ratelimits
ratelimits = [];
}
});

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
}

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

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)

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