I have a guildMemberAdd event which whenever a user joins a server, it runs this code:
const msg = await member.send('hi')
const filter = message => message.content === "e"
msg.channel.awaitMessages({ filter, max: 1, time: 10000, errors: ['time'] }).then(c => {
console.log("pog")
}).catch(e => console.log("Failed!"));
Although, whenever I reply to the bot with "e", it does absolutely nothing, and after the 10 seconds have passed, it logs "Failed!" in the console.
What am I doing wrong here? There are no error outputs in the console either from execution of the code above.
Related
I am very new to Discord.js so please forgive me for any basic errors.
I am trying to create a command that will ask for a name, and then store the users input into a variable, however this is proving itself quite difficult.
After the program sends the message "What would you like to name your event?", I type "TEST", and then it sends another message saying "createevent", the command word.
client.on('message', async message => {
if (message.author.bot) return;
if (message.content.startsWith('createevent')) {
const filter = m => m.author.id === message.author.id;
message.channel.startTyping()
await sleep(500);
message.channel.stopTyping()
message.lineReply('What would you like to name your event?')
message.channel.awaitMessages(filter, {max: 1, time: 50000}).then(collected => {
const eventname = message.content;
message.channel.send(eventname);
})
}
});
First of all, you should stop the collector and, as you said you want to know the content that the user replies, the content in your case would be collected.content not message.content.
I have figured out how to do make a bot react with its message from the following code:
if(message.content === "!start"){
message.channel.send(serve).then(message => {
message.react('764193096060764211');
})
}
(serve is an embed stored in a variable)
I want the user to react with it and the bot to do something with that information, for an example, storing the value 1 to a variable called startingServe. If the user doesn't react within 5 seconds, I want the bot to message "Gamer Ended". How do I do this? Looking forward for the help from this community! If there's anything else needed from me to answer this question, it is fine to ask.
Use something like this:
var startingServe = 0
message.awaitReactions(filter, { max: 1, time: 5000, errors: ['time'] })
.then(collected => {
const reaction = collected.first();
if (reaction.emoji.id == "764193096060764211") {
startingServe = 1
} else {
message.channel.send('Gamer Ended')
}
})
.catch(collected => {
message.channel.send('Gamer Ended');
});
Source and more info on this guide page.
So i started to make a discord bot using discord.js which has a command for tic tac toe.
I tried using a message collector, like this in a while loop. After it enters the loop nothing happens. I added a console.log to see if the totalRouds variable is modifying and it was, so the loop somehow passed over the message collector code and executed just the last line.
while(numberOfrounds < 9){
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
message.channel.awaitMessages(filter, {max: 1, time: 3000, errors: ['time']}).then(collected => {
// code for drawing a canvas
}).catch(err => {
console.log(err);
});
console.log(totalRouds);
numberOfrounds ++;
}
.awaitMessages() returns a Promise that resolves into your collected message data asynchronously. That means that while your last log statement runs immediately after you start collecting messages, the collected messages are only available and thus processed at a later time.
To illustrate that, let me tidy your code a little and add some logs in the order that your code would normally run:
while (numberOfrounds < 9) {
console.log("1");
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
console.log("2");
message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
console.log("5, after resolving, the collected data is only now avaiable");
}).catch(err => {
console.log(err);
});
console.log("3");
console.log(totalRouds);
numberOfrounds++;
console.log("4, immediately starts the next loop, back to #1 again");
}
I presume that your totalRouds variable is defined within the callback function passed into .then(). So other than the typo (let's fix that), your variable would be defined in the wrong scope and thus totalRounds would always remain undefined, even after the Promise resolves with your collected messages, you process those messages, you set totalRounds within the callback function etc. So here is our updated snippet:
while (numberOfrounds < 9) {
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
let totalRounds = 1 // Do your processing here
console.log(totalRounds); // This should log as expected
}).catch(err => {
console.log(err);
});
numberOfrounds++;
}
But this is still probably not the behaviour you are looking for. Why? Your bot will attempt to send all 9 replies (assuming your numberOfRounds starts at 0 earlier) at once, at which point Discord.js will automatically send them in batches to avoid spamming the API, and all message collectors would be waiting concurrently. You probably intend to "pause" or suspend processing until the Promise returned by .awaitMessages() resolves and you have finished processing the returned data, causing synchronous behaviour whilst using an asynchronous method call (therefore you say "the loop somehow passed over the message collector code and executed just the last line"). To do this, we can use async-await:
/*
You have not provided your full code,
so what you need to do is mark your message event's
callback function as async.
Refer to the linked article on MDN.
*/
while (numberOfrounds < 9) {
const filter = m => m.author.id === message.author.id;
message.reply('Enter a position:');
/*
Then, wait for the Promise returned by
this promise chain to resolve
before resuming operation
and moving on to the next iteration.
*/
await message.channel.awaitMessages(
filter,
{ max: 1, time: 3000, errors: ['time'] }
).then(collected => {
let totalRounds = 1
console.log(totalRounds);
}).catch(err => {
console.log(err);
});
numberOfrounds++;
}
My terminology may not be 100% correct, but this is my understanding. Feel free to comment if improvements can be made.
First post on this site so my bad if I don't format something correctly. I've been trying to make a change prefix command and I don't know how to check next message content for a variable to use instead of the old prefix.
msg.reply("Which prefix do you want?");
const collector = new Discord.MessageCollector(msg.channel, m => m.author.id === msg.author.id, { time: 5000 });
console.log(collector)
collector.on('collect', msg => {
newprefix=collector.content();
msg.reply('Prefix succesfully changed!');
});
I strongly advise using the awaitMessages method. First you need to define a filter, a delegate function that returns true if the reaction is one you want. Typically in a command/response setting, you want a filter that indicates the original command invoker replied.
const filter = (reaction, user) => {
return user.id === msg.author.id;
};
You can then define options for your awaitMessages. (It's quite common to do this in-line with the awaitMessages method, that's fine if that is more clear to you)
const options = {
max: 1,
time: 30000,
errors: ['time']
}
The above example accepts 1 message, if given in 30 seconds, otherwise it throws an exception.
Finally, you are ready to begin...
msg.reply("Which prefix do you want?").then(() => {
msg.channel.awaitMessages(filter, options)
.then(collected => {
newprefix = collected.first();
// Record newprefix to a persistent config here
msg.reply('Prefix successfully changed!');
})
.catch(collected => {
msg.reply("You didn't respond fast enough.");
});
}
Keep in mind, this occurs asynchronously, so if you need to write newprefix somewhere, a JSON config file for example, you should do from within the scope of the .then
I have a !trivia command which has 4 functions and inside the functions I have a .then() function and .setTimeout(). The problem is that once someone triggers the command, it will only stop once someone say '!stop'. How can I make it so it stops if no one typed in that channel within 5 minutes?
Use .awaitMessages()
let userUsingTheCommand = "<USER_ID>";
let filter = msg => msg.author.id = userUsingTheCommand;
// Errors: ['time'] treats ending because of the time limit as an error
function wait() {
channel.awaitMessages(filter, {
max: 1,
time: 60000 * 5,
errors: ['time']
})
.then(wait)
.catch(() => {
console.log("Time to stop!");
});
}