net.dv8tion.discord.Yui.java Source code

Java tutorial

Introduction

Here is the source code for net.dv8tion.discord.Yui.java

Source

/**
 *     Copyright 2015-2016 Austin Keener
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.dv8tion.discord;

import net.dv8tion.discord.bridge.IrcConnectInfo;
import net.dv8tion.discord.bridge.IrcConnection;
import net.dv8tion.discord.bridge.endpoint.EndPointInfo;
import net.dv8tion.discord.bridge.endpoint.EndPointManager;
import net.dv8tion.discord.commands.*;
import net.dv8tion.discord.music.PlayerControl;
import net.dv8tion.discord.util.Database;
import net.dv8tion.discord.util.GoogleSearch;
import net.dv8tion.jda.core.AccountType;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.JDABuilder;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.exceptions.RateLimitedException;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;

import javax.security.auth.login.LoginException;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

public class Yui {
    //Non error, no action exit codes.
    public static final int NORMAL_SHUTDOWN = 10;
    public static final int RESTART_EXITCODE = 11;
    public static final int NEWLY_CREATED_CONFIG = 12;

    //Non error, action required exit codes.
    public static final int UPDATE_LATEST_EXITCODE = 20;
    public static final int UPDATE_RECOMMENDED_EXITCODE = 21;

    //error exit codes.
    public static final int UNABLE_TO_CONNECT_TO_DISCORD = 30;
    public static final int BAD_USERNAME_PASS_COMBO = 31;
    public static final int NO_USERNAME_PASS_COMBO = 32;

    private static JDA api;
    private static List<IrcConnection> ircConnections;

    public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
        if (System.getProperty("file.encoding").equals("UTF-8")) {
            setupBot();
        } else {
            relaunchInUTF8();
        }
    }

    public static File getThisJarFile() throws UnsupportedEncodingException {
        //Gets the path of the currently running Jar file
        String path = Yui.class.getProtectionDomain().getCodeSource().getLocation().getPath();
        String decodedPath = URLDecoder.decode(path, "UTF-8");

        //This is code especially written for running and testing this program in an IDE that doesn't compile to .jar when running.
        if (!decodedPath.endsWith(".jar")) {
            return new File("Yui.jar");
        }
        return new File(decodedPath); //We use File so that when we send the path to the ProcessBuilder, we will be using the proper System path formatting.
    }

    public static JDA getAPI() {
        return api;
    }

    public static IrcConnection getIrcConnection(String identifier) {
        for (IrcConnection irc : ircConnections) {
            if (irc.getIdentifier().equals(identifier))
                return irc;
        }
        return null;
    }

    private static void setupBot() {
        try {
            Settings settings = SettingsManager.getInstance().getSettings();

            JDABuilder jdaBuilder = new JDABuilder(AccountType.BOT).setToken(settings.getBotToken());
            Database.getInstance();
            Permissions.setupPermissions();
            ircConnections = new ArrayList<IrcConnection>();

            HelpCommand help = new HelpCommand();
            jdaBuilder.addListener(help.registerCommand(help));
            if (settings.getGoogleApiKey() != null && !settings.getGoogleApiKey().isEmpty()) {
                GoogleSearch.setup(settings.getGoogleApiKey());
                jdaBuilder.addListener(help.registerCommand(new SearchCommand()));
                jdaBuilder.addListener(help.registerCommand(new NyaaCommand()));
                jdaBuilder.addListener(help.registerCommand(new MyAnimeListCommand()));
                jdaBuilder.addListener(help.registerCommand(new AnimeNewsNetworkCommand()));
            } else {
                System.out.println("No Google API Key provided, all search commands disabled");
            }
            jdaBuilder.addListener(help.registerCommand(new ReloadCommand()));
            jdaBuilder.addListener(help.registerCommand(new UpdateCommand()));
            jdaBuilder.addListener(help.registerCommand(new PermissionsCommand()));
            jdaBuilder.addListener(help.registerCommand(new EvalCommand()));
            jdaBuilder.addListener(help.registerCommand(new RollCommand()));
            jdaBuilder.addListener(help.registerCommand(new InfoCommand()));
            jdaBuilder.addListener(help.registerCommand(new UptimeCommand()));

            //Audio stuff
            jdaBuilder.addListener(new PlayerControl());

            for (IrcConnectInfo info : settings.getIrcConnectInfos()) {
                if (info.getHost() == null || info.getHost().isEmpty()) {
                    System.out.println(
                            "Skipping IRC connection '" + info.getIdentifier() + "' because no Host was provided.");
                    continue;
                }
                if (info.getNick() == null || info.getNick().isEmpty()) {
                    System.out.println(
                            "Skipping IRC connection '" + info.getIdentifier() + "' because no Nick was provided.");
                    continue;
                }
                IrcConnection irc = new IrcConnection(info);
                ircConnections.add(irc);
                jdaBuilder.addListener(irc);
            }

            if (settings.getProxyHost() != null && !settings.getProxyHost().isEmpty()) {
                //Sets JDA's proxy settings
                jdaBuilder
                        .setProxy(new HttpHost(settings.getProxyHost(), Integer.valueOf(settings.getProxyPort())));

                //Sets the JVM level proxy settings.
                System.setProperty("http.proxyHost", settings.getProxyHost());
                System.setProperty("http.proxyPort", settings.getProxyPort());
                System.setProperty("https.proxyHost", settings.getProxyHost());
                System.setProperty("https.proxyPort", settings.getProxyPort());

            }

            //Login to Discord now that we are all setup.
            api = jdaBuilder.buildBlocking();
            Permissions.getPermissions().setBotAsOp(api.getSelfUser());

            api.addEventListener(help.registerCommand(new TodoCommand(api)));
            api.addEventListener(help.registerCommand(new KanzeTodoCommand(api)));

            //Creates and Stores all Discord endpoints in our Manager.
            for (Guild guild : api.getGuilds()) {
                for (TextChannel channel : guild.getTextChannels()) {
                    EndPointManager.getInstance().createEndPoint(EndPointInfo.createFromDiscordChannel(channel));
                }
            }
        } catch (IllegalArgumentException e) {
            System.out.println("No login details provided! Please provide a botToken in the config.");
            System.exit(NO_USERNAME_PASS_COMBO);
        } catch (LoginException e) {
            System.out.println("The botToken provided in the Config.json was incorrect.");
            System.out.println("Did you modify the Config.json after it was created?");
            System.exit(BAD_USERNAME_PASS_COMBO);
        } catch (InterruptedException e) {
            System.out.println("Our login thread was interrupted!");
            System.exit(UNABLE_TO_CONNECT_TO_DISCORD);
        } catch (RateLimitedException e) {
            System.out.println("Encountered ratelimit while attempting to login!");
            System.exit(UNABLE_TO_CONNECT_TO_DISCORD);
        }
    }

    private static void relaunchInUTF8() throws InterruptedException, UnsupportedEncodingException {
        System.out.println("BotLauncher: We are not running in UTF-8 mode! This is a problem!");
        System.out.println("BotLauncher: Relaunching in UTF-8 mode using -Dfile.encoding=UTF-8");

        String[] command = new String[] { "java", "-Dfile.encoding=UTF-8", "-jar",
                Yui.getThisJarFile().getAbsolutePath() };

        //Relaunches the bot using UTF-8 mode.
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.inheritIO(); //Tells the new process to use the same command line as this one.
        try {
            Process process = processBuilder.start();
            process.waitFor(); //We wait here until the actual bot stops. We do this so that we can keep using the same command line.
            System.exit(process.exitValue());
        } catch (IOException e) {
            if (e.getMessage().contains("\"java\"")) {
                System.out.println(
                        "BotLauncher: There was an error relaunching the bot. We couldn't find Java to launch with.");
                System.out.println("BotLauncher: Attempted to relaunch using the command:\n   "
                        + StringUtils.join(command, " ", 0, command.length));
                System.out.println(
                        "BotLauncher: Make sure that you have Java properly set in your Operating System's PATH variable.");
                System.out.println("BotLauncher: Stopping here.");
            } else {
                e.printStackTrace();
            }
        }
    }
}