diff --git a/src/main/java/land/chipmunk/chipmunkbot/commands/LogQueryCommand.java b/src/main/java/land/chipmunk/chipmunkbot/commands/LogQueryCommand.java index da4b9e0..36042a4 100644 --- a/src/main/java/land/chipmunk/chipmunkbot/commands/LogQueryCommand.java +++ b/src/main/java/land/chipmunk/chipmunkbot/commands/LogQueryCommand.java @@ -20,14 +20,15 @@ import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Scanner; +import java.util.Arrays; import java.util.function.Predicate; import java.util.zip.GZIPInputStream; public class LogQueryCommand { - private Thread thread; + private LogQueryThread thread; private static SimpleCommandExceptionType ALREADY_QUERYING_LOGS_EXCEPTION = new SimpleCommandExceptionType(ComponentMessage.wrap(Component.translatable("Another log query is already running"))); - private static SimpleCommandExceptionType ALREADY_NOT_QUERYING_LOGS_EXCEPTION = new SimpleCommandExceptionType(ComponentMessage.wrap(Component.translatable("No log query is currently running"))); + private static SimpleCommandExceptionType NOT_QUERYING_LOGS_EXCEPTION = new SimpleCommandExceptionType(ComponentMessage.wrap(Component.translatable("No log query is currently running"))); public static void register (CommandDispatcher dispatcher) { final LogQueryCommand instance = new LogQueryCommand(); @@ -36,7 +37,7 @@ public class LogQueryCommand { literal("logquery") .then( literal("abort") - // .executes(this::abortCommand) + .executes(instance::abortCommand) ) .then( literal("count") @@ -52,6 +53,10 @@ public class LogQueryCommand { // .executes(instance::reportCommand) ) ) + .then( + literal("progress") + .executes(instance::progressCommand) + ) ); } @@ -67,10 +72,14 @@ public class LogQueryCommand { throw ALREADY_QUERYING_LOGS_EXCEPTION.create(); } - /* public int abortCommand (CommandContext context) throws CommandSyntaxException { - if (!querying()) throw ALREADY_NOT_QUERYING_LOGS_EXCEPTION.create(); - - } */ + public int abortCommand (CommandContext context) throws CommandSyntaxException { + if (!querying()) throw NOT_QUERYING_LOGS_EXCEPTION.create(); + + thread.breakQuery(); + context.getSource().sendOutput(Component.translatable("Stopped querying logs")); + + return Command.SINGLE_SUCCESS; + } public int countCommand (CommandContext context) throws CommandSyntaxException { alreadyQueryingCheck(); @@ -87,24 +96,43 @@ public class LogQueryCommand { return Command.SINGLE_SUCCESS; } - @AllArgsConstructor - public static class CountThread extends Thread { + public int progressCommand (CommandContext context) { + final Component progress = Component.translatable( + "Currently reading %s (%s/%s)", + Component.text(thread.currentFilename, NamedTextColor.GREEN), + Component.text(thread.currentIndex + 1), + Component.text(thread.totalFiles) + ); + + context.getSource().sendOutput(progress, false); + return Command.SINGLE_SUCCESS; + } + + public static abstract class LogQueryThread extends Thread { public Predicate query; public File directory; - public CommandSource source; + + public String currentFilename = null; + public int currentIndex = 0; + public int totalFiles; + + private boolean breakFlag; public void run () { - int instances = 0; - final long startTime = System.currentTimeMillis(); + breakFlag = false; - final String[] filenames = directory.list(); + String[] filenames = directory.list(); + if (filenames == null) return; + Arrays.sort(filenames); + totalFiles = filenames.length; - if (filenames == null) { - source.sendOutput(Component.translatable("Unable to query the bot's logs, as the directory does not exist", NamedTextColor.RED)); - return; - } + onStart(); for (String filename : filenames) { + currentFilename = filename; + + if (breakFlag) return; + try { InputStream is = new FileInputStream(new File(directory, filename)); if (filename.endsWith(".log.gz")) is = new GZIPInputStream(is); @@ -113,16 +141,50 @@ public class LogQueryCommand { final Scanner scanner = new Scanner(is, StandardCharsets.UTF_8); while (scanner.hasNextLine()) { - if (!query.test(scanner.nextLine())) continue; - instances++; + final String line = scanner.nextLine(); + if (!query.test(line)) continue; + onMatch(line); } scanner.close(); } catch (Exception exception) { exception.printStackTrace(); } - } + currentIndex++; + } + } + + public void breakQuery () { + breakFlag = true; + } + + public void onStart () {} + public void onFinish () {} + abstract void onMatch (String line); + } + + @AllArgsConstructor + public static class CountThread extends LogQueryThread { + public int instances = 0; + public long startTime; + public CommandSource source; + + public CountThread (Predicate query, File directory, CommandSource source) { + this.query = query; + this.directory = directory; + this.source = source; + } + + public void onStart () { + startTime = System.currentTimeMillis(); + } + + public void onMatch (String line) { + instances++; + } + + public void onFinish () { double seconds = (double) (System.currentTimeMillis() - startTime) / 1000d; source.sendOutput(Component.translatable("Found %s instances of the specified query in %s seconds", Component.text(instances, NamedTextColor.GREEN), Component.text(seconds, NamedTextColor.GREEN))); }