diff --git a/build-number.txt b/build-number.txt index b0460c18..da6a5a02 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -3664 \ No newline at end of file +3674 \ No newline at end of file diff --git a/build.gradle b/build.gradle index f93265d0..8809c945 100644 --- a/build.gradle +++ b/build.gradle @@ -58,6 +58,7 @@ dependencies { implementation 'party.iroiro.luajava:luajava:4.0.2' implementation 'party.iroiro.luajava:lua54:4.0.2' runtimeOnly 'party.iroiro.luajava:lua54-platform:4.0.2:natives-desktop' + implementation 'org.python:jython-standalone:2.7.4' implementation 'net.dv8tion:JDA:5.6.1' implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.25.0' implementation 'io.socket:socket.io-client:2.1.2' diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java index 093af325..5eacd8f4 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java @@ -7,6 +7,8 @@ import me.chayapak1.chomens_bot.command.CommandException; import me.chayapak1.chomens_bot.command.TrustLevel; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; +import org.python.core.PyObject; +import org.python.util.PythonInterpreter; import party.iroiro.luajava.Lua; import party.iroiro.luajava.lua54.Lua54; import party.iroiro.luajava.value.LuaValue; @@ -17,11 +19,17 @@ import java.util.concurrent.TimeUnit; public class ServerEvalCommand extends Command { public Lua lua; + public PythonInterpreter python; public ServerEvalCommand () { super( "servereval", - new String[] { "reset", "" }, + new String[] { + "lua reset", + "lua ", + "python reset", + "python " + }, new String[] {}, TrustLevel.OWNER ); @@ -31,49 +39,85 @@ public class ServerEvalCommand extends Command { public Component execute (final CommandContext context) throws CommandException { final Bot bot = context.bot; + final String language = context.getString(false, true); final String code = context.getString(true, true); - if (code.equalsIgnoreCase("reset")) { - if (lua != null) lua.close(); - lua = null; + switch (language.toLowerCase()) { + case "lua" -> { + if (code.equalsIgnoreCase("reset")) { + if (lua != null) lua.close(); + lua = null; - return Component.translatable("commands.servereval.reset", bot.colorPalette.defaultColor); - } - - bot.executorService.execute(() -> { - try { - if (lua == null) lua = new Lua54(); - - lua.openLibraries(); - - lua.set("lua", lua); - lua.set("bot", bot); - lua.set("context", context); - lua.set("shell", new Shell()); - - final LuaValue[] values = lua.eval(code); - - final StringBuilder output = new StringBuilder(); - - if (values.length != 1) { - output.append('['); - - int i = 1; - for (final LuaValue value : values) { - output.append(getString(value)); - if (i++ != values.length) output.append(", "); - } - - output.append(']'); - } else { - output.append(getString(values[0])); + return Component.translatable("commands.servereval.lua.reset", bot.colorPalette.defaultColor); } - context.sendOutput(Component.text(output.toString(), NamedTextColor.GREEN)); - } catch (final Exception e) { - context.sendOutput(Component.text(e.toString(), NamedTextColor.RED)); + bot.executorService.execute(() -> { + try { + if (lua == null) lua = new Lua54(); + + lua.openLibraries(); + + lua.set("lua", lua); + lua.set("python", python); + lua.set("bot", bot); + lua.set("context", context); + lua.set("shell", new Shell()); + + final LuaValue[] values = lua.eval(code); + + final StringBuilder output = new StringBuilder(); + + if (values.length != 1) { + output.append('['); + + int i = 1; + for (final LuaValue value : values) { + output.append(getString(value)); + if (i++ != values.length) output.append(", "); + } + + output.append(']'); + } else { + output.append(getString(values[0])); + } + + context.sendOutput(Component.text(output.toString(), NamedTextColor.GREEN)); + } catch (final Exception e) { + context.sendOutput(Component.text(e.toString(), NamedTextColor.RED)); + } + }); } - }); + case "python", "py" -> { + if (code.equalsIgnoreCase("reset")) { + if (python != null) python.close(); + python = null; + + return Component.translatable("commands.servereval.python.reset", bot.colorPalette.defaultColor); + } + + bot.executorService.execute(() -> { + try { + if (python == null) python = new PythonInterpreter(); + + python.set("lua", lua); + python.set("python", python); + python.set("bot", bot); + python.set("context", context); + + python.exec(code); + + final PyObject output = python.get("output"); + if (output != null) { + context.sendOutput(Component.text(output.toString(), NamedTextColor.GREEN)); + python.set("output", null); + } + } catch (final Exception e) { + context.sendOutput(Component.text(e.toString(), NamedTextColor.RED)); + } + }); + } + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); + } return null; } @@ -108,10 +152,15 @@ public class ServerEvalCommand extends Command { final BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); + boolean stderr = false; while ((character = stderrReader.read()) != -1) { final char[] chars = Character.toChars(character); final String string = new String(chars); - output.append("[STDERR] ").append(string); + if (!stderr) { + output.append("[STDERR] "); + stderr = true; + } + output.append(string); } process.waitFor(10, TimeUnit.SECONDS); diff --git a/src/main/resources/language-en_us.json b/src/main/resources/language-en_us.json index 4fb036a0..fb4b647c 100644 --- a/src/main/resources/language-en_us.json +++ b/src/main/resources/language-en_us.json @@ -238,8 +238,9 @@ "commands.seen.error.no_last_seen_entry": "This player doesn't seem to have the last seen entry in the database for some reason.", "commands.seen.error.no_time_entry": "This player doesn't seem to have the `lastSeen.time` entry in the database for some reason.", - "commands.servereval.description": "Evaluate codes using LuaJ", - "commands.servereval.reset": "Reset the Lua instance", + "commands.servereval.description": "Evaluate codes using LuaJ or Jython", + "commands.servereval.lua.reset": "Reset the Lua instance", + "commands.servereval.python.reset": "Reset the Python instance", "commands.stop.description": "Gracefully stops the bot", "commands.stop.output": "Stopping",