Skip to content
Advertisement

How do I use callbacks to order the chain of events in a command?

I am making a setup command, using the #awaitMessages listener 2 times in a row to set up a server correctly from a user input, but try as I might, I cannot achieve the effect of each message being sent, then collecting data, then sending the next message etc. Here is my code (I have removed lots of clutter you dont need)

message.channel.send("Please enter the role ID of admin:").then(() => {

    const filter = m => m.content  

    message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] })
        .then(collected => {
            message.channel.send(':white_check_mark: Admin role set up correctly')      
        }).catch(collected => {
                message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
        })
    });
    message.delete().then(async () => {
      await message.channel.send("Please enter the role ID of moderator:").then(() => {

        const filter = m => m.content  
    
        message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] })
            .then(collected => {
                message.channel.send(':white_check_mark: Mod role set up correctly')      
            }).catch(collected => {
                    message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
            })
        });
    })

What happens is the bot does not wait for my collect event, and just moves on to sending the next message e.g.

Please enter the role ID of administrator

Please enter the role ID of moderator

What am I doing wrong? – there is no error thrown (since I have not made a mistake in my code – it just does not do what I need)

Edit:

message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] })
          .then(collected => {
            if (!collected.content === "test") return;
              message.channel.send(':white_check_mark: Admin role set up correctly')      
          }).catch(collected => {
                  message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
          })
          message.channel.send("Please enter the role ID of moderator:").then(() => {
  
            const filter = m => m.content  
        
            message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] })
                .then(collected => {
                  if (!collected.content === "test") return;
                    message.channel.send(':white_check_mark: Mod role set up correctly')      
                }).catch(collected => {
                        message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
                })
            });
      });
      message.delete()

Advertisement

Answer

First off, I would avoid mixing await and using a promise (.then()) on the same thing.

Also your filters aren’t really serving much purpose as you just use an arrow function without doing anything with the result. You could fix this by limiting the filter so that only a specific user can trigger the #awaitMessages events by using the follow filter instead:

const filter = (reaction, user) => {
    return user.id === message.author.id;
};

You also now only need to define this once, as it will be in the scope for the rest of the code now too

To fix the problem you’re having, you can simply just chain everything together using .then(), whilst it might not be pretty, it works.

message.channel.send("Please enter the role ID of admin:").then(() => {
    const filter = (reaction, user) => {
        return user.id === message.author.id;
    };

    message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] }).then(collected => {
        if (!collected.content === "test") return;
        message.channel.send(':white_check_mark: Admin role set up correctly').then(() => {
            message.channel.send("Please enter the role ID of moderator:").then(() => { 
                message.channel.awaitMessages(filter, { max: 1, time: 10000, errors: ['time'] }).then(collected => {
                    if (!collected.content === "test") return;
                
                    message.channel.send(':white_check_mark: Mod role set up correctly');
     
                }).catch(collected => {
                    message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
                });
            });
        });      
    }).catch(collected => {
        message.channel.send(`:x: Setup cancelled - 0 messages were collected in the time limit, please try again`).then(m => m.delete({ timeout: 4000 }));
    });
});

Note: I changed your filter to make sure the same user is always entering the commands.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement