summaryrefslogtreecommitdiff
path: root/src/main/java/com/redstoner/modules/logs
diff options
context:
space:
mode:
authorDavid <david@panic.tk>2018-11-07 23:50:06 +0100
committerDavid <david@panic.tk>2018-11-07 23:50:06 +0100
commit604cf01967ede98bf5024e4926bb0777fc4e8eee (patch)
treee2fa63d7e683769ee3bf3eddc75280648e92eb04 /src/main/java/com/redstoner/modules/logs
parente86c52ef7c0e1e33c6af0e8674b038976bec11cc (diff)
Converted Modules to gradle
Diffstat (limited to 'src/main/java/com/redstoner/modules/logs')
-rw-r--r--src/main/java/com/redstoner/modules/logs/LogEntry.java71
-rw-r--r--src/main/java/com/redstoner/modules/logs/LogHandler.java200
-rw-r--r--src/main/java/com/redstoner/modules/logs/Logs.cmd34
-rw-r--r--src/main/java/com/redstoner/modules/logs/Logs.java157
4 files changed, 462 insertions, 0 deletions
diff --git a/src/main/java/com/redstoner/modules/logs/LogEntry.java b/src/main/java/com/redstoner/modules/logs/LogEntry.java
new file mode 100644
index 0000000..3ccc844
--- /dev/null
+++ b/src/main/java/com/redstoner/modules/logs/LogEntry.java
@@ -0,0 +1,71 @@
+package com.redstoner.modules.logs;
+
+public class LogEntry
+{
+ public final int line;
+ public final int global_line;
+ public final String filename;
+ public final String raw;
+
+ public LogEntry(String raw, int line, int global_line)
+ {
+ this("Unkown", raw, line, global_line);
+ }
+
+ public LogEntry(String filename, String raw, int line, int global_line)
+ {
+ this.raw = resolveColors(raw);
+ this.line = line;
+ this.global_line = global_line;
+ this.filename = filename;
+ }
+
+ public String applyFormat(String format, boolean colors)
+ {
+ // Replace escaped % with placeholder
+ format = format.replace("%%", "§§");
+ // Line numbers
+ format = format.replace("%l", "" + line);
+ format = format.replace("%L", "" + global_line);
+ // Filename
+ format = format.replace("%f", filename);
+ // Strip colors
+ if (!colors)
+ format = format.replace("%r", raw.replaceAll("$.", ""));
+ else
+ format = format.replace("%r", raw);
+ // Convert placeholder back
+ format = format.replace("§§", "%");
+ return format;
+ }
+
+ private String resolveColors(String message)
+ {
+ message = message.replace("", "§0");
+ message = message.replace("", "§1");
+ message = message.replace("", "§2");
+ message = message.replace("", "§3");
+ message = message.replace("", "§4");
+ message = message.replace("", "§5");
+ message = message.replace("", "§6");
+ message = message.replace("", "§7");
+ message = message.replace("", "§8");
+ message = message.replace("", "§9");
+ message = message.replace("", "§a");
+ message = message.replace("", "§b");
+ message = message.replace("", "§c");
+ message = message.replace("", "§d");
+ message = message.replace("", "§e");
+ message = message.replace("", "§f");
+
+ message = message.replace("", "§k");
+ message = message.replace("", "§l");
+ message = message.replace("", "§m");
+ message = message.replace("", "§n");
+ message = message.replace("", "§o");
+
+ message = message.replace("", "§r");
+
+ return message;
+ }
+}
diff --git a/src/main/java/com/redstoner/modules/logs/LogHandler.java b/src/main/java/com/redstoner/modules/logs/LogHandler.java
new file mode 100644
index 0000000..76f3849
--- /dev/null
+++ b/src/main/java/com/redstoner/modules/logs/LogHandler.java
@@ -0,0 +1,200 @@
+package com.redstoner.modules.logs;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+import java.util.zip.GZIPInputStream;
+
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.redstoner.misc.Utils;
+import com.redstoner.modules.datamanager.DataManager;
+
+public class LogHandler extends Thread
+{
+ private CommandSender sender;
+ private String regex, fileName;
+ private static ArrayList<CommandSender> stillSearching = new ArrayList<>();
+ public int totalFiles = 0;
+ public int filesSearched = 0;
+ public int totalLines = 0;
+ public int currentLine = 0;
+
+ protected LogHandler(CommandSender sender, String regex, String fileName)
+ {
+ this.sender = sender;
+ this.regex = regex;
+ this.fileName = fileName;
+ }
+
+ public void doSearch()
+ {
+ if (stillSearching.contains(sender))
+ {
+ Logs.logger.message(sender, true, "§4 DO NOT EVER TRY TO QUERY TWO SEARCHES AT ONCE. Go die...!");
+ return;
+ }
+ stillSearching.add(sender);
+ this.start();
+ }
+
+ /** Searches the logs for a certain regex and forwards any matches to the sender.
+ *
+ * @param sender the issuer of the search
+ * @param regex the regex to search for. Will be wrapped in "^.*" and ".*$" if it is missing line delimiters
+ * @param fileName the name of the files to search through. May contain wildcards. */
+ private void search(CommandSender sender, String regex, String fileName)
+ {
+ long starttime = System.currentTimeMillis();
+ int matches = 0;
+ Logs.logger.message(sender, "Starting log search for &e" + regex + "&7 in &e" + fileName
+ + " &7now. &cPlease do not query any other searches until this one completes.");
+ try
+ {
+ if (!regex.startsWith("^"))
+ regex = "^.*" + regex;
+ if (!regex.endsWith("$"))
+ regex += ".*$";
+ File logFolder = Logs.getLogsDir();
+ Pattern fileNamePattern;
+ try
+ {
+ fileNamePattern = Pattern.compile(fileName);
+ }
+ catch (PatternSyntaxException e)
+ {
+ Logs.logger.message(sender, true, "An error occured trying to compile the filename pattern!");
+ stillSearching.remove(sender);
+ return;
+ }
+ File[] files = logFolder.listFiles(new FilenameFilter()
+ {
+ @Override
+ public boolean accept(File dir, String name)
+ {
+ return fileNamePattern.matcher(name).matches();
+ }
+ });
+ totalFiles = files.length;
+ if (totalFiles == 0)
+ {
+ Logs.logger.message(sender, true, "No files found!");
+ stillSearching.remove(sender);
+ return;
+ }
+ else
+ Logs.logger.message(sender, "A total of &e" + totalFiles + "&7 files will be searched!");
+
+ boolean progress = (boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "progress", true);
+ Pattern searchPattern;
+ try
+ {
+ searchPattern = Pattern.compile(regex);
+ }
+ catch (PatternSyntaxException e)
+ {
+ Logs.logger.message(sender, true, "An error occured trying to compile the search pattern!");
+ stillSearching.remove(sender);
+ return;
+ }
+ for (File file : files)
+ {
+ if (file.getName().endsWith(".gz"))
+ {
+
+ BufferedReader inputReader = new BufferedReader(
+ new InputStreamReader(new GZIPInputStream(new FileInputStream(file))));
+ matches += searchStream(inputReader, searchPattern, sender, file.getName());
+ inputReader.close();
+ }
+ else
+ {
+ BufferedReader inputReader = new BufferedReader(new FileReader(file));
+ matches += searchStream(inputReader, searchPattern, sender, file.getName());
+ inputReader.close();
+ }
+ filesSearched++;
+ if (progress)
+ {
+ sender.sendMessage("§7So far, §e" + filesSearched + "§7/§e" + totalFiles + "§7 File(s) and §e"
+ + totalLines + "§7 Line(s) were searched.");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logs.logger.message(sender, true,
+ "An unexpected error occured, please check your search parameters and try again!");
+ stillSearching.remove(sender);
+ return;
+ }
+ stillSearching.remove(sender);
+ if ((boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "summary", true))
+ {
+ String[] message = new String[2];
+ message[0] = "§aYour search completed after " + (System.currentTimeMillis() - starttime) + "ms!";
+ message[1] = "§7In total: §e" + filesSearched + "§7 File(s) and §e" + totalLines
+ + "§7 Line(s) were searched, §a" + matches + "§7 Match(es) were found!";
+ Logs.logger.message(sender, message);
+ }
+ return;
+ }
+
+ /** This function searches through an InputStream to find a regex. If it finds a match, it will forward that match to the sender and increase the match counter.
+ *
+ * @param inputReader the input reader containing the data
+ * @param regex the regex to search for
+ * @param sender the issuer of the search
+ * @param singleFile true if only a single file is being searched, false if the original filename contained wildcards.
+ * @param filename the name of the file that is currently being searched
+ * @return how many matches it found
+ * @throws IOException if something goes wrong */
+ private int searchStream(BufferedReader inputReader, Pattern searchPattern, CommandSender sender, String filename)
+ throws IOException
+ {
+ String format = (String) DataManager.getOrDefault(Utils.getID(sender), "Logs", "format", Logs.defaultFormat);
+ boolean colors = (boolean) DataManager.getOrDefault(Utils.getID(sender), "Logs", "colors", true);
+ Player p = null;
+ if (sender instanceof Player)
+ p = (Player) sender;
+ int matches = 0;
+ String line = "";
+ currentLine = 0;
+ while ((line = inputReader.readLine()) != null)
+ {
+ totalLines++;
+ currentLine++;
+ if (searchPattern.matcher(line).matches())
+ {
+ if (((p != null) && (!p.isOnline())))
+ {
+ stillSearching.remove(sender);
+ throw new IOException("The player has left during the search. Aborting now.");
+ }
+ LogEntry entry = new LogEntry(filename, line, currentLine, totalLines);
+ sender.sendMessage(entry.applyFormat(format, colors));
+ matches++;
+ }
+ }
+ return matches;
+ }
+
+ @Override
+ public void run()
+ {
+ try
+ {
+ search(sender, regex, fileName);
+ }
+ catch (Exception e)
+ {}
+ }
+}
diff --git a/src/main/java/com/redstoner/modules/logs/Logs.cmd b/src/main/java/com/redstoner/modules/logs/Logs.cmd
new file mode 100644
index 0000000..c5283fe
--- /dev/null
+++ b/src/main/java/com/redstoner/modules/logs/Logs.cmd
@@ -0,0 +1,34 @@
+command log {
+ perm utils.logs;
+ alias logs;
+ search [string:file(s)] [string:search...] {
+ run search_logs file(s) search;
+ help Performs the specified search operation on the logs. Wildcards are supported in filenames. Search string is a regex.;
+ type player;
+ }
+ format {
+ run show_format;
+ help Displays your current log output format with an example result.;
+ type player;
+ }
+ format_help {
+ run show_format_help;
+ help Displays all available placeholders for the formatting;
+ type player;
+ }
+ option_help {
+ run show_option_help;
+ help Displays all available options.;
+ type player;
+ }
+ set format [string:format] {
+ run set_format format;
+ help Sets a new log output format;
+ type player;
+ }
+ set [string:option] [boolean:state] {
+ run set_option option state;
+ help Allows you to enable or disable various features such as sumamries, live progress updates, etc...;
+ type player;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/redstoner/modules/logs/Logs.java b/src/main/java/com/redstoner/modules/logs/Logs.java
new file mode 100644
index 0000000..b54bfc9
--- /dev/null
+++ b/src/main/java/com/redstoner/modules/logs/Logs.java
@@ -0,0 +1,157 @@
+package com.redstoner.modules.logs;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bukkit.command.CommandSender;
+
+import com.nemez.cmdmgr.Command;
+import com.redstoner.annotations.Commands;
+import com.redstoner.annotations.Version;
+import com.redstoner.misc.CommandHolderType;
+import com.redstoner.modules.Module;
+import com.redstoner.modules.ModuleLogger;
+import com.redstoner.modules.datamanager.DataManager;
+
+@Commands(CommandHolderType.File)
+@Version(major = 4, minor = 0, revision = 4, compatible = 4)
+public class Logs implements Module
+{
+ public static final String defaultFormat = "§7 > %f: %r";
+ private final LogEntry example_1 = new LogEntry("1970-01-01-2.log.gz",
+ "[01:23:45] [Async Chat Thread - #1337/INFO]: §aFooBar §7→ §4THIS SERVER SUCKS", 14, 73);
+ private final LogEntry example_2 = new LogEntry("1970-01-01-2.log.gz",
+ "[01:23:45] [Server thread/INFO]: admin issued server command: /ban FooBar Ab00se", 15, 74);
+ protected static ModuleLogger logger;
+
+ @Override
+ public void firstLoad()
+ {
+ Module.super.firstLoad();
+ DataManager.setConfig("logs.root", "/etc/minecraft/redstoner/logs");
+ }
+
+ @Override
+ public boolean onEnable()
+ {
+ Module.super.onEnable();
+ logger = getLogger();
+ return true;
+ }
+
+ public static File getLogsDir()
+ {
+ return new File((String) DataManager.getConfigOrDefault("logs.root", "../logs"));
+ }
+
+ @Command(hook = "search_logs")
+ public boolean search_logs(CommandSender sender, String files, String search)
+ {
+ LogHandler handler = new LogHandler(sender, search, files);
+ handler.doSearch();
+ return true;
+ }
+
+ // FORMATTING
+ @Command(hook = "show_format")
+ public boolean show_format(CommandSender sender)
+ {
+ showExample(sender);
+ return true;
+ }
+
+ @Command(hook = "set_format")
+ public boolean set_format(CommandSender sender, String format)
+ {
+ if (format.equals("--reset"))
+ format = defaultFormat;
+ format = format.replace("&", "§").replace("$$", "&");
+ DataManager.setData(sender, "format", format);
+ showExample(sender, format);
+ return true;
+ }
+
+ private void showExample(CommandSender sender)
+ {
+ showExample(sender, (String) DataManager.getOrDefault(sender, "format", defaultFormat));
+ }
+
+ private void showExample(CommandSender sender, String format)
+ {
+ sender.sendMessage(getLogger().getHeader());
+ sender.sendMessage("Your format is: " + format);
+ sender.sendMessage("Here's an example of what it would look like in an actual log search:");
+ boolean colors = (boolean) DataManager.getOrDefault(sender, "colors", true);
+ if ((boolean) DataManager.getOrDefault(sender, "progress", true))
+ {
+ sender.sendMessage("§7So far, §e1§7/§e2§7 File(s) and §e68§7 Line(s) were searched.");
+ }
+ sender.sendMessage(example_1.applyFormat(format, colors));
+ sender.sendMessage(example_2.applyFormat(format, colors));
+ if ((boolean) DataManager.getOrDefault(sender, "summary", true))
+ {
+ sender.sendMessage("§aSearch completed after 39ms!");
+ sender.sendMessage(
+ "§7In total: §e2§7 File(s) and §e105§7 Line(s) were searched, §a2§7 Match(es) were found!");
+ }
+ }
+
+ @Command(hook = "show_format_help")
+ public boolean format_help(CommandSender sender)
+ {
+ //@noformat
+ String[] format_help = new String[] {
+ " &e%l&cine&7 -> Linenumber in the current file",
+ " &e%L&cine&7 -> Global linenumber (sum of all previous files + current line)",
+ " &e%f&cile&7 -> Complete filename",
+ " &e%r&caw&7 -> The raw line containing the text as it appears in the logs",
+ "",
+ " &7Use %% to gain a literal %."};
+ //@format
+ getLogger().message(sender, format_help);
+ return true;
+ }
+
+ // SEARCH OPTIONS
+ @Command(hook = "show_option_help")
+ public boolean show_options(CommandSender sender)
+ {
+ List<String> options = new ArrayList<>(Option.values().length + 1);
+ options.add("Available options are:");
+ for (Option o : Option.values())
+ options.add(" - " + o.toString());
+ getLogger().message(sender, options.toArray(new String[] {}));
+ return true;
+ }
+
+ @Command(hook = "set_option")
+ public boolean set_option(CommandSender sender, String option, boolean state)
+ {
+ option = option.toLowerCase();
+ Option o = null;
+ try
+ {
+ o = Option.valueOf(option);
+ }
+ catch (IllegalArgumentException e)
+ {}
+ if (o == null)
+ {
+ getLogger().message(sender, true,
+ "Invalid option! To get a list of all available options, run &e/logs option_help");
+ return true;
+ }
+ DataManager.setData(sender, option, state);
+ getLogger().message(sender,
+ "Successfully turned displaying of &e" + option + (state ? " &aon&7!" : " &coff&7!"));
+ return true;
+ }
+}
+
+enum Option
+{
+ summary,
+ progress,
+ colors
+}