From 7dcee59e43a641585c60241fa03e5cce04445195 Mon Sep 17 00:00:00 2001 From: ChomeNS Date: Tue, 28 Mar 2023 17:25:58 +0700 Subject: [PATCH] skidded greplogs --- .../chipmunk/chayapak/chomens_bot/Bot.java | 3 + .../chipmunk/chayapak/chomens_bot/Logger.java | 2 +- .../chomens_bot/commands/GrepLogCommand.java | 69 +++++++ .../plugins/CommandHandlerPlugin.java | 1 + .../chomens_bot/plugins/DiscordPlugin.java | 2 + .../chomens_bot/plugins/GrepLogPlugin.java | 168 ++++++++++++++++++ 6 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 src/main/java/land/chipmunk/chayapak/chomens_bot/commands/GrepLogCommand.java create mode 100644 src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/GrepLogPlugin.java diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/Bot.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/Bot.java index c681e33..ec46191 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/Bot.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/Bot.java @@ -36,6 +36,7 @@ public class Bot { @Getter @Setter private ConsolePlugin console; @Getter @Setter private LoggerPlugin logger; // in ConsolePlugin + @Getter @Setter private DiscordPlugin discord; @Getter private final ChatPlugin chat; @Getter private final SelfCarePlugin selfCare; @Getter private final PositionPlugin position; @@ -51,6 +52,7 @@ public class Bot { @Getter private final ClearChatUsernamePlugin clearChatUsername; @Getter private final TrustedPlugin trusted; @Getter private final BruhifyPlugin bruhify; + @Getter private final GrepLogPlugin grepLog; public Bot (String host, int port, String _username, boolean kaboom, String serverName, List allBots, Configuration config) { this.host = host; @@ -80,6 +82,7 @@ public class Bot { this.clearChatUsername = new ClearChatUsernamePlugin(this); this.trusted = new TrustedPlugin(this); this.bruhify = new BruhifyPlugin(this); + this.grepLog = new GrepLogPlugin(this); reconnect(); } diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/Logger.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/Logger.java index b0c3ae7..e31ab46 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/Logger.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/Logger.java @@ -84,7 +84,7 @@ public class Logger { } public static synchronized void compressLogFile() throws IOException { - if (Files.size(logFile.toPath()) > 100*1024*1024) { // Will not save because log file is too big + if (Files.size(logFile.toPath()) > 100 * 1024 * 1024) { // Will not save because log file is too big return; } diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/commands/GrepLogCommand.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/commands/GrepLogCommand.java new file mode 100644 index 0000000..824be3e --- /dev/null +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/commands/GrepLogCommand.java @@ -0,0 +1,69 @@ +package land.chipmunk.chayapak.chomens_bot.commands; + +import land.chipmunk.chayapak.chomens_bot.Bot; +import land.chipmunk.chayapak.chomens_bot.command.Command; +import land.chipmunk.chayapak.chomens_bot.command.CommandContext; +import net.kyori.adventure.text.Component; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class GrepLogCommand implements Command { + public String name() { return "greplog"; } + + public String description() { + return "Queries the bot's log files"; + } + + public List usage() { + final List usages = new ArrayList<>(); + usages.add("<{input}>"); + usages.add("-ignorecase <{input}>"); + usages.add("-regex <{input}>"); + usages.add("-ignorecase -regex <{input}>"); + usages.add("stop"); + + return usages; + } + + public List alias() { + final List aliases = new ArrayList<>(); + aliases.add("logquery"); + aliases.add("greplogs"); + + return aliases; + } + + public int trustLevel() { + return 0; + } + + public Component execute(CommandContext context, String[] _args, String[] fullArgs) { + final Bot bot = context.bot(); + + String[] args = _args; + + boolean ignoreCase = false; + boolean regex = false; + + switch (_args[0]) { + case "-ignorecase" -> { + ignoreCase = true; + args = Arrays.copyOfRange(_args, 1, _args.length); + } + case "-regex" -> { + regex = true; + args = Arrays.copyOfRange(_args, 1, _args.length); + } + case "stop" -> { + bot.grepLog().thread().interrupt(); + return Component.text("success"); + } + } + + bot.grepLog().query(String.join(" ", args), regex, ignoreCase); + + return Component.text("success"); + } +} diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/CommandHandlerPlugin.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/CommandHandlerPlugin.java index 18549da..b56464e 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/CommandHandlerPlugin.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/CommandHandlerPlugin.java @@ -43,6 +43,7 @@ public class CommandHandlerPlugin { registerCommand(new UUIDCommand()); registerCommand(new TimeCommand()); registerCommand(new BruhifyCommand()); + registerCommand(new GrepLogCommand()); } public void registerCommand (Command command) { diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java index d29850f..b8728bf 100644 --- a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/DiscordPlugin.java @@ -69,6 +69,8 @@ public class DiscordPlugin { for (Bot bot : Main.allBots) { String channelId = servers.get(bot.host() + ":" + bot.port()); + bot.discord(this); + bot.addListener(new SessionAdapter() { @Override public void connected(ConnectedEvent event) { diff --git a/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/GrepLogPlugin.java b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/GrepLogPlugin.java new file mode 100644 index 0000000..951b3d9 --- /dev/null +++ b/src/main/java/land/chipmunk/chayapak/chomens_bot/plugins/GrepLogPlugin.java @@ -0,0 +1,168 @@ +package land.chipmunk.chayapak.chomens_bot.plugins; + +import land.chipmunk.chayapak.chomens_bot.Bot; +import land.chipmunk.chayapak.chomens_bot.Logger; +import lombok.Getter; +import net.dv8tion.jda.api.entities.TextChannel; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; + +import java.io.*; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; + +public class GrepLogPlugin { + private final Bot bot; + + @Getter private GrepLogThread thread = null; + + public GrepLogPlugin (Bot bot) { + this.bot = bot; + } + + public void query (String query, boolean regex, boolean ignoreCase) { + thread = new GrepLogThread(query, regex, ignoreCase); + thread.start(); + } + + // should i move this to another file or keep it here + public class GrepLogThread extends Thread { + private String query; + private final boolean regex; + private final boolean ignoreCase; + + private Pattern pattern; + + private boolean queryStopped = false; + + private int matches = 0; + private final StringBuilder results = new StringBuilder(); + + public GrepLogThread(String query, boolean regex, boolean ignoreCase) { + this.regex = regex; + this.ignoreCase = ignoreCase; + + this.query = query; + + if (regex) { + if (ignoreCase) { + pattern = Pattern.compile(query, Pattern.CASE_INSENSITIVE); + } + else { + pattern = Pattern.compile(query); + } + } else { + if (ignoreCase) { + this.query = query.toLowerCase(); + } + } + } + + @Override + public void run() { + bot.chat().tellraw( + Component.translatable( + "Collecting %s in logs...", + Component.text(query).color(NamedTextColor.GOLD) + ) + ); + + final File[] fileList = Logger.logDir.listFiles(); + + for (File file : fileList) { + final String fileName = file.getName(); + if (fileName.matches(".*\\.txt\\.gz")) { + try ( + FileInputStream fin = new FileInputStream(file); + GZIPInputStream gzin = new GZIPInputStream(fin, 65536); + BufferedReader br = new BufferedReader(new InputStreamReader(gzin, StandardCharsets.UTF_8)) + ) { + br.readLine(); + readFile(br); + } catch (Exception ignored) { + } // TODO: Handle exception + } else { + try ( + FileInputStream fin = new FileInputStream(file); + BufferedReader br = new BufferedReader(new InputStreamReader(fin, StandardCharsets.UTF_8)) + ) { + br.readLine(); + readFile(br); + } catch (Exception ignored) { + } // TODO: Handle exception + } + + if (Thread.interrupted()) { + bot.chat().tellraw(Component.text("Log query stopped")); + } else if (queryStopped) { + break; + } + } + + finish(); + } + + private void readFile(BufferedReader br) { + String line; + try { + while ((line = br.readLine()) != null) { + if (line.length() == 0) continue; + + String[] tokens = line.split("\\s+"); + if (tokens.length < 3) continue; // not a valid log message + + processLine(line); + } + } catch (IOException ignored) {} + } + + private void processLine(String _line) { + // [day/month/year hh:mm:ss] [server:port] message + String[] tokens = _line.split("\\s+"); + final String line = String.join(" ", Arrays.copyOfRange(tokens, 3, tokens.length)); // very 1 liner + + if (regex) { + if (pattern.matcher(line).find()) { + match(_line); + } + } else { + if (ignoreCase) { + if (line.toLowerCase().contains(query)) { + match(_line); + } + } else { + if (line.contains(query)) { + match(_line); + } + } + } + } + + private void match (String line) { + results.append(line); + results.append("\n"); + + matches++; + + int resultsLimit = 1_000_000; + if (results.length() > resultsLimit) { + queryStopped = true; + } + } + + private void finish () { + bot.chat().tellraw( + Component.translatable( + "Log query finished, found %s matches. Results were sent in Discord", + Component.text(matches).color(NamedTextColor.AQUA) + ) + ); + + final String channelId = bot.discord().servers.get(bot.host() + ":" + bot.port()); + final TextChannel logChannel = bot.discord().jda().getTextChannelById(channelId); + logChannel.sendMessage("Log query output").addFile(results.toString().getBytes(), "report.txt").queue(); + } + } +}