extends Node const prefix := "!e" var expr := Expression.new() const PRINT_FUNCS = { "print": "", "prints": " ", "printt": "\\t", "printraw": "", } const BLACKLISTED_OBJS = [ "OS.", "File.", "GDScript.", "ClassDB.", "Expression.", ] 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 func _ready(): var bot := DiscordBot.new() add_child(bot) var file = File.new() var err = file.open("res://token", File.READ) var token if err == OK: token = file.get_as_text() elif OS.has_environment("TOKEN"): 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): 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: 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") 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])