如何让 Discord Bot 等待特定用户使用 JDA 发送消息?
How to make a Discord Bot wait for a specific user to send a message with JDA?
我目前正在 Java 学习编程 class,并且最近开始尝试使用 JDA 工具为我的服务器制作一个基本的 Discord 机器人。理想情况下,我希望我的机器人在有人说 "Hello Apples!" 时通过询问他们的姓名来回应,然后如果此消息是由说 "Hello Apples!" 的同一个人发送的,则用 "Hi !" 回应 现在我的机器人未能等待超过初始 "Hello Apples!" 消息的任何用户输入,并立即溢出所有文本。我相信我当前的代码设置正确,以确保机器人仅在收到来自最初发送 "Hi Apples!" 的同一个人的消息时才响应 "Hi !",但我不能完全确定,因为它不等待其他消息,因此从同一消息中读取两次并打印出来:
你好!告诉我你的名字,或者说 "Stop"!
嗨嗨苹果!!
等着你
我真的很想知道如何创建某种 "stop",或者一种方法,使机器人等待最初问候机器人的用户的附加用户输入,如果可能的话,一种设置时间限制的方法,这样如果他们不回复,机器人就不会保持无法运行状态。
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;
}
}
}
}
}
我的预期结果是:
用户:嗨苹果!
机器人:嗨!告诉我你的名字,或者说停止!
USER2:嗨!
BOT:轮到你了 USER2!
用户:吉米
机器人:嗨,吉米!
实际结果:(一次性发送)
你好!告诉我你的名字,或者说 "Stop"!
嗨嗨苹果!!
轮到你了(我的不和谐昵称)!
由于您使用的是基于事件的框架,因此您可以使用状态机来实现此行为。每当您获得初始触发器时,在这种情况下 "Hi Apple!"
您将为该文本通道启动一个新的状态机。
在此状态机中,您处理消息事件直到终止信号到达,在本例中为 "Stop!"
。
状态机将使用事件方法中的开关案例和私有 state
字段来实现。在这种情况下,您在整个对话中只有一次互动,因此只有一种状态使这毫无意义。
但是例如,在进行对话的情况下,我认为这将在稍后进行,您将需要使用状态机概念。
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();
}
}
}
那么你只需要在你的初始事件处理程序中注册一个这样的实例
if (content.startsWith("Hi Apples!")) {
channel.sendMessage("Hi! Tell me your name, or say \"Stop\"!").queue();
event.getJDA().addEventListener(new AppleStateMachine(channel, member.getUser());
}
确保您不要在此处混用 GuildMessageReceivedEvent
和 MessageReceivedEvent
,因为它们是按顺序触发的,您可能会收到两次初始消息。您的状态机和消息侦听器都应该侦听相同类型的事件。
另一种替代方法是使用 JDA-Utilities class EventWaiter
.
我目前正在 Java 学习编程 class,并且最近开始尝试使用 JDA 工具为我的服务器制作一个基本的 Discord 机器人。理想情况下,我希望我的机器人在有人说 "Hello Apples!" 时通过询问他们的姓名来回应,然后如果此消息是由说 "Hello Apples!" 的同一个人发送的,则用 "Hi !" 回应 现在我的机器人未能等待超过初始 "Hello Apples!" 消息的任何用户输入,并立即溢出所有文本。我相信我当前的代码设置正确,以确保机器人仅在收到来自最初发送 "Hi Apples!" 的同一个人的消息时才响应 "Hi !",但我不能完全确定,因为它不等待其他消息,因此从同一消息中读取两次并打印出来:
你好!告诉我你的名字,或者说 "Stop"!
嗨嗨苹果!!
等着你
我真的很想知道如何创建某种 "stop",或者一种方法,使机器人等待最初问候机器人的用户的附加用户输入,如果可能的话,一种设置时间限制的方法,这样如果他们不回复,机器人就不会保持无法运行状态。
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;
}
}
}
}
}
我的预期结果是:
用户:嗨苹果!
机器人:嗨!告诉我你的名字,或者说停止!
USER2:嗨!
BOT:轮到你了 USER2!
用户:吉米
机器人:嗨,吉米!
实际结果:(一次性发送)
你好!告诉我你的名字,或者说 "Stop"!
嗨嗨苹果!!
轮到你了(我的不和谐昵称)!
由于您使用的是基于事件的框架,因此您可以使用状态机来实现此行为。每当您获得初始触发器时,在这种情况下 "Hi Apple!"
您将为该文本通道启动一个新的状态机。
在此状态机中,您处理消息事件直到终止信号到达,在本例中为 "Stop!"
。
状态机将使用事件方法中的开关案例和私有 state
字段来实现。在这种情况下,您在整个对话中只有一次互动,因此只有一种状态使这毫无意义。
但是例如,在进行对话的情况下,我认为这将在稍后进行,您将需要使用状态机概念。
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();
}
}
}
那么你只需要在你的初始事件处理程序中注册一个这样的实例
if (content.startsWith("Hi Apples!")) {
channel.sendMessage("Hi! Tell me your name, or say \"Stop\"!").queue();
event.getJDA().addEventListener(new AppleStateMachine(channel, member.getUser());
}
确保您不要在此处混用 GuildMessageReceivedEvent
和 MessageReceivedEvent
,因为它们是按顺序触发的,您可能会收到两次初始消息。您的状态机和消息侦听器都应该侦听相同类型的事件。
另一种替代方法是使用 JDA-Utilities class EventWaiter
.