Completely overhaul logging

Now uses log4j2 as the default logger.
The output is now colorized and better organized.
The text is also much more readable.

This commit also attempts to fix the /skip issue.
This commit is contained in:
Anya 2022-05-17 14:48:47 -07:00
parent 9ae1db1b80
commit 35512486ad
14 changed files with 102 additions and 74 deletions

27
pom.xml
View file

@ -33,12 +33,22 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.9</version>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.17.2</version>
</dependency>
<dependency>
<groupId>com.sedmelluq</groupId>
@ -48,7 +58,7 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
<version>8.0.29</version>
</dependency>
<!-- DDG api (https://github.com/nstrydom2/duckduckgo-api) -->
<dependency>
@ -60,7 +70,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
<version>31.1-jre</version>
</dependency>
</dependencies>
@ -78,6 +88,11 @@
<name>bintray</name>
<url>https://jcenter.bintray.com</url>
</repository>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
<build>

View file

@ -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.

View file

@ -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;
}

View file

@ -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<CommandClass> 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;
}
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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)

View file

@ -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<CommandInfo> 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);

View file

@ -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+
"--------------------------------");
}
/**

View file

@ -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;

View file

@ -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<String, Server> 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;
}
/**

View file

@ -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);

View file

@ -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.

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN" monitorInterval="30">
<Properties>
<Property name="LOG_PATTERN">%d{HH:mm} %highlight{%-5level} %cyan{%logger{7}} - %m%n</Property>
</Properties>
<Appenders>
<Console name="console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_PATTERN}"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="console"/>
</Root>
</Loggers>
</Configuration>