diff --git a/CHANGELOG.md b/CHANGELOG.md index e1415e8..1c58413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] - +### Added +- `?tex` command to render a LaTeX expression. +- Configuration option to use another rTeX instance for `?tex`. ## [2.6.0] - 2021-03-18 ### Added diff --git a/exts/tex.py b/exts/tex.py new file mode 100644 index 0000000..9701651 --- /dev/null +++ b/exts/tex.py @@ -0,0 +1,65 @@ +""" +TeX extension for qrm +--- +Copyright (C) 2021 thxo + +This file is part of qrm2 and is released under the terms of +the GNU General Public License, version 2. +""" + +import aiohttp +from io import BytesIO +from urllib.parse import urljoin + +import discord +import discord.ext.commands as commands + +import common as cmn +import data.options as opt + + +class TexCog(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + self.session = aiohttp.ClientSession(connector=bot.qrm.connector) + self.rtex_instance = getattr(opt, "rtex_instance", "https://rtex.probablyaweb.site/") + with open(cmn.paths.resources / "template.1.tex") as latex_template: + self.template = latex_template.read() + + @commands.command(name="tex", aliases=["latex"], category=cmn.cat.fun) + async def tex(self, ctx: commands.Context, *, expr: str): + """Renders a LaTeX expression.""" + payload = { + "format": "png", + "code": self.template.replace("#CONTENT#", expr), + "quality": 50 + } + + with ctx.typing(): + # ask rTeX to render our expression + async with self.session.post(urljoin(self.rtex_instance, "api/v2"), json=payload) as r: + if r.status != 200: + raise cmn.BotHTTPError(r) + + render_result = await r.json() + if render_result["status"] != "success": + embed = cmn.embed_factory(ctx) + embed.title = "LaTeX Rendering Failed!" + embed.description = render_result.get("description", "Unknown error") + embed.colour = cmn.colours.bad + await ctx.send(embed=embed) + return + + # if rendering went well, download the file given in the response + async with self.session.get(urljoin(self.rtex_instance, "api/v2/" + render_result["filename"])) as r: + png_buffer = BytesIO(await r.read()) + + embed = cmn.embed_factory(ctx) + embed.title = "LaTeX Expression" + embed.description = "Rendered by [rTeX](https://rtex.probablyaweb.site/)." + embed.set_image(url="attachment://tex.png") + await ctx.send(file=discord.File(png_buffer, "tex.png"), embed=embed) + + +def setup(bot: commands.Bot): + bot.add_cog(TexCog(bot)) diff --git a/templates/data/options.py b/templates/data/options.py index 8b6e9c6..c88b204 100644 --- a/templates/data/options.py +++ b/templates/data/options.py @@ -41,6 +41,7 @@ exts = [ "morse", "qrz", "study", + "tex", "weather", "dbconv", "propagation", @@ -86,3 +87,6 @@ msg_reacts = {} # A :pika: emote's ID, None for no emote :c pika = 658733876176355338 + +# Base URL to a deployment of rTeX, which performs LaTeX rendering. +rtex_instance = "https://rtex.probablyaweb.site/"