hermitP
hermitP

Reputation: 23

How to get discord.js bot to reply to a series of DM messages only after user response?

I am trying to get a bot to read and reply a series of replies from a user in a DM channel. In my setup, the process of workflow would be (message author on left):

user: "bot post"
bot: "Please upload an image if necessary"
user: *uploads image*
bot: "Now please set a date in dd/mm/yyyy format"
user: "09/23/1952"
bot: "Now please set some contact info"
user: ...

Right now I have an awaitMessages to collect user responses to each question. The intended function is that the bot will store the responses and create an embedded post with all the info on the main server. But right now, each question is asked at the exact same time, instead of after waiting for the user to reply. Here is a snippet of my current code:

client.on("message", msg => {
    var words = msg.content.split(' ').map(x => x.toLowerCase());
    if (msg.author.bot || msg.guild !== null || words[1] !== 'post') return;
    const filter = m => m.author.id === msg.author.id;

    img = "" \\ store the image url inputted
    date = "" \\ store the date as a string

    \\ bot asks for image
    msg.author.send("First, upload an image if you have one. If not, just reply `skip`.") 
        .then(() => {
            msg.channel.awaitMessages(filter, {
                max: 1,
                time: 300000
            })
                .then((collected) => {
                    console.log(collected.first().content)
                    if (collected.first().attachments.size === 1) {
                        img = collected.first().attachments.first().url;
                        msg.author.send("Image successfully uploaded.");
                    } else {
                        msg.author.send("No image uploaded.");
                    }
                })
                .catch(() => {
                    msg.author.send("No image uploaded. Your time limit ran out");
                });
        })

    \\ bot asks for date input
    msg.author.send("Next, please input a start/due date in `dd/mm/yyyy`.") 
        .then(() => {
            msg.channel.awaitMessages(filter, {
                max: 1,
                time: 30000,
                errors: ['time'],
            })
                .then((collected) => {
                    date = collected.first().content
                    msg.author.send("Date has been entered.")
                })
                .catch(() => {
                    msg.author.send("No date was entered. Your time limit ran out");
                });
        });

})

Running the bot and messaging bot post in a DM channel to the bot results in this:

bot: First upload an image if you have one. If not just reply skip.
bot: Next, please input a start date/due date in dd/mm/yyyy form.

This causes the next message written to be the ones collected in both awaitMessages, i.e. a reply skip will tell the first portion that there is no image AND tell the second portion that the date inputted in is skip simultaneously.

Is there any way to get the bot to only perform a function only after the user has responded to the previous one? I've tried using a setTimeout() to delay each portion but that's not an ideal functionality. I want the bot to reply as soon as it reads the user's input.

How do I solve the problem?

Upvotes: 2

Views: 2963

Answers (1)

Mohammad Dohadwala
Mohammad Dohadwala

Reputation: 746

You need to move your second send function inside the then() of the first. Kind of like this:

client.on("message", msg => {
    var words = msg.content.split(" ").map(x => x.toLowerCase());
    if (msg.author.bot || msg.guild !== null || words[1] !== "post") return;
    const filter = m => m.author.id === msg.author.id;

    img = ""; // store the image url inputted
    date = ""; // store the date as a string

    // bot asks for image
    msg.author
      .send("First, upload an image if you have one. If not, just reply `skip`.")
      .then(() => {
        msg.channel
          .awaitMessages(filter, {
            max: 1,
            time: 300000
          })
          .then(collected => {
            console.log(collected.first().content);
            if (collected.first().attachments.size === 1) {
              img = collected.first().attachments.first().url;
              msg.author.send("Image successfully uploaded.");

              // bot asks for date input
              msg.author
                .send("Next, please input a start/due date in `dd/mm/yyyy`.")
                .then(() => {
                  msg.channel
                    .awaitMessages(filter, {
                      max: 1,
                      time: 30000,
                      errors: ["time"]
                    })
                    .then(collected => {
                      date = collected.first().content;
                      msg.author.send("Date has been entered.");
                    })
                    .catch(() => {
                      msg.author.send(
                        "No date was entered. Your time limit ran out"
                      );
                    });
                });
            } else {
              msg.author.send("No image uploaded.");
            }
          })
          .catch(() => {
            msg.author.send("No image uploaded. Your time limit ran out");
          });
      });
  });

And yes, that looks awful. You could look into async/await to make your code easier to read and have fewer indentations.

Upvotes: 1

Related Questions