Discord JDA Bot генерирует исключение NullPointerException при вызове расширенного класса - PullRequest
1 голос
/ 25 января 2020

Я сейчас пытаюсь запрограммировать очень базового c Discord бота в JDA, и я только что столкнулся с проблемой, пытаясь аккуратно разделить мой код на основной класс, MessageHandler, CommandHandler и VoiceHandler класс.

Главный класс добавил бы EventListener для вызова MessageHandler, если событие получено, и затем перейдет в CommandHandler, если префикс бота виден перед командой.

Проблема заключается в том, что он выдает исключение NullPointerException при попытке вызвать CommandHandler с new CommandHandler.handleCmd. Сообщение об ошибке гласит "ERROR JDA - One of the EventListeners had an uncaught exception" Но оно не должно делать ничего, кроме перехода в функцию handleCmd класса CommandHandler, если я не ошибаюсь. Поэтому я не понимаю, почему это должно приводить к ошибке.

Любая помощь будет принята с благодарностью!

Это мой основной класс

import net.dv8tion.jda.api.AccountType;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

import javax.security.auth.login.LoginException;

public class Main extends ListenerAdapter {
    public static void main(String[] args) throws LoginException {
        JDABuilder builder = new JDABuilder(AccountType.BOT);
        String token = "somethingsomething";
        builder.setToken(token);
        builder.addEventListeners(new MessageHandler());   //Puts Eventlistener to trigger MessageHandler

        builder.build();
    }
}

, который должен вызвать мой MessageHandler

import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;

public class MessageHandler extends ListenerAdapter {
    protected String userName;
    protected String userMessage;
    protected MessageReceivedEvent event;

    public void onMessageReceived(MessageReceivedEvent event) {
        userName = event.getAuthor().getName();
        userMessage = event.getMessage().getContentRaw();
        this.event = event;

        if (event.getAuthor().isBot()) {
            return;
        } else if (userMessage.startsWith(">")) {
            new CommandHandler().handleCmd();                            //Should trigger CommandHandler (this is the problem)
        }
    }
}

И затем ветвь в CommandHandler

public class CommandHandler extends MessageHandler {
    private String command = userMessage.substring(1);

    public void handleCmd() {
        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

Метод VoiceHandler.join () просто заставляет бота подключаться к моему голосовому каналу, но на данный момент это не имеет значения

Также вот полное сообщение об ошибке, если это полезно

[JDA MainWS-ReadThread] ERROR JDA - One of the EventListeners had an uncaught exception
java.lang.NullPointerException
    at CommandHandler.<init>(CommandHandler.java:2)
    at MessageHandler.onMessageReceived(MessageHandler.java:17)
    at net.dv8tion.jda.api.hooks.ListenerAdapter.onEvent(ListenerAdapter.java:376)
    at net.dv8tion.jda.api.hooks.InterfacedEventManager.handle(InterfacedEventManager.java:96)
    at net.dv8tion.jda.internal.hooks.EventManagerProxy.handle(EventManagerProxy.java:64)
    at net.dv8tion.jda.internal.JDAImpl.handleEvent(JDAImpl.java:151)
    at net.dv8tion.jda.internal.handle.MessageCreateHandler.handleInternally(MessageCreateHandler.java:122)
    at net.dv8tion.jda.internal.handle.SocketHandler.handle(SocketHandler.java:36)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onDispatch(WebSocketClient.java:853)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onEvent(WebSocketClient.java:741)
    at net.dv8tion.jda.internal.requests.WebSocketClient.handleEvent(WebSocketClient.java:720)
    at net.dv8tion.jda.internal.requests.WebSocketClient.onBinaryMessage(WebSocketClient.java:891)
    at com.neovisionaries.ws.client.ListenerManager.callOnBinaryMessage(ListenerManager.java:385)
    at com.neovisionaries.ws.client.ReadingThread.callOnBinaryMessage(ReadingThread.java:276)
    at com.neovisionaries.ws.client.ReadingThread.handleBinaryFrame(ReadingThread.java:996)
    at com.neovisionaries.ws.client.ReadingThread.handleFrame(ReadingThread.java:755)
    at com.neovisionaries.ws.client.ReadingThread.main(ReadingThread.java:108)
    at com.neovisionaries.ws.client.ReadingThread.runMain(ReadingThread.java:64)
    at com.neovisionaries.ws.client.WebSocketThread.run(WebSocketThread.java:45)

1 Ответ

1 голос
/ 25 января 2020

Stacktrace сообщает вам, в какой строке происходит исключение (строка 2 из CommandHandler).

Ваше поле userMessage равно null, и вы выполняете вызов метода для него. Это происходит, если userMessage не был установлен в вашем CommandHandler.

Следующий фрагмент кода

userMessage = event.getMessage().getContentRaw(); 

устанавливает userMessage только в текущем объекте MessageHandler. Эти значения не используются совместно с вновь созданными объектами CommandHandler. Вам необходимо установить их явно с помощью конструктора или параметров метода. Вы также можете изменить эти поля на stati c fields.

Как это может выглядеть при использовании конструктора:

public class CommandHandler extends MessageHandler {
    private String command;

    /**
    *   You can add more parameters to this constructor or also a MessageHandler object.
    **/
    public CommandHandler(String userMessage){
        if(userMessage != null){
            this.comand = userMessage.substring(1);
        }
    }

    public void handleCmd() {
        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

И создание объекта будет выглядеть так:

if (event.getAuthor().isBot()) {
    return;
} else if (userMessage.startsWith(">")) {
    new CommandHandler(userMessage).handleCmd();
}

Вопрос в том, зачем вам расширять MessageHandler? Вы используете его как служебный класс, поэтому я бы предложил изменить его на служебный класс:

public final class CommandHandler {

    public static void handleCmd(String userMessage) {
        if(userMessage == null){
            return;
        }
        String command = userMessage.substring(1);

        switch (command) {
            case "join":
                new VoiceHandler().join();
                break;
            case ... :
                ...
                break;
            case ... :
                ...
                break;
        }
    }
}

И вызов этого метода:

CommandHandler.handleCmd(userMessage);
...