refactor: make eval use only 1 connection to hopefully reduce threads amount + some misc refactors
fix: in GetBotInfoFunction, i misspelled `username` as `usernane`, it has been fixed refactor: remove GetLatestChatMessageFunction, since the functions are now global and not bot-specific (yes, i know i can still implement it somewhere like in EvalPlugin or even call a function in GetLatestChatMessageFunction itself passing the bot, but no one really use this function anyway except the last time when ploat made some telnet ahh eval thing which used this function)
This commit is contained in:
@@ -2,10 +2,7 @@ package me.chayapak1.chomens_bot;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import me.chayapak1.chomens_bot.plugins.ConsolePlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.DiscordPlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.IRCPlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.*;
|
||||
import me.chayapak1.chomens_bot.util.*;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
|
||||
import org.yaml.snakeyaml.LoaderOptions;
|
||||
@@ -146,6 +143,7 @@ public class Main {
|
||||
console = new ConsolePlugin(config);
|
||||
if (config.discord.enabled) discord = new DiscordPlugin(config);
|
||||
if (config.irc.enabled) irc = new IRCPlugin(config);
|
||||
EvalPlugin.connect(config.eval.address);
|
||||
|
||||
LoggerUtilities.log(I18nUtilities.get("initialized"));
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalOutput;
|
||||
import me.chayapak1.chomens_bot.plugins.EvalPlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
@@ -28,7 +29,7 @@ public class EvalCommand extends Command {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (!bot.eval.connected) throw new CommandException(Component.translatable("commands.eval.error.offline"));
|
||||
if (!EvalPlugin.connected) throw new CommandException(Component.translatable("commands.eval.error.offline"));
|
||||
|
||||
final String action = context.getAction();
|
||||
|
||||
@@ -38,16 +39,19 @@ public class EvalCommand extends Command {
|
||||
|
||||
final CompletableFuture<EvalOutput> future = bot.eval.run(command);
|
||||
|
||||
future.thenApply(output -> {
|
||||
if (output.isError()) context.sendOutput(Component.text(output.output()).color(NamedTextColor.RED));
|
||||
else context.sendOutput(Component.text(output.output()));
|
||||
// it returns null when the eval server isn't online, even though we have already checked,
|
||||
// i'm just fixing the warning here
|
||||
if (future == null) return null;
|
||||
|
||||
return output;
|
||||
future.thenApply(result -> {
|
||||
if (result.isError()) context.sendOutput(Component.text(result.output(), NamedTextColor.RED));
|
||||
else context.sendOutput(Component.text(result.output()));
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
case "reset" -> {
|
||||
bot.eval.reset();
|
||||
|
||||
EvalPlugin.reset();
|
||||
return Component.translatable("commands.eval.reset", bot.colorPalette.defaultColor);
|
||||
}
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
|
||||
@@ -5,17 +5,11 @@ import me.chayapak1.chomens_bot.Bot;
|
||||
public class EvalFunction {
|
||||
public final String name;
|
||||
|
||||
protected final Bot bot;
|
||||
|
||||
public EvalFunction (
|
||||
final String name,
|
||||
final Bot bot
|
||||
) {
|
||||
public EvalFunction (final String name) {
|
||||
this.name = name;
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public Output execute (final Object... args) throws Exception { return null; }
|
||||
public Output execute (final Bot bot, final Object... args) throws Exception { return null; }
|
||||
|
||||
public record Output(String message, boolean parseJSON) {
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
|
||||
|
||||
public class ChatFunction extends EvalFunction {
|
||||
public ChatFunction (final Bot bot) {
|
||||
super("chat", bot);
|
||||
public ChatFunction () {
|
||||
super("chat");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) {
|
||||
public Output execute (final Bot bot, final Object... args) {
|
||||
if (args.length == 0) return null;
|
||||
|
||||
final String message = (String) args[0];
|
||||
|
||||
@@ -11,12 +11,12 @@ import java.util.concurrent.TimeUnit;
|
||||
public class CoreFunction extends EvalFunction {
|
||||
private long lastExecutionTime = System.currentTimeMillis();
|
||||
|
||||
public CoreFunction (final Bot bot) {
|
||||
super("core", bot);
|
||||
public CoreFunction () {
|
||||
super("core");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) throws Exception {
|
||||
public Output execute (final Bot bot, final Object... args) throws Exception {
|
||||
if (args.length == 0) return null;
|
||||
|
||||
// prevent 69 DDOS exploit !!!
|
||||
|
||||
@@ -4,12 +4,12 @@ import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
|
||||
|
||||
public class CorePlaceBlockFunction extends EvalFunction {
|
||||
public CorePlaceBlockFunction (final Bot bot) {
|
||||
super("corePlaceBlock", bot);
|
||||
public CorePlaceBlockFunction () {
|
||||
super("corePlaceBlock");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) {
|
||||
public Output execute (final Bot bot, final Object... args) {
|
||||
if (args.length == 0) return null;
|
||||
|
||||
final String command = (String) args[0];
|
||||
|
||||
@@ -5,15 +5,15 @@ import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
|
||||
|
||||
public class GetBotInfoFunction extends EvalFunction {
|
||||
public GetBotInfoFunction (final Bot bot) {
|
||||
super("getBotInfo", bot);
|
||||
public GetBotInfoFunction () {
|
||||
super("getBotInfo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) {
|
||||
public Output execute (final Bot bot, final Object... args) {
|
||||
final JsonObject object = new JsonObject();
|
||||
|
||||
object.addProperty("usernane", bot.username);
|
||||
object.addProperty("username", bot.username);
|
||||
object.addProperty("host", bot.host);
|
||||
object.addProperty("port", bot.port);
|
||||
object.addProperty("loggedIn", bot.loggedIn);
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package me.chayapak1.chomens_bot.evalFunctions;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
|
||||
import me.chayapak1.chomens_bot.data.listener.Listener;
|
||||
import me.chayapak1.chomens_bot.util.SNBTUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class GetLatestChatMessageFunction extends EvalFunction implements Listener {
|
||||
private String latestMessage = "";
|
||||
|
||||
public GetLatestChatMessageFunction (final Bot bot) {
|
||||
super("getLatestChatMessage", bot);
|
||||
|
||||
bot.listener.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSystemMessageReceived (final Component component, final String string, final String ansi) {
|
||||
latestMessage = SNBTUtilities.fromComponent(false, component);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) {
|
||||
return new Output(latestMessage, true);
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,12 @@ import me.chayapak1.chomens_bot.util.SNBTUtilities;
|
||||
import java.util.List;
|
||||
|
||||
public class GetPlayerListFunction extends EvalFunction {
|
||||
public GetPlayerListFunction (final Bot bot) {
|
||||
super("getPlayerList", bot);
|
||||
public GetPlayerListFunction () {
|
||||
super("getPlayerList");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Output execute (final Object... args) {
|
||||
public Output execute (final Bot bot, final Object... args) {
|
||||
final List<PlayerEntry> list = bot.players.list;
|
||||
|
||||
final JsonArray array = new JsonArray();
|
||||
|
||||
@@ -2,115 +2,127 @@ package me.chayapak1.chomens_bot.plugins;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import io.socket.client.IO;
|
||||
import io.socket.client.Socket;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalFunction;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalOutput;
|
||||
import me.chayapak1.chomens_bot.evalFunctions.*;
|
||||
import me.chayapak1.chomens_bot.util.LoggerUtilities;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class EvalPlugin {
|
||||
public static final String BRIDGE_PREFIX = "function:";
|
||||
private static final String BRIDGE_PREFIX = "function:";
|
||||
public static final List<EvalFunction> FUNCTIONS = ObjectList.of(
|
||||
new CoreFunction(),
|
||||
new CorePlaceBlockFunction(),
|
||||
new ChatFunction(),
|
||||
new GetPlayerListFunction(),
|
||||
new GetBotInfoFunction()
|
||||
);
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
public boolean connected = false;
|
||||
private static Socket socket = null;
|
||||
public static boolean connected = false;
|
||||
|
||||
private Socket socket = null;
|
||||
|
||||
private int transactionId = 0;
|
||||
|
||||
private final Map<Integer, CompletableFuture<EvalOutput>> futures = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
public final List<EvalFunction> functions = new ArrayList<>();
|
||||
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
public EvalPlugin (final Bot bot) {
|
||||
functions.add(new CoreFunction(bot));
|
||||
functions.add(new CorePlaceBlockFunction(bot));
|
||||
functions.add(new ChatFunction(bot));
|
||||
functions.add(new GetPlayerListFunction(bot));
|
||||
functions.add(new GetBotInfoFunction(bot));
|
||||
functions.add(new GetLatestChatMessageFunction(bot));
|
||||
private static final AtomicInteger transactionId = new AtomicInteger();
|
||||
private static final Map<Integer, CompletableFuture<EvalOutput>> futures = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
public static void connect (final String address) {
|
||||
try {
|
||||
socket = IO.socket(bot.config.eval.address);
|
||||
socket = IO.socket(address);
|
||||
} catch (final Exception e) {
|
||||
bot.logger.error(e);
|
||||
LoggerUtilities.error(e);
|
||||
return;
|
||||
}
|
||||
|
||||
socket.on(Socket.EVENT_CONNECT, (args) -> {
|
||||
socket.on(Socket.EVENT_CONNECT, args -> {
|
||||
connected = true;
|
||||
|
||||
final JsonArray array = new JsonArray();
|
||||
final JsonArray functionsArray = new JsonArray();
|
||||
|
||||
for (final EvalFunction function : functions) array.add(function.name);
|
||||
for (final Bot bot : Main.bots) {
|
||||
final String server = bot.getServerString(true);
|
||||
|
||||
for (final EvalFunction function : FUNCTIONS) {
|
||||
final JsonObject object = new JsonObject();
|
||||
|
||||
object.addProperty("name", function.name);
|
||||
object.addProperty("server", server);
|
||||
|
||||
functionsArray.add(object);
|
||||
}
|
||||
|
||||
for (final EvalFunction function : FUNCTIONS) {
|
||||
socket.on(
|
||||
BRIDGE_PREFIX + function.name + ":" + bot.getServerString(true),
|
||||
functionArgs ->
|
||||
Main.EXECUTOR_SERVICE.submit(() -> {
|
||||
try {
|
||||
final EvalFunction.Output output = function.execute(bot, functionArgs);
|
||||
if (output == null) return;
|
||||
socket.emit("functionOutput:" + function.name, output.message(), output.parseJSON());
|
||||
} catch (final Exception ignored) { }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
socket.on("codeOutput", outputArgs -> {
|
||||
if (outputArgs.length < 3) return;
|
||||
|
||||
try {
|
||||
final int id = (int) outputArgs[0];
|
||||
final boolean isError = (boolean) outputArgs[1];
|
||||
final String output = (String) outputArgs[2];
|
||||
|
||||
if (!futures.containsKey(id)) return;
|
||||
|
||||
final CompletableFuture<EvalOutput> future = futures.remove(id);
|
||||
|
||||
future.complete(new EvalOutput(isError, output));
|
||||
} catch (final ClassCastException | NumberFormatException ignored) { }
|
||||
});
|
||||
}
|
||||
|
||||
socket.emit(
|
||||
"setFunctions",
|
||||
gson.toJson(array)
|
||||
GSON.toJson(functionsArray)
|
||||
);
|
||||
});
|
||||
socket.on(Socket.EVENT_DISCONNECT, (args) -> connected = false);
|
||||
socket.on(Socket.EVENT_CONNECT_ERROR, (args) -> connected = false);
|
||||
|
||||
for (final EvalFunction function : functions) {
|
||||
socket.on(
|
||||
BRIDGE_PREFIX + function.name,
|
||||
args ->
|
||||
bot.executorService.submit(() -> {
|
||||
try {
|
||||
final EvalFunction.Output output = function.execute(args);
|
||||
|
||||
if (output == null) return;
|
||||
|
||||
socket.emit("functionOutput:" + function.name, output.message(), output.parseJSON());
|
||||
} catch (final Exception ignored) { }
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
socket.on("codeOutput", (args) -> {
|
||||
if (args.length < 3) return;
|
||||
|
||||
try {
|
||||
final int id = (int) args[0];
|
||||
final boolean isError = (boolean) args[1];
|
||||
final String output = (String) args[2];
|
||||
|
||||
if (!futures.containsKey(id)) return;
|
||||
|
||||
final CompletableFuture<EvalOutput> future = futures.remove(id);
|
||||
|
||||
future.complete(new EvalOutput(isError, output));
|
||||
} catch (final NumberFormatException ignored) { }
|
||||
});
|
||||
socket.on(Socket.EVENT_DISCONNECT, args -> connected = false);
|
||||
socket.on(Socket.EVENT_CONNECT_ERROR, args -> connected = false);
|
||||
|
||||
socket.connect();
|
||||
}
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
public EvalPlugin (final Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public CompletableFuture<EvalOutput> run (final String code) {
|
||||
final CompletableFuture<EvalOutput> future = new CompletableFuture<>();
|
||||
|
||||
if (!connected) return null;
|
||||
|
||||
socket.emit("runCode", transactionId, code);
|
||||
socket.emit("runCode", bot.getServerString(true), transactionId.get(), code);
|
||||
|
||||
futures.put(transactionId, future);
|
||||
|
||||
transactionId++;
|
||||
futures.put(transactionId.getAndIncrement(), future);
|
||||
|
||||
return future;
|
||||
}
|
||||
|
||||
public void reset () {
|
||||
public static void reset () {
|
||||
if (!connected) return;
|
||||
|
||||
socket.emit("reset");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user