How to make a Discord Bot wait for a specific user to send a message with JDA?

浪子不回头ぞ 提交于 2021-02-02 09:30:12

问题


I'm currently taking an intro to programming class in Java, and have recently started experimenting with the JDA tools to make a basic Discord bot for my server. Ideally, I want my bot to respond when someone says "Hello Apples!" by asking them for their name, then responding with "Hi !" if this message was sent by the same person who said "Hello Apples!" Right now my bot fails to await any user input past the initial "Hello Apples!" message, and spills out all of its text at once. I believe my current code is set up properly to ensure that the bot will only respond with "Hi !" if it receives a message from the same person who originally sent "Hi Apples!", but I can't be completely sure because it doesn't wait for an additional message, and as a result reads from the same message twice and prints out:
Hi! Tell me your name, or say "Stop"!
Hi Hi Apples!!
Wait your turn

I would really like to know how to create a "stop" of some sort, or a method that would cause the bot to wait for addition user input from the user who originally greeted the bot, and if possible, a way to set a time limit so the bot doesn't remain inoperable if they don't reply.

import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;

public class Main {
  public static void main(String[] args) throws Exception {
    try {
      JDA api = new     JDABuilder(AccountType.BOT).setToken("NTQxMTMxMDc4MTY1ODU2MjYw.DzbGoQ.oFIM_py    pLMOc60qU1PgeeUXU8Qo").build();
      api.addEventListener(new MyEventListener());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

import net.dv8tion.jda.core.entities.Member;
import net.dv8tion.jda.core.entities.Message;
import net.dv8tion.jda.core.entities.MessageChannel;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.entities.User;
import net.dv8tion.jda.core.entities.*;
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;

public class MyEventListener extends ListenerAdapter {
  public void onMessageReceived(MessageReceivedEvent event) {
    if (event.getAuthor().isBot()) return;

    Message message = event.getMessage();
    String content = message.getContentRaw();
    MessageChannel channel = event.getChannel();

    if (content.startsWith("Hi Apples!")) {
      Member member = message.getMember();
      channel.sendMessage("Hi! Tell me your name, or say \"Stop\"!").queue();
      int n = 0;    
      while (n == 0) {
        Message message2 = event.getMessage(); 
        String content2 = message.getContentRaw();
        Member member2 = message2.getMember();
        String nick = member2.getNickname();
        if (member == member2) {
          channel.sendMessage("Hi " + content2 + "!").queue();
          n = 1;
        }
        else {
        }
          channel.sendMessage("Wait your turn " + nick + "!").queue();
        if (content2 == "Stop") {
          channel.sendMessage("Understood!").queue();
          n = 1;
        }
      }   
    }        
  }
}

My expected results are:
USER: Hi Apples!
BOT: Hi! Tell me your name, or say stop!
USER2: Hi!
BOT: Wait your turn USER2!
USER: Jimmy
BOT: Hi Jimmy!

Actual results: (Sent all at once)
Hi! Tell me your name, or say "Stop"!
Hi Hi Apples!!
Wait your turn (my discord nickname)!


回答1:


Since you are using an event-based framework you could implement this behavior with the use of a state-machine. Whenever you get your initial trigger, in this case "Hi Apple!" you would initiate a new state-machine for that text channel.

In this state-machine you handle message events until your termination signal arrives, in this case "Stop!".

The state-machine would be implemented using a switch-case in the event method together with a private state field. In this case you only have one interaction in the entire conversation so there is only one state which makes this pointless.

But for example in the case of having a conversation which is what I assume this will be later on you would need to go with the state-machine concept.

public class AppleStateMachine extends ListenerAdapter {
    private final long channelId, authorId; // id because keeping the entity would risk cache to become outdated

    public AppleStateMachine(MessageChannel channel, User author) {
        this.channelId = channel.getIdLong();
        this.authorId = author.getIdLong();
    }

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        if (event.getAuthor().isBot()) return; // don't respond to other bots
        if (event.getChannel().getIdLong() != channelId) return; // ignore other channels
        MessageChannel channel = event.getChannel();
        String content = event.getMessage().getContentRaw();
        // since only one state is present you don't need a switch but that would be the concept if you had more than 1 interaction point in this protocol
        if (content.equals("Stop")) {
            channel.sendMessage("Understood!").queue();
            event.getJDA().removeEventListener(this); // stop listening
        }
        else if (event.getAuthor().getIdLong() == authorId) {
            channel.sendMessage("Hi " + content + "!").queue();
            event.getJDA().removeEventListener(this); // stop listening
        }
        else {
            channel.sendMessage("Wait your turn " + event.getMember().getEffectiveName() + "!").queue();
        }
    }
}

Then you only need to register an instance of this in your initial event handler

if (content.startsWith("Hi Apples!")) {
    channel.sendMessage("Hi! Tell me your name, or say \"Stop\"!").queue();
    event.getJDA().addEventListener(new AppleStateMachine(channel, member.getUser());
}

Another alternative to this is using the JDA-Utilities class EventWaiter.



来源:https://stackoverflow.com/questions/54491660/how-to-make-a-discord-bot-wait-for-a-specific-user-to-send-a-message-with-jda

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!