Reputation: 73
I am trying to get discord.js to read DM messages on Discord to have a bot that will be a server/faction application bot made from scratch but I Have it to send the first part when you type %apply to the bot the problem comes when trying to get passed question 2 it keeps getting question 2 instead of going to question 3
I am trying to filter out the DM messages when they are not the same as the passed ones so I have several if commands
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
if (message.content === "%apply") {
apply = "TRUE";
a0 = message.author.lastMessageID
message.author.sendMessage("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.sendMessage("```Application Started - Type '#Cancel' to cancel the application```");
message.author.sendMessage("```Question 1: In-Game Name?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a0) && (message.content != "%apply") && (apply === "TRUE")) {
a1 = message.author.lastMessageID;
message.author.sendMessage("```Question 2: Age?```");
}
if ((message.guild === null) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a2 = message.author.lastMessageID;
message.author.sendMessage("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
}
if ((message.guild === null) && (message.author.lastMessageID != a2) && (message.author.lastMessageID != a1) && (message.author.lastMessageID != a0) && (apply === "TRUE")) {
a3 = message.author.lastMessageID;
message.author.sendMessage("```Question 4: Do you have schematica?```");
}
I expected it to go from question 1 to question 2 the question 3
Upvotes: 0
Views: 11064
Reputation: 5623
Although @Gruntzy's answer is not wrong, there's another solution that's built into Discord.js and meant for these situations - TextChannel.awaitMessages()
. You can use it in a system like shown below.
const questions = [ // ------------------------------------
"What's your IGN?", //
"How old are you?", // Define the questions you'd like the
"What time zone do you reside in?", // application to have in this array.
"Do you have Schematica?" //
]; // ------------------------------------
const applying = [];
bot.on("message", async message => {
if (message.author.bot) return;
if (message.content.toLowerCase() === "%apply") {
if (applying.includes(message.author.id)) return;
try {
console.log(`${message.author.tag} began applying.`);
applying.push(message.author.id);
await message.channel.send(":pencil: **Application started!** Type `#cancel` to exit.");
for (let i = 0, cancel = false; i < questions.length && cancel === false; i++) {
await message.channel.send(questions[i]);
await message.channel.awaitMessages(m => m.author.id === message.author.id, { max: 1, time: 300000, errors: ["time"] })
.then(collected => {
if (collected.first().content.toLowerCase() === "#cancel") {
await message.channel.send(":x: **Application cancelled.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} cancelled their application.`);
}
}).catch(() => {
await message.channel.send(":hourglass: **Application timed out.**");
applying.splice(applying.indexOf(message.author.id), 1);
cancel = true;
console.log(`${message.author.tag} let their application time out.`);
});
}
await message.channel.send(":thumbsup: **You're all done!**");
console.log(`${message.author.tag} finished applying.`);
} catch(err) {
console.error(err);
}
}
});
To make the code easier to understand, let's go through it step by step...
1. Preceding lines.
questions
array contains all the questions you'd like to be asked in the application. I've implemented an array for the sake of efficiency; a question can be added or removed by changing only one line, and the same code won't be copied and pasted over and over again.applying
array will help us keep track of the users in the application process.2. Message event.
await
inside of it.try...catch
statement. This allows us to catch any unhandled promise rejections (i.e. if TextChannel.send()
throws an error) easily.3. %apply
command.
applying
array.await
: it waits for the promise to be fulfilled before moving on.for
loop to iterate through the questions
array.
let i = 0, cancel = false
declares i
(the "counter" variable) and a cancel
variable so we can stop the loop if the user wants to cancel the application or if it times out. We can't use break
within our then()
callback, so I've reverted to this method.i < questions.length && cancel === false
are our conditions to match before continuing with the next iteration - the counter must be within the range of the array, and cancel
must still be false
.i++
increments the counter by 1.TextChannel.awaitMessages()
. Our first parameter is a filter that the message must pass through, and the second is the options.
then()
callback, we check if the message was #cancel
. If so, we send the cancellation message, remove the user from the array, and set cancel
's value to true
.catch()
method would be called if no message was provided in 5 minutes. So in our callback, we send the time out message, remove the user from the array, and set cancel
's value to true
.Upvotes: 4
Reputation: 443
Your variables a0, ... , a3
are inside the "onMessage"
scope, and are undefined everytime in your callback. So if you message is not %apply
, you are stuck into the "Question 2" step
You should keep track of your users registration steps in a global variable, and read it to know what step you are into. Here is a short example of how to do this. Note that this is a really basic approach, and it might be better to use some in-memory database if you need to add more complex features to your apply procedure. It also requires more controls, and I guess some other data storage to keep track of the user answers.
let userApplications = {}
bot.on("message", function(message) {
if (message.author.equals(bot.user)) return;
let authorId = message.author.id;
if (message.content === "%apply") {
console.log(`Apply begin for authorId ${authorId}`);
// User is not already in a registration process
if (!(authorId in userApplications)) {
userApplications[authorId] = { "step" : 1}
message.author.send("```We need to ask some questions so we can know a litte bit about yourself```");
message.author.send("```Application Started - Type '#Cancel' to cancel the application```");
message.author.send("```Question 1: In-Game Name?```");
}
} else {
if (message.channel.type === "dm" && authorId in userApplications) {
let authorApplication = userApplications[authorId];
if (authorApplication.step == 1 ) {
message.author.send("```Question 2: Age?```");
authorApplication.step ++;
}
else if (authorApplication.step == 2) {
message.author.send("```Question 3: Timezone? NA, AU, EU, NZ, or Other? (If other, describe your timezone)```");
authorApplication.step ++;
}
else if (authorApplication.step == 3) {
message.author.send("```Question 4: Do you have schematica?```");
authorApplication.step ++;
}
else if (authorApplication.step == 4) {
message.author.send("```Thanks for your registration. Type %apply to register again```");
delete userApplications[authorId];
}
}
}
});
some other quick notes :
sendMessage(msg)
is deprecated in the discord.js api, send(msg)
should be used nowmessage.channel.type
rather than looking for a empty message.guildId
Upvotes: 0