Evaluate gdscript code
Diffstat (limited to 'Eval.gd')
-rw-r--r--Eval.gd120
1 files changed, 100 insertions, 20 deletions
diff --git a/Eval.gd b/Eval.gd
index 803df2a..2fcb570 100644
--- a/Eval.gd
+++ b/Eval.gd
@@ -1,8 +1,47 @@
extends Node
-const prefix = "!e"
+const prefix := "!e"
+
+var expr := Expression.new()
+
+const PRINT_FUNCS = {
+ "print": "",
+ "prints": " ",
+ "printt": "\\t",
+ "printraw": "",
+}
+
+const BLACKLISTED_OBJS = [
+ "OS.",
+ "File."
+]
+
+var script_append := "\n#----INSERTED-----#\n\nvar output: String"
+
+const print_func_template := """
+func {name}(arg1 = '', arg2 = '', arg3 = '', arg4 = '', arg5 = '', arg6 = '', arg7 = '', arg8 = '', arg9 = '') -> void:
+ # Also call the built-in printing function
+ {name}(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
+ for argument in [arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9]:
+ output += str(argument) + '{separator}'
+ output += '{end}'
+"""
+
+var output_message = "Output: ```%s```"
+
+var func_replacements = [
+ [compile("print\\s*\\("), "self.print("],
+ [compile("prints\\s*\\("), "self.prints("],
+ [compile("printt\\s*\\("), "self.printt("],
+ [compile("printraw\\s*\\("), "self.printraw("],
+]
+
+
+func compile(source: String) -> RegEx:
+ var reg := RegEx.new()
+ reg.compile(source)
+ return reg
-var expr = Expression.new()
func _ready():
var bot := DiscordBot.new()
@@ -16,38 +55,79 @@ func _ready():
token = OS.get_environment("TOKEN")
else:
push_error("token missing")
+ file.close()
bot.TOKEN = token
bot.connect("bot_ready", self, "_on_bot_ready")
bot.connect("message_create", self, "_on_message_create")
bot.login()
+ for print_func in PRINT_FUNCS:
+ script_append += print_func_template.format(
+ {
+ name = print_func,
+ separator = PRINT_FUNCS[print_func],
+ end = "" if print_func == "printraw" else "\\n",
+ }
+ )
func _on_bot_ready(bot: DiscordBot):
+ bot.set_presence({"activity": {"type": "Game", "name": "Evaluating GDScript"}})
print("Logged in as " + bot.user.username + "#" + bot.user.discriminator)
print("Listening on " + str(bot.channels.size()) + " channels and " + str(bot.guilds.size()) + " guilds.")
+
func _on_message_create(bot: DiscordBot, message: Message, _channel: Dictionary):
- if message.author.bot or message.content.split(" ")[0] != prefix:
- return
- var reg = RegEx.new()
- reg.compile("`+([^`]+)`+")
+ var split = message.content.split(" ")
+ if message.author.bot or not prefix in split[0]:
+ return
+ var reg := compile("`+([^`]+)`+")
var res = reg.search(message.content)
- var code = res.strings[1] if res else message.content.substr(len(prefix) + 1)
+ var code: String = res.strings[1] if res else PoolStringArray(Array(split).slice(1, len(split))).join(" ")
var lines = code.split("\n")
if res and lines[0] in ["swift", "py", "c", "c++"]:
lines.remove(0)
code = lines.join("\n")
-
- var skip = false
- var error = expr.parse(code, [])
- if error != OK:
- bot.send(message, str(expr.get_error_text()) if expr.get_error_text() else "null")
- skip = true
-
- if not skip:
- var result = expr.execute([], null, true)
- if not expr.has_execute_failed():
- bot.send(message, str(result) if result else "null")
- return
- bot.send(message, "Execution of \n```swift\n%s\n``` Has failed" % code + ( ": " + expr.get_error_text() if expr.get_error_text() else "."))
+ for b in BLACKLISTED_OBJS:
+ code = code.replace(b, "Node.")
+
+ code = code.strip_edges()
+
+ var original_code = code # save it for later
+
+ var error
+ if lines.size() > 1 or "." in code:
+ if code.find("func _ready()") == -1:
+ code = "func _ready():\n" + code.indent("\t") + "\n"
+
+ if not "extends" in lines[0]:
+ code = "extends Node\n" + code
+
+ for row in func_replacements:
+ code = row[0].sub(code, row[1], true)
+
+ code += script_append
+
+ var script := GDScript.new()
+ script.source_code = code
+ error = script.reload()
+ if error == OK:
+ var instance: Node = script.new()
+ if is_instance_valid(instance):
+ add_child(instance)
+ yield(get_tree(), "idle_frame")
+ var o = instance.output.strip_edges()
+ bot.reply(message, output_message % (o if o else "null"))
+ instance.queue_free()
+ return
+ else:
+ var e: int = expr.parse(code, [])
+
+ if e == OK:
+ var o = str(expr.execute([], null, true))
+ if not expr.has_execute_failed():
+ bot.reply(message, output_message % (o if o else "null"))
+ return
+ error = expr.get_error_text()
+
+ bot.reply(message, "Execution of \n```swift\n%s\n``` Has failed. Error: %s" % [original_code, error])