JDA - How to wait for next message

2.5k Views Asked by At

Im making a discord bot with JDA and I want to know how to wait for a message. Something like this

import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

public class Listener extends ListenerAdapter {
    public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
        String message = event.getMessage().getContentRaw();
        boolean isBot = event.getAuthor().isBot();

        // Check if message is not from a bot
        if (!isBot) {
            if (message.equalsIgnoreCase("hi")) {
                event.getChannel().sendMessage("Hello, what's your name?").queue();
                // Wait for second message
                String name = event.getMessage().getContentRaw(); // Saving content from second message
                event.getChannel().sendMessage("Your name is: " + name).queue();
            }
        }
    }
}

User: Hi

Bot: Hello, what's your name?

User: sends name

Bot: Your name is: name

How do i get the second message?

1

There are 1 best solutions below

0
On

As already told by Minn in the comment. You could use that method given in the thread. However, I'd recommend using the JDA-Utilities EventWaiter.

If you're using Maven or Gradle, use either one of these:

<!--- Place this in your repositories block --->
  <repository>
    <id>central</id>
    <name>bintray</name>
    <url>http://jcenter.bintray.com</url>
  </repository>
<!--- Place this in your dependencies block --->
  <dependency>
    <groupId>com.jagrosh</groupId>
    <artifactId>jda-utilities</artifactId>
    <version>JDA-UTILITIES-VERSION</version>  <!--- This will be the latest JDA-Utilities version. Currently: 3.0.4 --->
    <scope>compile</scope>
    <type>pom</type>
  </dependency>
  <dependency>
    <groupId>net.dv8tion</groupId>
    <artifactId>JDA</artifactId> <!--- This will be your JDA Version --->
    <version>JDA-VERSION</version>
  </dependency>

For gradle it's much easier:


# Add this to the dependencies (What's inside this block, not the block itself.

dependencies {
    compile 'com.jagrosh:jda-utilities:JDA-UTILITIES-VERSION'
    compile 'net.dv8tion:JDA:JDA-VERSION'
}

# Same story for the repo's
repositories {
    jcenter()
}

When this has loaded in, I'd recommend checking the ExampleBot main class. for adding your own stuff to it. Since I will only explain the basics of getting the EventWaiter to work.

This will be the main class of the bot to start with, when you run this, it will start the bot with these commands. ShutdownCommand and PingCommand are a part of the Utilities. So these will be added automaticly.

public static void main(String[] args) throws IOException, LoginException, IllegalArgumentException, RateLimitedException
    {
        // the first is the bot token
        String token = "The token of your bot"
        // the second is the bot's owner's id
        String ownerId = "The ID of your user account"
        // define an eventwaiter, dont forget to add this to the JDABuilder!
        EventWaiter waiter = new EventWaiter();
        // define a command client
        CommandClientBuilder client = new CommandClientBuilder();
        // sets the owner of the bot
        client.setOwnerId(ownerId);
        // sets the bot prefix
        client.setPrefix("!!");
        // adds commands
        client.addCommands(
                // command to say hello
                new HelloCommand(waiter),
                // command to check bot latency
                new PingCommand(),
                // command to shut off the bot
                new ShutdownCommand());

        // start getting a bot account set up
        new JDABuilder(AccountType.BOT)
                // set the token
                .setToken(token)
                // set the game for when the bot is loading
                .setStatus(OnlineStatus.DO_NOT_DISTURB)
                .setActivity(Activity.playing("loading..."))
                // add the listeners
                .addEventListeners(waiter, client.build())
                // start it up!
                .build();
    }

Now, for the HelloCommand. You start by making a new class called "HelloCommand". In this class you will extend the "Command" portion of the utilities.

public class HelloCommand extends Command
{
    private final EventWaiter waiter; // This variable is used to define the waiter, and call it from anywhere in this class.

    public HelloCommand(EventWaiter waiter)
    {
        this.waiter = waiter; // Define the waiter
        this.name = "hello"; // The command
        this.aliases = new String[]{"hi"}; // Any aliases about the command 
        this.help = "says hello and waits for a response"; // Description of the command
    }
    
    @Override
    protected void execute(CommandEvent event)
    {
        // ask what the user's name is
        event.reply("Hello. What is your name?"); // Respond to the command with a message.
        
        // wait for a response
        waiter.waitForEvent(MessageReceivedEvent.class, 
                // make sure it's by the same user, and in the same channel, and for safety, a different message
                e -> e.getAuthor().equals(event.getAuthor()) 
                        && e.getChannel().equals(event.getChannel()) 
                        && !e.getMessage().equals(event.getMessage()), 
                // respond, inserting the name they listed into the response
                e -> event.reply("Hello, `"+e.getMessage().getContentRaw()+"`! I'm `"+e.getJDA().getSelfUser().getName()+"`!"),
                // if the user takes more than a minute, time out
                1, TimeUnit.MINUTES, () -> event.reply("Sorry, you took too long."));
    }
    
}

Now, this is where we get to the jucy stuff. When using the event waiter. There are a few area's you need to check for.

        // wait for a response
        waiter.waitForEvent(MessageReceivedEvent.class, 
                // make sure it's by the same user, and in the same channel, and for safety, a different message
                e -> e.getAuthor().equals(event.getAuthor()) 
                        && e.getChannel().equals(event.getChannel()) 
                        && !e.getMessage().equals(event.getMessage()), 
                // respond, inserting the name they listed into the response
                e -> event.reply("Hello, `"+e.getMessage().getContentRaw()+"`! I'm `"+e.getJDA().getSelfUser().getName()+"`!"),
                // if the user takes more than a minute, time out
                1, TimeUnit.MINUTES, () -> event.reply("Sorry, you took too long."));

Explained in more detail:

        waiter.waitForEvent(GuildMessageReceivedEvent.class, // What event do you want to wait for?
            p -> p.getAuthor().equals(message.getAuthor()) && p.getChannel().equals(message.getChannel()), // This is important to get correct, check if the user is the same as the one who executed the command. Otherwise you'll get a user who isn't the one who executed it and the waiter responds to it.
            run -> {
            // Run whatever stuff you want here.
        }, 1, // How long should it wait for an X amount of Y?
            TimeUnit.MINUTES, // Y == TimeUnit.<TIME> (Depending on the use case, a different time may be needed)
            () -> message.getChannel().sendMessage("You took longer then a minute to respond. So I've reverted this message.").queue()); // If the user never responds. Do this.

This should be the BASICS to using the EventWaiter. This may depend on your use case. And it can be done by only using the eventwaiter class as well.