Evaluate gdscript code
Diffstat (limited to 'Eval.gd')
| -rw-r--r-- | Eval.gd | 120 |
1 files changed, 100 insertions, 20 deletions
@@ -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]) |