latex bot discord
Diffstat (limited to 'Latex.gd')
| -rw-r--r-- | Latex.gd | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/Latex.gd b/Latex.gd new file mode 100644 index 0000000..1f52119 --- /dev/null +++ b/Latex.gd @@ -0,0 +1,130 @@ +extends Node + +var template_tex := """ +\\documentclass[varwidth=true]{standalone} +\\usepackage[utf8]{inputenc} +\\usepackage{xcolor} +\\usepackage{amsmath} + +\\color{white} +\\begin{document} + +%s + +\\end{document} +""" + +var f := File.new() +var thread_pool := [] + + +func compile(source: String) -> RegEx: + var reg := RegEx.new() + reg.compile(source) + return reg + + +func _ready(): + for _i in range(5): + thread_pool.append(Thread.new()) + var dir = Directory.new() + if !dir.dir_exists("res://texs"): + dir.make_dir("texs") + f.open("res://texs/.gdignore", File.WRITE) # touch .gdignore + f.close() + 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() + + +func _on_bot_ready(bot: DiscordBot): + bot.set_presence({"activity": {"type": "Game", "name": "Printing LaTeX"}}) + 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: + return + var msg: String + var reg := compile("`{3}(la)?tex([^`]+)`{3}") + var res := reg.search(message.content) + if res: + msg = res.strings[2] + else: + var reg2 := compile("!(la)?tex\\s*([\\s\\S]+)") + var res2 := reg2.search(message.content) + if !res2: + return + msg = res2.strings[2] + + msg = msg.strip_edges() + + print("----\n%s\n----" % msg) + if !msg: + return + + var th :Thread + for thread in thread_pool: + if !thread.is_alive(): + th = thread + break + if !th: + thread_pool.append(Thread.new()) + th = thread_pool[-1] + + th.start(self, "latex2img", template_tex % msg) + while true: + yield(get_tree(), "idle_frame") + if !th.is_alive(): + var img = th.wait_to_finish() + if img is Dictionary: + bot.reply(message, "No({err}): `{output}`".format(img)) + return + bot.reply( + message, + "Tex:", + {"files": [{"name": "code.png", "media_type": "image/png", "data": img.save_png_to_buffer()}]} + ) + return + + +func _notification(what): + if what == NOTIFICATION_EXIT_TREE: + OS.execute("bash", ["-c", "rm -r texs"], false) + + +func latex2img(latex: String): + randomize() + var name := ("%s-%s" % [randi() % 201, randi() % 201]).c_escape() + f.open("res://texs/%s.tex" % name, File.WRITE_READ) + f.store_string(latex) + f.close() + var output :PoolStringArray = [] + var err = OS.execute("bash", ["-c", "cd texs && latex -interaction=nonstopmode '%s.tex'" % name], true, output, true) + if err: + return {err = err, output = "(la)" + output.join(" ")} + output.resize(0) + var dvipng = [ + "-c", "dvipng -strict -bg Transparent --png -Q 250 -D 250 -T tight -o 'texs/%s.png' 'texs/%s.dvi'" % [name, name] + ] + err = OS.execute("bash", dvipng, true, output, true) + if err: + return {err = err, output = "(dvi)" +output.join(" ")} + var img := Image.new() + err = img.load("res://texs/%s.png" % name) + OS.execute("bash", ["-c", "rm 'texs/%s.'*" % name], false) + return img |