aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/evergreen/latex.py
blob: 79b50ccd6ce19e088723de8bf6b6d0dc1b1e9787 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from io import BytesIO
from typing import Union

import discord
import matplotlib.pyplot as plt
from discord.ext import commands

# configure fonts and colors for matplotlib
plt.rcParams.update(
    {
        "font.size": 16,
        "mathtext.fontset": "cm",  # Computer Modern font set
        "mathtext.rm": "serif",
        "figure.facecolor": "38383F",  # matches Discord's dark mode background color
        "text.color": "white",
    }
)


class Latex(commands.Cog):
    """Renders latex."""

    def __init__(self, bot: commands.Bot):
        self.bot = bot

    @staticmethod
    def _render(text: str) -> Union[BytesIO, str]:
        """Return the rendered image if latex compiles without errors, otherwise return the error message."""
        text = text.replace(r"\\", "$\n$")  # matplotlib uses \n for newlines, not \\
        fig = plt.figure()

        try:
            fig.text(0, 1, text, horizontalalignment="left", verticalalignment="top")

            rendered_image = BytesIO()
            plt.savefig(rendered_image, bbox_inches="tight", dpi=600)
            rendered_image.seek(0)
            return rendered_image

        except ValueError as e:
            return str(e)

    @commands.command()
    async def latex(self, ctx: commands.Context, *, text: str) -> None:
        """Renders the text in latex and sends the image."""
        async with ctx.typing():
            image = self._render(text)

            if isinstance(image, BytesIO):
                await ctx.send(file=discord.File(image, "latex.png"))
            else:
                await ctx.send(image)


def setup(bot: commands.Bot) -> None:
    """Load the Latex Cog."""
    bot.add_cog(Latex(bot))