252 lines
9.4 KiB
Java
252 lines
9.4 KiB
Java
package moe.oko.Kiafumi;
|
|
|
|
import moe.oko.Kiafumi.command.CommandClass;
|
|
import moe.oko.Kiafumi.command.CommandRegistrar;
|
|
import moe.oko.Kiafumi.listener.MainListener;
|
|
import moe.oko.Kiafumi.listener.SkynetListener;
|
|
import moe.oko.Kiafumi.model.KiafumiDB;
|
|
import moe.oko.Kiafumi.model.ServerManager;
|
|
import moe.oko.Kiafumi.util.CommandInfo;
|
|
import moe.oko.Kiafumi.util.EmbedUI;
|
|
import net.dv8tion.jda.api.EmbedBuilder;
|
|
import net.dv8tion.jda.api.JDA;
|
|
import net.dv8tion.jda.api.JDABuilder;
|
|
import net.dv8tion.jda.api.OnlineStatus;
|
|
import net.dv8tion.jda.api.entities.Activity;
|
|
import net.dv8tion.jda.api.entities.Guild;
|
|
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
|
|
import net.dv8tion.jda.api.requests.GatewayIntent;
|
|
import net.dv8tion.jda.api.utils.ChunkingFilter;
|
|
import net.dv8tion.jda.api.utils.MemberCachePolicy;
|
|
import net.dv8tion.jda.api.utils.cache.CacheFlag;
|
|
import org.simpleyaml.configuration.file.YamlConfiguration;
|
|
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.InputStream;
|
|
import java.nio.file.Files;
|
|
import java.time.ZonedDateTime;
|
|
import java.util.List;
|
|
|
|
import static moe.oko.Kiafumi.util.LoggingManager.*;
|
|
|
|
/**
|
|
* Kiafumi Main Class
|
|
* @author Kay, oko, Tiddy
|
|
* @version 0.9.0-pre
|
|
* @apiNote Thanks to:
|
|
* | Maxopoly, Orinnari, ProgrammerDan, and more, for helping teach Kay how to code Java from scratch.
|
|
* | Favna, and the HC Development community for encouraging the development core of HC.
|
|
* | HC as a whole, for being a wonderful community and encouraging the creation of this bot
|
|
* | Civ, for encouraging us all to sort out how the hell programming works
|
|
* | Discord, for offering a platform to learn these skills on
|
|
* | The Java Development Team, for making a Language I personally love and adore - Kay
|
|
*/
|
|
public class Kiafumi {
|
|
|
|
private final File CONFIG_FILE = new File("config.yml");
|
|
|
|
public YamlConfiguration yamlConfiguration = new YamlConfiguration();
|
|
|
|
public String footer = EmbedUI.BRAND + " 0.9.0-pre";
|
|
|
|
public static Kiafumi instance;
|
|
|
|
public static JDA JDA;
|
|
|
|
public List<CommandClass> activeCommands;
|
|
|
|
public KiafumiConfig config;
|
|
|
|
public KiafumiDB database;
|
|
public ServerManager serverManager;
|
|
|
|
/**
|
|
* Main Class function.
|
|
* @param args - Arguments for program start.
|
|
*/
|
|
public static void main(String[] args) {
|
|
try {
|
|
var kia = new Kiafumi();
|
|
kia.start();
|
|
} catch (Exception ex) {
|
|
System.out.println("Failed to start Kiafumi, check your Java installation.");
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Ran on program start. Anything in here can determine whether the program will start.
|
|
*/
|
|
public void start() {
|
|
instance = this;
|
|
info("Starting Kiafumi.");
|
|
|
|
// All commands to be loaded on startup!
|
|
activeCommands = new CommandRegistrar().getCommandClasses();
|
|
|
|
// Ensuring the configuration file is generated and/or exists.
|
|
if (!CONFIG_FILE.exists()) {
|
|
try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("config.yml")) {
|
|
// Save the default config
|
|
Files.copy(is, CONFIG_FILE.toPath());
|
|
} catch (Exception ex) {
|
|
warn("Failed to create the configuration file. Stopping. (" + CONFIG_FILE.getAbsolutePath() + ")");
|
|
ex.printStackTrace();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Try to load configuration into the configuration API.
|
|
try {
|
|
yamlConfiguration.load("config.yml");
|
|
} catch (FileNotFoundException e) {
|
|
e.printStackTrace();
|
|
warn("File not found, must've failed to create...");
|
|
} catch (Exception e) {
|
|
warn("Ensure all values are inputted properly.");
|
|
e.printStackTrace();
|
|
}
|
|
|
|
// Initializes our configuration helper & ensures it loads properly.
|
|
config = new KiafumiConfig(yamlConfiguration);
|
|
if(config.load()) {
|
|
info("Fetched Kiafumi config.");
|
|
} else {
|
|
error("Failed to load configuration. Stopping process.");
|
|
Runtime.getRuntime().exit(0);
|
|
}
|
|
|
|
// Registers the stop() function if the program is stopped.
|
|
info("Registering shutdown hook.");
|
|
Runtime.getRuntime().addShutdownHook(new Thread(this::stop));
|
|
|
|
// Initializes database and loads credentials.
|
|
database = config.createDb();
|
|
|
|
serverManager = new ServerManager();
|
|
|
|
// Makes our JDA instance.
|
|
startDiscord();
|
|
}
|
|
|
|
/**
|
|
* Ran on program shutdown.
|
|
*/
|
|
public void stop() {
|
|
var build = new EmbedBuilder()
|
|
.setColor(EmbedUI.FAILURE)
|
|
.setTitle("Offline")
|
|
.setFooter(footer)
|
|
.setTimestamp(ZonedDateTime.now());
|
|
JDA.getTextChannelById(config.getLogChannel()).sendMessageEmbeds(build.build()).queue();
|
|
info("Shutting down Kiafumi.");
|
|
if(database.saveServerInformation()) {
|
|
info("Successfully saved server information. Shutting down peacefully.");
|
|
} else {
|
|
for(int i = 0; i < 15; i++) {
|
|
error("FAILED TO SAVE SERVER INFORMATION.");
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts a JDA Instance.
|
|
*/
|
|
public void startDiscord() {
|
|
try {
|
|
JDA = JDABuilder.create(config.getToken(), GatewayIntent.GUILD_MEMBERS,
|
|
GatewayIntent.GUILD_MESSAGES,
|
|
GatewayIntent.DIRECT_MESSAGES, GatewayIntent.GUILD_PRESENCES, GatewayIntent.GUILD_VOICE_STATES)
|
|
.setChunkingFilter(ChunkingFilter.ALL)
|
|
.setMemberCachePolicy(MemberCachePolicy.ALL)
|
|
.disableCache(CacheFlag.EMOTE)
|
|
.setActivity(Activity.of(Activity.ActivityType.valueOf(config.getActivityType()), config.getActivityMsg()))
|
|
.setStatus(OnlineStatus.valueOf(config.getStatusType()))
|
|
.addEventListeners(
|
|
new MainListener(),
|
|
new SkynetListener()
|
|
).build().awaitReady();
|
|
} catch(Exception ex) {
|
|
error("Initialization broke...");
|
|
ex.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
registerAllCommands();
|
|
info("Finished registering commands.");
|
|
|
|
var eb = new EmbedBuilder()
|
|
.setColor(EmbedUI.SUCCESS)
|
|
.setTitle("Online")
|
|
.setFooter(footer)
|
|
.setTimestamp(ZonedDateTime.now());
|
|
JDA.getTextChannelById(config.getLogChannel()).sendMessageEmbeds(eb.build()).queue();
|
|
}
|
|
|
|
/**
|
|
* Quick method to register commands in all servers.
|
|
*/
|
|
private void registerAllCommands() {
|
|
// Registers slash commands.
|
|
info("Registering commands for guilds.");
|
|
int i = 0;
|
|
for(Guild guild : JDA.getGuilds()) {
|
|
registerForGuild(guild);
|
|
i++;
|
|
}
|
|
info("Registered commands for " + i + " guilds.");
|
|
|
|
// Registers the event listeners for those commands.
|
|
for(CommandClass cmd : activeCommands) {
|
|
JDA.addEventListener(cmd);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Registers all bot commands with the guild provided
|
|
* @param guild - guild to have commands provided to
|
|
*/
|
|
public void registerForGuild(Guild guild) {
|
|
debug("Registering commands for guild [" + guild.getName() + ":" + guild.getId() + "]");
|
|
int i = 0;
|
|
int j = 0;
|
|
for(CommandClass cmd : activeCommands) {
|
|
for(CommandInfo ci : cmd.getSlashCommandInfo()) {
|
|
var cca = guild.upsertCommand(ci.getName(), ci.getDescription());
|
|
i++;
|
|
if(ci.hasSubCommands()) {
|
|
for (String name : ci.getSubCommands().keySet()) {
|
|
var si = ci.getSubCommands().get(name);
|
|
var sd = new SubcommandData(si.getName(), si.getDescription());
|
|
for (String option : si.getOptions().keySet()) {
|
|
sd.addOption(si.getOptions().get(option), option, si.getOptionDescriptions().get(option), si.getOptionRequirements().get(option));
|
|
}
|
|
cca.addSubcommands(sd);
|
|
}
|
|
}
|
|
if(ci.hasOptions()) {
|
|
for(String name : ci.getOptions().keySet()) {
|
|
// Any intelligent IDE will rage about the option not being used, it's added to the action then executed later, don't edit without reason.
|
|
cca.addOption(ci.getOptions().get(name), name, ci.getOptionDescriptions().get(name), ci.getOptionRequirements().get(name));
|
|
}
|
|
}
|
|
// Push w/ modifications.
|
|
//trace("Command: " + ci.getName() + " registration on " + guild.getId() + " completed.");
|
|
try {
|
|
cca.queue();
|
|
} catch (Exception ex) {
|
|
// Only time this should occur is when a server does not have the proper scope.
|
|
error("Failed to queue command for RestAction.");
|
|
}
|
|
}
|
|
}
|
|
debug("Registered " + i + " commands for guild [" + guild.getId() + "]");
|
|
}
|
|
|
|
// Gets the active database.
|
|
public KiafumiDB getDatabase() { return database; }
|
|
|
|
// Gets active ServerManager
|
|
public ServerManager getServerManager() { return serverManager; }
|
|
} |