diff --git a/pom.xml b/pom.xml index a78339f..fca2c08 100644 --- a/pom.xml +++ b/pom.xml @@ -33,12 +33,22 @@ org.apache.httpcomponents httpclient - 4.5 + 4.5.13 - org.slf4j - slf4j-simple - 1.7.9 + org.apache.logging.log4j + log4j-api + 2.17.2 + + + org.apache.logging.log4j + log4j-core + 2.17.2 + + + org.apache.logging.log4j + log4j-slf4j-impl + 2.17.2 com.sedmelluq @@ -48,7 +58,7 @@ mysql mysql-connector-java - 8.0.28 + 8.0.29 @@ -60,7 +70,7 @@ com.google.guava guava - 31.0.1-jre + 31.1-jre @@ -78,6 +88,11 @@ bintray https://jcenter.bintray.com + + maven_central + Maven Central + https://repo.maven.apache.org/maven2/ + diff --git a/src/main/java/moe/oko/Kiafumi/Kiafumi.java b/src/main/java/moe/oko/Kiafumi/Kiafumi.java index fc48607..94e24e4 100644 --- a/src/main/java/moe/oko/Kiafumi/Kiafumi.java +++ b/src/main/java/moe/oko/Kiafumi/Kiafumi.java @@ -90,8 +90,6 @@ public class Kiafumi { // All commands to be loaded on startup! activeCommands = new CommandRegistrar().getCommandClasses(); - logger.info("Config load start..."); - // Ensuring the configuration file is generated and/or exists. if (!CONFIG_FILE.exists()) { try (InputStream is = this.getClass().getClassLoader().getResourceAsStream("config.yml")) { @@ -143,7 +141,6 @@ public class Kiafumi { public void stop() { var build = new EmbedBuilder() .setColor(EmbedUI.FAILURE) - .setAuthor("Kiafumi", null, Kiafumi.JDA.getSelfUser().getAvatarUrl()) .setTitle("Offline") .setFooter(footer) .setTimestamp(ZonedDateTime.now()); @@ -178,11 +175,10 @@ public class Kiafumi { } registerAllCommands(); - info("Loaded " + activeCommands.size() + " commands."); + info("Finished registering commands."); var eb = new EmbedBuilder() .setColor(EmbedUI.SUCCESS) - .setAuthor("Kiafumi", null, Kiafumi.JDA.getSelfUser().getAvatarUrl()) .setTitle("Online") .setFooter(footer) .setTimestamp(ZonedDateTime.now()); @@ -194,6 +190,7 @@ public class Kiafumi { */ private void registerAllCommands() { // Registers slash commands. + info("Registering commands for guilds."); for(Guild guild : JDA.getGuilds()) { registerForGuild(guild); } @@ -209,7 +206,7 @@ public class Kiafumi { * @param guild - guild to have commands provided to */ public void registerForGuild(Guild guild) { - info("Registering commands for guild [" + guild.getId() + "]"); + debug("Registering commands for guild [" + guild.getName() + ":" + guild.getId() + "]"); int i = 0; for(CommandClass cmd : activeCommands) { for(CommandInfo ci : cmd.getSlashCommandInfo()) { @@ -232,7 +229,7 @@ public class Kiafumi { } } // Push w/ modifications. - //info("Command: " + ci.getName() + " registration on " + guild.getId() + " completed."); + //trace("Command: " + ci.getName() + " registration on " + guild.getId() + " completed."); try { cca.queue(); } catch (Exception ex) { @@ -245,18 +242,15 @@ public class Kiafumi { } /* - Static logger info reference. + Static logger references. */ public static void info(String str) { instance.logger.info(str); } - - /* - Static Logger Error reference. - */ public static void error(String str) { instance.logger.error(str); } + public static void debug(String str) { instance.logger.debug(str); } /** * Used for logging commands with ease to console via a static method. @@ -264,15 +258,15 @@ public class Kiafumi { * @param msg - Any message to append with this. */ public static void slashLog(SlashCommandInteractionEvent event, @Nullable String msg) { - info("User[" + event.getUser().getName() + ":" + event.getUser().getId() + "] RAN " + event.getName() + "." + (msg == null ? "" : msg)); + info("User [" + event.getUser().getName() + ":" + event.getUser().getId() + "] ran command: \"" + event.getName() + "\"." + (msg == null ? "" : msg)); } public static void slashLog(SlashCommandInteractionEvent event) { - info("User[" + event.getUser().getName() + ":" + event.getUser().getId() + "] RAN " + event.getName() + "."); + info("User [" + event.getUser().getName() + ":" + event.getUser().getId() + "] ran command: \"" + event.getName() + "\"."); } public static void slashResponse(SlashCommandInteractionEvent event, String msg) { - info("User[" + event.getUser().getName() + ":" + event.getUser().getId() + "] CMD RESPONSE: " + msg); + info("User [" + event.getUser().getName() + ":" + event.getUser().getId() + "] was provided response: \"" + msg + "\""); } // Gets the active database. diff --git a/src/main/java/moe/oko/Kiafumi/KiafumiConfig.java b/src/main/java/moe/oko/Kiafumi/KiafumiConfig.java index 4e1607d..1930424 100644 --- a/src/main/java/moe/oko/Kiafumi/KiafumiConfig.java +++ b/src/main/java/moe/oko/Kiafumi/KiafumiConfig.java @@ -65,8 +65,7 @@ public class KiafumiConfig { */ public boolean load() { try { - var n = System.lineSeparator(); // newline - info("Starting Discord configuration load"); + var n = System.lineSeparator() + "\033[0m"; // newline // Discord loaders var discord = configuration.getConfigurationSection("discord"); @@ -76,12 +75,15 @@ public class KiafumiConfig { mainGuild = discord.getString("mainGuild"); clientId = discord.getString("clientId"); defaultInvitePermissionLevel = discord.getInt("invitePermissionLevel"); - // Log discord settings. - info("Discord configuration:" +n+ - "Log Channel: " + logChannel +n+ - "Owner ID: " + ownerId +n+ - "Primary Guild: " + mainGuild +n+ - "Invite link: " + assembleDefaultInvite()); + // Log discord settings in a neat table. + info("Printing loaded discord configuration." +n+ + "DISCORD CONFIGURATION" +n+ + "--------------------------------" +n+ + "Log Channel: \033[0;34m" + logChannel +n+ + "Owner ID: \033[0;34m" + ownerId +n+ + "Primary Guild: \033[0;34m" + mainGuild +n+ + "Invite URL: \033[0;34m" + assembleDefaultInvite() +n+ + "--------------------------------"); // Kiafumi loaders var main = configuration.getConfigurationSection("main"); @@ -107,7 +109,6 @@ public class KiafumiConfig { error("Failed to load configuration!"); return false; } - info("Configuration Loaded."); return true; } diff --git a/src/main/java/moe/oko/Kiafumi/command/CommandRegistrar.java b/src/main/java/moe/oko/Kiafumi/command/CommandRegistrar.java index 1ef49e0..4f74cf2 100644 --- a/src/main/java/moe/oko/Kiafumi/command/CommandRegistrar.java +++ b/src/main/java/moe/oko/Kiafumi/command/CommandRegistrar.java @@ -11,6 +11,7 @@ import java.util.stream.Collectors; import static moe.oko.Kiafumi.Kiafumi.error; import static moe.oko.Kiafumi.Kiafumi.info; +import static moe.oko.Kiafumi.Kiafumi.debug; /** * CommandRegistrar Class @@ -49,13 +50,13 @@ public class CommandRegistrar { // TODO have this check the classpath that we're under and have it scan *that* instead of hard-coding it to only be moe.oko.Kiafumi path. var classes = findAllClassesContaining("moe.oko.Kiafumi.command"); List commands = new ArrayList<>(); - info("[CommandRegistrar] Discovered " + classes.size() + " classes containing moe.oko.Kiafumi.command in package class."); + debug("Discovered " + classes.size() + " classes containing moe.oko.Kiafumi.command in package class."); for (Class clazz : classes) { for (Constructor cnstr : clazz.getConstructors()) { try { var obj = cnstr.newInstance(); // making an attempt. if (obj instanceof CommandClass) { - info("[CommandRegistrar] Registering class " + cnstr.getName()); + debug("Loading command class %green(" + cnstr.getName() + ")."); commands.add((CommandClass) obj); } } catch (InstantiationException ex) { @@ -63,12 +64,12 @@ public class CommandRegistrar { } } } - info("[CommandRegistrar] CommandClasses loaded [" + commands.size() + "]"); + info("Loaded [" + commands.size() + "] command classes."); return commands; } catch (IllegalAccessException | InvocationTargetException exception) { // Now we don't ignore, this is a core issue. exception.printStackTrace(); - error("[CommandRegistrar] Fatal failure in class loading."); + error("Failure in command class loading."); return null; } } diff --git a/src/main/java/moe/oko/Kiafumi/command/music/MusicCommand.java b/src/main/java/moe/oko/Kiafumi/command/music/MusicCommand.java index e25800c..be8ac79 100644 --- a/src/main/java/moe/oko/Kiafumi/command/music/MusicCommand.java +++ b/src/main/java/moe/oko/Kiafumi/command/music/MusicCommand.java @@ -8,7 +8,6 @@ import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers; import com.sedmelluq.discord.lavaplayer.tools.FriendlyException; import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist; import com.sedmelluq.discord.lavaplayer.track.AudioTrack; -import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import moe.oko.Kiafumi.command.CommandClass; import moe.oko.Kiafumi.model.audio.AudioInfo; import moe.oko.Kiafumi.model.audio.AudioPlayerSendHandler; @@ -133,14 +132,16 @@ public class MusicCommand extends CommandClass { if (info.hasVoted(e.getUser())) { e.getHook().sendMessage("\u26A0 You've already voted to skip this song!").queue(); } else { + // Determine requisite votes. int votes = info.getSkips(); - int required = Math.round((info.getAuthor().getVoiceState().getChannel().getMembers().size() - 1) / 2); // Determines required amount of votes - if (votes >= (required)){ + int channelUsers = info.getAuthor().getVoiceState().getChannel().getMembers().size()-1; + int required = channelUsers/2; + if (votes+1 >= required){ getPlayer(e.getGuild()).stopTrack(); e.getHook().sendMessage("\u23E9 Skipping current track.").queue(); } else { info.addSkip(e.getUser()); - e.getHook().sendMessage("**" + e.getUser().getName() + "** voted to skip the track. [" + (votes + 1) + "/" + (required) + "]").queue(); + e.getHook().sendMessage("**" + e.getUser().getName() + "** voted to skip the track. [" + (votes+1) + "/" + (required) + "]").queue(); } } } @@ -149,7 +150,6 @@ public class MusicCommand extends CommandClass { slashLog(e); e.deferReply().queue(); if (isIdle(e.getHook(), e.getGuild())) return; - if (isCurrentDj(e.getMember()) || isDj(e.getMember())) { forceSkipTrack(e.getGuild(), e.getHook()); } else { @@ -190,7 +190,7 @@ public class MusicCommand extends CommandClass { case "play": e.deferReply().queue(); var input = e.getOption("url").getAsString(); - slashLog(e, "INPUT " + input); + slashLog(e, " With search \"" + input + "\"."); if(input.contains("https://")) { loadTrack(input, e.getMember(), e.getHook()); } else { diff --git a/src/main/java/moe/oko/Kiafumi/command/utility/DuckCommand.java b/src/main/java/moe/oko/Kiafumi/command/utility/DuckCommand.java index e8203e5..610e66c 100644 --- a/src/main/java/moe/oko/Kiafumi/command/utility/DuckCommand.java +++ b/src/main/java/moe/oko/Kiafumi/command/utility/DuckCommand.java @@ -38,7 +38,7 @@ public class DuckCommand extends CommandClass { if ("search".equals(name)) { e.deferReply().queue(); String option = e.getOption("query").getAsString(); - slashLog(e, "WITH QUERY " + option); + slashLog(e, " With search \"" + option + "\"."); WebSearch ws = WebSearch.instanceOf(); SearchResult sr; try { diff --git a/src/main/java/moe/oko/Kiafumi/command/utility/InfoCommand.java b/src/main/java/moe/oko/Kiafumi/command/utility/InfoCommand.java index d809ef7..604d11a 100644 --- a/src/main/java/moe/oko/Kiafumi/command/utility/InfoCommand.java +++ b/src/main/java/moe/oko/Kiafumi/command/utility/InfoCommand.java @@ -38,7 +38,7 @@ public class InfoCommand extends CommandClass { ? e.getMember() : e.getOption("user").getAsMember(); final var dTF = DateTimeFormatter.ofPattern("MM-dd-yyyy"); - slashLog(e, "FOR USER " + member.getUser().getName() + ":" + member.getId()); + slashLog(e, " For user [" + member.getUser().getName() + ":" + member.getId() + "]."); // Build embed EmbedBuilder eb1 = new EmbedBuilder() .setColor(EmbedUI.INFO) @@ -56,7 +56,7 @@ public class InfoCommand extends CommandClass { // Setup variables final var guild = e.getGuild(); final var dTF2 = DateTimeFormatter.ofPattern("MM-dd-yyyy"); - slashLog(e, "FOR GUILD[" + guild.getId() + ":" + guild.getName() + "]"); + slashLog(e, " For guild [" + guild.getId() + ":" + guild.getName() + "]"); // Build Embed EmbedBuilder eb2 = new EmbedBuilder() .setColor(EmbedUI.INFO) diff --git a/src/main/java/moe/oko/Kiafumi/command/utility/SettingCommand.java b/src/main/java/moe/oko/Kiafumi/command/utility/SettingCommand.java index dd2b408..6a5bfa3 100644 --- a/src/main/java/moe/oko/Kiafumi/command/utility/SettingCommand.java +++ b/src/main/java/moe/oko/Kiafumi/command/utility/SettingCommand.java @@ -25,7 +25,7 @@ import static moe.oko.Kiafumi.Kiafumi.slashResponse; public class SettingCommand extends CommandClass { @Override public boolean isEnabled() { - return true; //Another non-disable command + return true; // Another non-disable command } @Override @@ -41,7 +41,7 @@ public class SettingCommand extends CommandClass { case "settings" -> { slashLog(e); e.deferReply().queue(); - //No options, just fire an embed off... + // No options, just fire an embed off... EmbedBuilder eb = new EmbedBuilder() .setColor(EmbedUI.INFO) .setTitle("Kiafumi Settings") @@ -49,22 +49,21 @@ public class SettingCommand extends CommandClass { .setFooter(EmbedUI.BRAND) .setTimestamp(ZonedDateTime.now()); e.getHook().sendMessageEmbeds(eb.build()).queue(); - return; } case "setting" -> { - //User is attempting a settings modification. Check if admin. + // User is attempting a settings modification. Check if admin. if(!e.getMember().hasPermission(Permission.ADMINISTRATOR) && !e.getMember().isOwner()) { - slashLog(e, "FAILED PERM CHECK"); + slashLog(e, EmbedUI.RESPONSE_PRIVILEGES); e.deferReply(true).queue(); - //Private reply, other people can't see this if ephemeral. - e.getHook().sendMessage("**You cannot run this command**").queue(); + // Private reply, other people can't see this if ephemeral. + e.getHook().sendMessage("**You cannot run this command.**").queue(); return; } switch (e.getSubcommandName().toLowerCase()) { case "view" -> { e.deferReply().queue(); String opt = e.getOption("name").getAsString(); - slashLog(e, "SUBCOMMAND[VIEW] FOR " + opt); + slashLog(e, "With subcommand \"" + name + "\". Setting \"" + opt + "\"."); EmbedBuilder eb1 = new EmbedBuilder() .setColor(EmbedUI.INFO) .setTitle(opt) @@ -72,13 +71,12 @@ public class SettingCommand extends CommandClass { .setFooter(EmbedUI.BRAND) .setTimestamp(ZonedDateTime.now()); e.getHook().sendMessageEmbeds(eb1.build()).queue(); - return; } case "set" -> { e.deferReply().queue(); String opt1 = e.getOption("name").getAsString(); String opt2 = e.getOption("value").getAsString(); - slashLog(e, "SUBCOMMAND[SET] FOR " + opt1 + " TO " + opt2); + slashLog(e, "With subcommand \"" + name + "\". Setting \"" + opt1 + "\" to \"" + opt2 + "\"."); String response = server.setOptionByString(opt1, opt2); slashResponse(e, response); EmbedBuilder eb2 = new EmbedBuilder() @@ -88,12 +86,11 @@ public class SettingCommand extends CommandClass { .setFooter(EmbedUI.BRAND) .setTimestamp(ZonedDateTime.now()); e.getHook().sendMessageEmbeds(eb2.build()).queue(); - return; } case "clear" -> { e.deferReply().queue(); String opt3 = e.getOption("name").getAsString(); - slashLog(e, "SUBCOMMAND[CLEAR] FOR " + opt3); + slashLog(e, "With subcommand \"" + name + "\". Setting \"" + opt3 + "\"."); String response1 = server.resetOptionByString(opt3); slashResponse(e, response1); EmbedBuilder eb3 = new EmbedBuilder() @@ -103,7 +100,6 @@ public class SettingCommand extends CommandClass { .setFooter(EmbedUI.BRAND) .setTimestamp(ZonedDateTime.now()); e.getHook().sendMessageEmbeds(eb3.build()).queue(); - return; } } } @@ -116,7 +112,7 @@ public class SettingCommand extends CommandClass { List si = new ArrayList<>(); CommandInfo ci2 = new CommandInfo("setting", "Permits modification, viewing, and clearing of settings.", CommandType.COMMAND); - //For those looking here for inspiration, you CANNOT mix options and subcommands. You can only have one or the other. + // For those looking here for inspiration, you CANNOT mix options and subcommands. You can only have one or the other. CommandInfo ci = new CommandInfo("view", "Shows the current value for the setting provided.", CommandType.SUBCOMMAND); ci.addOption("name", "The name of the setting to display", OptionType.STRING, true); diff --git a/src/main/java/moe/oko/Kiafumi/listener/MainListener.java b/src/main/java/moe/oko/Kiafumi/listener/MainListener.java index 3f03d6c..a82d9de 100644 --- a/src/main/java/moe/oko/Kiafumi/listener/MainListener.java +++ b/src/main/java/moe/oko/Kiafumi/listener/MainListener.java @@ -46,8 +46,12 @@ public class MainListener extends ListenerAdapter { */ @Override public void onReady(@NotNull ReadyEvent event) { - info("Received READY signal from Discord, bot is now logged in." + System.lineSeparator() + - " Guilds Active: " + event.getGuildAvailableCount() + " Guilds Unavailable: " + event.getGuildUnavailableCount()); + var n = System.lineSeparator(); + info("Received READY signal from Discord, bot is now logged in." +n+ + "--------------------------------" +n+ + "Active Guilds: " + event.getGuildAvailableCount() +n+ + "Guilds Unavailable: " + event.getGuildUnavailableCount() +n+ + "--------------------------------"); } /** diff --git a/src/main/java/moe/oko/Kiafumi/model/KiafumiDB.java b/src/main/java/moe/oko/Kiafumi/model/KiafumiDB.java index 28006b7..021df99 100644 --- a/src/main/java/moe/oko/Kiafumi/model/KiafumiDB.java +++ b/src/main/java/moe/oko/Kiafumi/model/KiafumiDB.java @@ -8,8 +8,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import static moe.oko.Kiafumi.Kiafumi.error; -import static moe.oko.Kiafumi.Kiafumi.info; +import static moe.oko.Kiafumi.Kiafumi.*; /** * Kiafumi DB Class @@ -126,7 +125,7 @@ public class KiafumiDB { } String modRole = rs.getString(6); Server server = new Server(id, welcomeEnabled, welcomeChannel, joinRole, protectionEnabled, modRole); - info("Loaded: " + server); + debug("Loaded " + server + "from database."); servers.add(server); } return servers; diff --git a/src/main/java/moe/oko/Kiafumi/model/ServerManager.java b/src/main/java/moe/oko/Kiafumi/model/ServerManager.java index 1a04f37..b12a9bd 100644 --- a/src/main/java/moe/oko/Kiafumi/model/ServerManager.java +++ b/src/main/java/moe/oko/Kiafumi/model/ServerManager.java @@ -7,8 +7,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.List; -import static moe.oko.Kiafumi.Kiafumi.error; -import static moe.oko.Kiafumi.Kiafumi.info; +import static moe.oko.Kiafumi.Kiafumi.*; /** * ServerManager Class @@ -30,7 +29,6 @@ public class ServerManager { } HashMap serverHashMap = new HashMap<>(); for(Server s : loadedServers) { - info("Loading " + s + " into memory from db."); serverHashMap.put(s.getId(), s); } info("Successfully loaded " + serverHashMap.size() + " servers."); @@ -63,16 +61,15 @@ public class ServerManager { * @return - whether the function succeeded. */ public boolean createNewDefaultServer(Guild guild) { - info("Started default server creation for server " + guild.getId()); + var serverName = guild.getName() + ":" + guild.getId() + "]."; + debug("Creating data for [" + serverName); Server server = new Server(guild.getId()); - if(Kiafumi.instance.getDatabase().createServerInformation(guild)) { - info("New defaults persistent for " + server); - servers.put(server.getId(), server); - return true; - } else { + if(!Kiafumi.instance.getDatabase().createServerInformation(guild)) { error("Failed to create new defaults for " + guild.getId()); return false; } + servers.put(server.getId(), server); + return true; } /** diff --git a/src/main/java/moe/oko/Kiafumi/util/EmbedUI.java b/src/main/java/moe/oko/Kiafumi/util/EmbedUI.java index 9d50d99..ee1a997 100644 --- a/src/main/java/moe/oko/Kiafumi/util/EmbedUI.java +++ b/src/main/java/moe/oko/Kiafumi/util/EmbedUI.java @@ -7,6 +7,7 @@ import java.awt.Color; * @author oko */ public abstract class EmbedUI { + // TODO: restructure & rename class - it has surpassed its scope. /** * Shorthand reference for common EmbedBuilder colors & strings. * I chose these colors based on the Pantone Color of the year. @@ -14,6 +15,7 @@ public abstract class EmbedUI { // Strings public static final String BRAND = "Kiafumi - oko.moe"; + public static final String RESPONSE_PRIVILEGES = " Insufficient privileges."; // Colors public static final Color SUCCESS = new Color(136,176,75); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index ee78c8d..dbf28ce 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -10,7 +10,7 @@ #DISCORD CONFIG STACK discord: #Paste in your bot token here. - token: "DO NOT SHARE THIS" + token: "DO NOT SHARE" #The main guild the bot will recognize and do protection actions on. (Use LossPrevention for more in-depth actions!) mainGuild: "" #The channel ID the bot will send important logging messages to. @@ -19,8 +19,9 @@ discord: ownerId: "" #The client ID of the bot (for invite generation) clientId: "" - #Level of permissions for the invite (If you don't know this, use https://discordapi.com/permissions.html) (ADMINISTRATOR is default) - invitePermissionLevel: 8 + #Level of permissions for the invite (If you don't know this, use https://discordapi.com/permissions.html) + #If problems occur, you can use 8 (Administrator) + invitePermissionLevel: 139855252544 #MAIN CONFIG STACK main: #Currently, unimplemented, maybe in the future if performance becomes and issue. diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml new file mode 100644 index 0000000..6d9d590 --- /dev/null +++ b/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + %d{HH:mm} %highlight{%-5level} %cyan{%logger{7}} - %m%n + + + + + + + + + + + + + + \ No newline at end of file