Compare commits
No commits in common. "41e57d04f22aa4e752d53d81f18f3bc1c6327292" and "e56fc19ab3cbb344edfcf8846a56151ddecc4c98" have entirely different histories.
41e57d04f2
...
e56fc19ab3
6 changed files with 18 additions and 327 deletions
|
@ -69,7 +69,6 @@ public class Bot {
|
||||||
public TPSPlugin tps;
|
public TPSPlugin tps;
|
||||||
public EvalPlugin eval;
|
public EvalPlugin eval;
|
||||||
public TrustedPlugin trusted;
|
public TrustedPlugin trusted;
|
||||||
public GrepLogPlugin grepLog;
|
|
||||||
public BruhifyPlugin bruhify;
|
public BruhifyPlugin bruhify;
|
||||||
public CloopPlugin cloop;
|
public CloopPlugin cloop;
|
||||||
public ExploitsPlugin exploits;
|
public ExploitsPlugin exploits;
|
||||||
|
@ -124,7 +123,6 @@ public class Bot {
|
||||||
this.tps = new TPSPlugin(this);
|
this.tps = new TPSPlugin(this);
|
||||||
this.eval = new EvalPlugin(this);
|
this.eval = new EvalPlugin(this);
|
||||||
this.trusted = new TrustedPlugin(this);
|
this.trusted = new TrustedPlugin(this);
|
||||||
this.grepLog = new GrepLogPlugin(this);
|
|
||||||
this.bruhify = new BruhifyPlugin(this);
|
this.bruhify = new BruhifyPlugin(this);
|
||||||
this.cloop = new CloopPlugin(this);
|
this.cloop = new CloopPlugin(this);
|
||||||
this.exploits = new ExploitsPlugin(this);
|
this.exploits = new ExploitsPlugin(this);
|
||||||
|
|
|
@ -47,15 +47,21 @@ public class FilterCommand extends Command {
|
||||||
|
|
||||||
String action = context.getString(false, true);
|
String action = context.getString(false, true);
|
||||||
|
|
||||||
// run 2 times. for example `*filter -ignorecase -regex add test` will be both accepted
|
// this is a mess
|
||||||
for (int i = 0; i < 2; i++) {
|
if (action.equals("-ignorecase")) {
|
||||||
if (action.equals("-ignorecase")) {
|
ignoreCase = true;
|
||||||
ignoreCase = true;
|
action = context.getString(false, true);
|
||||||
action = context.getString(false, true);
|
} else if (action.equals("-regex")) {
|
||||||
} else if (action.equals("-regex")) {
|
regex = true;
|
||||||
regex = true;
|
action = context.getString(false, true);
|
||||||
action = context.getString(false, true);
|
}
|
||||||
}
|
|
||||||
|
if (action.equals("-ignorecase")) {
|
||||||
|
ignoreCase = true;
|
||||||
|
action = context.getString(false, true);
|
||||||
|
} else if (action.equals("-regex")) {
|
||||||
|
regex = true;
|
||||||
|
action = context.getString(false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Gson gson = new Gson();
|
final Gson gson = new Gson();
|
||||||
|
@ -122,7 +128,9 @@ public class FilterCommand extends Command {
|
||||||
Component.join(JoinConfiguration.newlines(), filtersComponents)
|
Component.join(JoinConfiguration.newlines(), filtersComponents)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
default -> throw new CommandException(Component.text("Invalid action"));
|
default -> {
|
||||||
|
throw new CommandException(Component.text("Invalid action"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
package me.chayapak1.chomens_bot.commands;
|
|
||||||
|
|
||||||
import me.chayapak1.chomens_bot.Bot;
|
|
||||||
import me.chayapak1.chomens_bot.command.Command;
|
|
||||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
|
||||||
import me.chayapak1.chomens_bot.command.CommandException;
|
|
||||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
|
||||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
|
|
||||||
public class GrepLogCommand extends Command {
|
|
||||||
private Thread thread;
|
|
||||||
|
|
||||||
public GrepLogCommand() {
|
|
||||||
super(
|
|
||||||
"greplog",
|
|
||||||
"Queries the bot's logs",
|
|
||||||
new String[] { "<input>", "...-ignorecase...", "...-regex...", "stop" },
|
|
||||||
new String[] { "logquery", "findlog" },
|
|
||||||
TrustLevel.PUBLIC,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component execute(CommandContext context) throws CommandException {
|
|
||||||
final Bot bot = context.bot;
|
|
||||||
|
|
||||||
if (bot.discord.jda == null) throw new CommandException(Component.text("The bot's Discord integration has to be enabled to use the command."));
|
|
||||||
|
|
||||||
boolean ignoreCase = false;
|
|
||||||
boolean regex = false;
|
|
||||||
|
|
||||||
String firstInput = context.getString(false, true);
|
|
||||||
|
|
||||||
// run 2 times. for example `*greplog -ignorecase -regex test` will be both accepted
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
if (firstInput.equals("-ignorecase")) {
|
|
||||||
ignoreCase = true;
|
|
||||||
firstInput = context.getString(false, true);
|
|
||||||
} else if (firstInput.equals("-regex")) {
|
|
||||||
regex = true;
|
|
||||||
firstInput = context.getString(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// interesting code
|
|
||||||
final String input = (firstInput + " " + context.getString(true, false)).trim();
|
|
||||||
|
|
||||||
if (input.equals("stop")) {
|
|
||||||
if (thread == null) throw new CommandException(Component.text("There is no query process running"));
|
|
||||||
|
|
||||||
bot.grepLog.running = false;
|
|
||||||
|
|
||||||
thread.interrupt(); // ? should i interrupt it this way?
|
|
||||||
|
|
||||||
thread = null;
|
|
||||||
|
|
||||||
return Component.text("Stopped querying the logs").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (thread != null) throw new CommandException(Component.text("Another query is already running"));
|
|
||||||
|
|
||||||
context.sendOutput(
|
|
||||||
Component
|
|
||||||
.translatable("Started querying the logs for %s")
|
|
||||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
|
||||||
.arguments(
|
|
||||||
Component
|
|
||||||
.text(input)
|
|
||||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
final boolean finalIgnoreCase = ignoreCase;
|
|
||||||
final boolean finalRegex = regex;
|
|
||||||
|
|
||||||
thread = new Thread(() -> {
|
|
||||||
try {
|
|
||||||
bot.grepLog.search(context, input, finalIgnoreCase, finalRegex);
|
|
||||||
} catch (CommandException e) {
|
|
||||||
context.sendOutput(e.message.color(NamedTextColor.RED));
|
|
||||||
}
|
|
||||||
|
|
||||||
thread = null;
|
|
||||||
});
|
|
||||||
|
|
||||||
thread.start();
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -57,7 +57,6 @@ public class CommandHandlerPlugin {
|
||||||
registerCommand(new SeenCommand());
|
registerCommand(new SeenCommand());
|
||||||
registerCommand(new IPFilterCommand());
|
registerCommand(new IPFilterCommand());
|
||||||
registerCommand(new StopCommand());
|
registerCommand(new StopCommand());
|
||||||
registerCommand(new GrepLogCommand());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean disabled = false;
|
public boolean disabled = false;
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
package me.chayapak1.chomens_bot.plugins;
|
|
||||||
|
|
||||||
import me.chayapak1.chomens_bot.Bot;
|
|
||||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
|
||||||
import me.chayapak1.chomens_bot.command.CommandException;
|
|
||||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
|
||||||
import me.chayapak1.chomens_bot.util.FileLoggerUtilities;
|
|
||||||
import me.chayapak1.chomens_bot.util.StringUtilities;
|
|
||||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
|
||||||
import net.dv8tion.jda.api.utils.FileUpload;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.event.ClickEvent;
|
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.NotDirectoryException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
import java.util.regex.PatternSyntaxException;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import java.util.zip.GZIPInputStream;
|
|
||||||
|
|
||||||
public class GrepLogPlugin {
|
|
||||||
private final Bot bot;
|
|
||||||
|
|
||||||
private Pattern pattern;
|
|
||||||
|
|
||||||
private int count = 0;
|
|
||||||
|
|
||||||
public boolean running = false;
|
|
||||||
|
|
||||||
public GrepLogPlugin (Bot bot) {
|
|
||||||
this.bot = bot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void search (CommandContext context, String input, boolean ignoreCase, boolean regex) throws CommandException {
|
|
||||||
running = true;
|
|
||||||
|
|
||||||
try (final Stream<Path> files = Files.list(FileLoggerUtilities.logDirectory)) {
|
|
||||||
final Path[] fileList = files.toArray(Path[]::new);
|
|
||||||
|
|
||||||
Arrays.sort(fileList, Comparator.comparing(a -> a.getFileName().toString()));
|
|
||||||
|
|
||||||
final StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
for (Path filePath : fileList) {
|
|
||||||
if (!running) return;
|
|
||||||
|
|
||||||
if (count > 1_000_000) break;
|
|
||||||
|
|
||||||
final String fileName = filePath.getFileName().normalize().toString();
|
|
||||||
final String absolutePath = filePath.toAbsolutePath().normalize().toString();
|
|
||||||
|
|
||||||
if (fileName.endsWith(".txt.gz")) {
|
|
||||||
try (
|
|
||||||
final GZIPInputStream gzipInputStream = new GZIPInputStream(new FileInputStream(absolutePath));
|
|
||||||
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(gzipInputStream, StandardCharsets.UTF_8))
|
|
||||||
) {
|
|
||||||
result.append(process(bufferedReader, input, ignoreCase, regex));
|
|
||||||
}
|
|
||||||
} else if (fileName.endsWith(".txt")) {
|
|
||||||
try (
|
|
||||||
final FileInputStream fileInputStream = new FileInputStream(absolutePath);
|
|
||||||
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fileInputStream, StandardCharsets.UTF_8))
|
|
||||||
) {
|
|
||||||
result.append(process(bufferedReader, input, ignoreCase, regex));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ? should this be here? (see `process` function below)
|
|
||||||
pattern = null;
|
|
||||||
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
final String stringifiedResult = result.toString();
|
|
||||||
|
|
||||||
final long matches = stringifiedResult.lines().count();
|
|
||||||
|
|
||||||
if (matches == 0) throw new CommandException(Component.text("No matches has been found"));
|
|
||||||
|
|
||||||
final String channelId = bot.discord.servers.get(bot.host + ":" + bot.port);
|
|
||||||
final TextChannel logChannel = bot.discord.jda.getTextChannelById(channelId);
|
|
||||||
|
|
||||||
if (logChannel == null) return;
|
|
||||||
|
|
||||||
logChannel
|
|
||||||
.sendMessage("Greplog result:")
|
|
||||||
.addFiles(
|
|
||||||
FileUpload.fromData(
|
|
||||||
// as of the time writing this, discord has an 8 MB file size limit for bots
|
|
||||||
StringUtilities.truncateToFitUtf8ByteLength(stringifiedResult, 8 * 1000 * 1000).getBytes(),
|
|
||||||
String.format("result-%d.txt", System.currentTimeMillis() / 1000)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.queue(message -> {
|
|
||||||
final String url = message.getAttachments().get(0).getUrl();
|
|
||||||
|
|
||||||
final Component component = Component.translatable("Found %s matches for %s. You can see the results by clicking %s or in the Discord server.")
|
|
||||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
|
||||||
.arguments(
|
|
||||||
Component.text(matches).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
|
||||||
Component.text(input).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
|
||||||
Component
|
|
||||||
.text("here")
|
|
||||||
.color(NamedTextColor.GREEN)
|
|
||||||
.hoverEvent(
|
|
||||||
HoverEvent.showText(
|
|
||||||
Component
|
|
||||||
.text("Click! :D")
|
|
||||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.clickEvent(
|
|
||||||
ClickEvent.openUrl(url)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
context.sendOutput(component);
|
|
||||||
});
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
running = false;
|
|
||||||
throw new CommandException(Component.text("File not found"));
|
|
||||||
} catch (NotDirectoryException e) {
|
|
||||||
running = false;
|
|
||||||
throw new CommandException(Component.text("Logger directory is not a directory"));
|
|
||||||
} catch (PatternSyntaxException e) {
|
|
||||||
running = false;
|
|
||||||
throw new CommandException(Component.text("Pattern is invalid"));
|
|
||||||
} catch (IOException e) {
|
|
||||||
running = false;
|
|
||||||
throw new CommandException(Component.text("An I/O error has occurred"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private StringBuilder process (BufferedReader bufferedReader, String input, boolean ignoreCase, boolean regex) throws IOException, PatternSyntaxException {
|
|
||||||
if (regex && pattern == null) {
|
|
||||||
if (ignoreCase) pattern = Pattern.compile(input, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CHARACTER_CLASS);
|
|
||||||
else pattern = Pattern.compile(input, Pattern.UNICODE_CHARACTER_CLASS);
|
|
||||||
}
|
|
||||||
|
|
||||||
final StringBuilder result = new StringBuilder();
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
|
||||||
if (
|
|
||||||
(regex && pattern.matcher(line).find()) || // *greplog -regex text OR *greplog -ignorecase -regex text
|
|
||||||
(!ignoreCase && !regex && line.contains(input)) || // *greplog text
|
|
||||||
(ignoreCase && StringUtilities.containsIgnoreCase(line, input)) // *greplog -ignorecase
|
|
||||||
) {
|
|
||||||
result.append(line).append("\n");
|
|
||||||
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
package me.chayapak1.chomens_bot.util;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.CharBuffer;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.nio.charset.CharsetDecoder;
|
|
||||||
import java.nio.charset.CodingErrorAction;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
public class StringUtilities {
|
|
||||||
// https://stackoverflow.com/a/35148974/18518424
|
|
||||||
public static String truncateToFitUtf8ByteLength(String s, int maxBytes) {
|
|
||||||
if (s == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Charset charset = StandardCharsets.UTF_8;
|
|
||||||
CharsetDecoder decoder = charset.newDecoder();
|
|
||||||
byte[] sba = s.getBytes(charset);
|
|
||||||
if (sba.length <= maxBytes) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
// Ensure truncation by having byte buffer = maxBytes
|
|
||||||
ByteBuffer bb = ByteBuffer.wrap(sba, 0, maxBytes);
|
|
||||||
CharBuffer cb = CharBuffer.allocate(maxBytes);
|
|
||||||
// Ignore an incomplete character
|
|
||||||
decoder.onMalformedInput(CodingErrorAction.IGNORE);
|
|
||||||
decoder.decode(bb, cb, true);
|
|
||||||
decoder.flush(cb);
|
|
||||||
return new String(cb.array(), 0, cb.position());
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/25379180/18518424
|
|
||||||
public static boolean containsIgnoreCase(String src, String what) {
|
|
||||||
final int length = what.length();
|
|
||||||
if (length == 0)
|
|
||||||
return true; // Empty string is contained
|
|
||||||
|
|
||||||
final char firstLo = Character.toLowerCase(what.charAt(0));
|
|
||||||
final char firstUp = Character.toUpperCase(what.charAt(0));
|
|
||||||
|
|
||||||
for (int i = src.length() - length; i >= 0; i--) {
|
|
||||||
// Quick check before calling the more expensive regionMatches() method:
|
|
||||||
final char ch = src.charAt(i);
|
|
||||||
if (ch != firstLo && ch != firstUp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (src.regionMatches(true, i, what, 0, length))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue