From 4a6b6c1e92e98155e8148d19eab7ad53df11ed9b Mon Sep 17 00:00:00 2001 From: Daniel Milnes Date: Sat, 22 Oct 2022 23:23:29 +0100 Subject: [PATCH] Remove the broken maths challenge code (#738) * Remove the broken maths challenge code I am sorry to the people of for bullying your API all these years... * Sort imports * Remove unused dependencies --- cdbot/cogs/maths.py | 185 +++++++++----------------------------------- poetry.lock | 158 +------------------------------------ pyproject.toml | 2 - 3 files changed, 39 insertions(+), 306 deletions(-) diff --git a/cdbot/cogs/maths.py b/cdbot/cogs/maths.py index 52f15826..59e456b0 100644 --- a/cdbot/cogs/maths.py +++ b/cdbot/cogs/maths.py @@ -5,146 +5,26 @@ from io import BytesIO import aiohttp -import dateutil.parser -import httpx from PIL import Image from discord import Colour, Embed, File, Member, Message, Reaction -from discord.ext import tasks -from discord.ext.commands import Bot, BucketType, Cog, Context, command, cooldown -from html2markdown import convert +from discord.ext.commands import Bot, Cog, Context, command from cdbot.constants import Maths as constants -async def get_challenges( - client: httpx.AsyncClient, page_index: int = 0, page_size: int = 999 -): - """Get challenges, given the relevant parameters.""" - return ( - await client.post( - constants.Challenges.URL, - headers=dict(accessToken=constants.Challenges.TOKEN), - json={ - "pageIndex": page_index, - "pageSize": page_size, - "orderBy": [{"desc": "answerDate"}], - "where": [ - {"field": "sys.versionStatus", "equalTo": "published"}, - {"field": "sys.contentTypeId", "in": ["mathsQuiz"]}, - ], - "fields": ["entryTitle", "category", "sys", "description", "answer"], - }, - ) - ).json()["items"] - - -async def get_challenge(number: int) -> dict: - async with httpx.AsyncClient() as client: - challenge, *_ = await get_challenges(client, page_index=number - 1, page_size=1) - - question = ( - await client.post( - constants.Challenges.URL, - headers=dict(accessToken=constants.Challenges.TOKEN), - json={ - "pageIndex": 0, - "pageSize": 1, - "where": [ - {"field": "sys.slug", "equalTo": challenge["sys"]["slug"]}, - {"field": "sys.versionStatus", "equalTo": "published"}, - ], - }, - ) - ).json()["items"][0]["question"] - - asset = question[1]["value"]["asset"]["sys"] if len(question) > 1 else None - - return { - "title": challenge["entryTitle"], - "published": dateutil.parser.isoparse( - challenge["sys"]["version"]["created"] - ).strftime("%d/%m/%Y"), - "category": challenge["category"][0]["entryTitle"], - "challenge": convert(question[0]["value"]).replace(" ", "")[:-1], - "image": ( - ( - "https://www.kingsmathsschool.com" - "".join( - asset["uri"].rpartition("/")[:2] + (asset["properties"]["filename"],) - ) - ) - if asset - else "" - ), - "description": challenge["description"], - "slug": challenge["sys"]["slug"], - } - - class Maths(Cog): """Maths-related commands.""" def __init__(self, bot: Bot): self.bot = bot - self.update_challenge.start() - - @tasks.loop(minutes=1) - async def update_challenge(self): - """Check the Kings site for the latest challenges.""" - print("Updating maths challenges...") - latest_challenge = float("inf") - latest_challenge = int( - self.channel.topic.split("Nerds, the lot of you | Challenge ")[1].split( - " " - )[0][:-1] - ) - async with httpx.AsyncClient() as client: - challenges = await get_challenges(client) - for number, challenge in enumerate(challenges[::-1], 1): - title = challenge["entryTitle"] - if number > latest_challenge: - await self.challenge(self.channel, len(challenges) - number + 1) - await self.channel.edit(topic=constants.Challenges.TOPIC.format(title)) - print("Maths challenges successfully updated.") - - @update_challenge.before_loop - async def wait_until_ready(self): - """Wait for bot to become ready.""" - await self.bot.wait_until_ready() - self.channel = self.bot.get_channel(constants.Challenges.CHANNEL) @Cog.listener() async def on_message(self, message): """Check if the message contains inline LaTeX.""" if constants.LATEX_RE.findall(message.content): - await self.latex_render(message.channel, message.channel.id, message, message.content) - - @command() - @cooldown(1, 60, BucketType.user) - @cooldown(4, 60, BucketType.channel) - @cooldown(6, 3600, BucketType.guild) - async def challenge(self, ctx: Context, number: int = 1): - """Show the provided challenge number.""" - challenge = await get_challenge(number) - description = challenge["challenge"] - if len(description) > 2048: - description = description[:2045] + "..." - embed = Embed( - title=challenge["title"], - colour=Colour(0xE5E242), - url=f"https://www.kingsmathsschool.com/weekly-maths-challenge/{challenge['slug']}", - description=description, - ) - - embed.set_image(url=challenge["image"]) - embed.set_thumbnail( - url="https://pbs.twimg.com/profile_images/502115424121528320/hTQzj_-R.png" - ) - embed.set_author(name="King's Maths School") - embed.set_footer( - text=f"Challenge Released: {challenge['published']} | Category: {challenge['category']}" - ) - return await ctx.send(embed=embed) + await self.latex_render( + message.channel, message.channel.id, message, message.content + ) @command() async def latex(self, ctx: Context, *, expression: str): @@ -153,11 +33,14 @@ async def latex(self, ctx: Context, *, expression: str): """ await self.latex_render(ctx, ctx.channel.id, ctx.message, expression) - async def latex_render(self, ctx: Context, channel: int, message: Message, expression: str): + async def latex_render( + self, ctx: Context, channel: int, message: Message, expression: str + ): if channel in constants.BLOCKED_CHANNELS: return await ctx.send( - "\N{NO ENTRY SIGN} You cannot use this command in this channel!", delete_after=10 + "\N{NO ENTRY SIGN} You cannot use this command in this channel!", + delete_after=10, ) # Code and regexes taken from https://quicklatex.com/js/quicklatex.js @@ -170,13 +53,13 @@ async def latex_render(self, ctx: Context, channel: int, message: Message, expre preamble = constants.LATEX_PREAMBLE.replace("%", "%25").replace("&", "%26") - body = 'formula=' + formula - body = body + '$$$$&fsize=50px' - body = body + '&fcolor=ffffff' - body = body + '&mode=0' - body = body + '&out=1' - body = body + '&errors=1' - body = body + '&preamble=' + preamble + body = "formula=" + formula + body = body + "$$$$&fsize=50px" + body = body + "&fcolor=ffffff" + body = body + "&mode=0" + body = body + "&out=1" + body = body + "&errors=1" + body = body + "&preamble=" + preamble border_width = 20 @@ -189,15 +72,15 @@ async def latex_render(self, ctx: Context, channel: int, message: Message, expre if not m: return status, url, valign, imgw, imgh, errmsg = m.groups() - if status == '0': + if status == "0": async with session.get(url) as response: content = await response.content.read() img = Image.open(BytesIO(content)) - alpha = img.convert('RGBA').split()[-1] + alpha = img.convert("RGBA").split()[-1] image = Image.new( "RGB", (img.size[0] + 2 * border_width, img.size[1] + 2 * border_width), - "#36393F" + "#36393F", ) image.paste(img, (border_width, border_width), mask=alpha) image_bytes = BytesIO() @@ -205,23 +88,31 @@ async def latex_render(self, ctx: Context, channel: int, message: Message, expre image_bytes.seek(0) # send the resulting image and add a bin reaction - rendered_message = await ctx.send(file=File(image_bytes, filename="result.png")) + rendered_message = await ctx.send( + file=File(image_bytes, filename="result.png") + ) await rendered_message.add_reaction("\N{WASTEBASKET}") # checks if the person who reacted was the original latex author and that they reacted with a bin def should_delete(reaction: Reaction, user: Member): - return all(( - message.author == user, - reaction.emoji == "\N{WASTEBASKET}", - reaction.message.id == rendered_message.id, - )) + return all( + ( + message.author == user, + reaction.emoji == "\N{WASTEBASKET}", + reaction.message.id == rendered_message.id, + ) + ) # if the latex author reacts with a bin within 30 secs of sending, delete the rendered image # otherwise delete the bin reaction try: - await self.bot.wait_for("reaction_add", check=should_delete, timeout=30) + await self.bot.wait_for( + "reaction_add", check=should_delete, timeout=30 + ) except asyncio.TimeoutError: - await rendered_message.remove_reaction("\N{WASTEBASKET}", self.bot.user) + await rendered_message.remove_reaction( + "\N{WASTEBASKET}", self.bot.user + ) else: await rendered_message.delete() @@ -229,13 +120,13 @@ def should_delete(reaction: Reaction, user: Member): embed = Embed( title="\N{WARNING SIGN} **LaTeX Compile Error** \N{WARNING SIGN}", colour=Colour(0xB33A3A), - description=errmsg.replace("@", "") + description=errmsg.replace("@", ""), ) return await ctx.send(embed=embed, delete_after=30) -def setup(bot): +async def setup(bot): """ Required boilerplate for adding functionality of cog to bot. """ - bot.add_cog(Maths(bot)) + await bot.add_cog(Maths(bot)) diff --git a/poetry.lock b/poetry.lock index 1a1f729d..38593e45 100644 --- a/poetry.lock +++ b/poetry.lock @@ -25,23 +25,6 @@ yarl = ">=1.0,<2.0" [package.extras] speedups = ["aiodns", "brotlipy", "cchardet"] -[[package]] -name = "anyio" -version = "3.5.0" -description = "High level compatibility layer for multiple asynchronous event loop implementations" -category = "main" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -idna = ">=2.8" -sniffio = ">=1.1" - -[package.extras] -doc = ["packaging", "sphinx-rtd-theme", "sphinx-autodoc-typehints (>=1.2.0)"] -test = ["coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "pytest (>=6.0)", "pytest-mock (>=3.6.1)", "trustme", "contextlib2", "uvloop (<0.15)", "mock (>=4)", "uvloop (>=0.15)"] -trio = ["trio (>=0.16)"] - [[package]] name = "async-timeout" version = "3.0.1" @@ -96,21 +79,6 @@ test = ["coverage (>=4.5.4)", "fixtures (>=3.0.0)", "flake8 (>=4.0.0)", "stestr toml = ["toml"] yaml = ["pyyaml"] -[[package]] -name = "beautifulsoup4" -version = "4.9.3" -description = "Screen-scraping library" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""} - -[package.extras] -html5lib = ["html5lib"] -lxml = ["lxml"] - [[package]] name = "certifi" version = "2020.6.20" @@ -127,17 +95,6 @@ category = "main" optional = false python-versions = "*" -[[package]] -name = "charset-normalizer" -version = "2.0.10" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.5.0" - -[package.extras] -unicode_backport = ["unicodedata2"] - [[package]] name = "colorama" version = "0.4.4" @@ -294,64 +251,6 @@ python-versions = ">=3.7" [package.dependencies] gitdb = ">=4.0.1,<5" -[[package]] -name = "h11" -version = "0.11.0" -description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" -category = "main" -optional = false -python-versions = "*" - -[[package]] -name = "html2markdown" -version = "0.1.7" -description = "Conservatively convert html to markdown" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -beautifulsoup4 = "*" - -[[package]] -name = "httpcore" -version = "0.14.5" -description = "A minimal low-level HTTP client." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -anyio = ">=3.0.0,<4.0.0" -certifi = "*" -h11 = ">=0.11,<0.13" -sniffio = ">=1.0.0,<2.0.0" - -[package.extras] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] - -[[package]] -name = "httpx" -version = "0.22.0" -description = "The next generation HTTP client." -category = "main" -optional = false -python-versions = ">=3.6" - -[package.dependencies] -certifi = "*" -charset-normalizer = "*" -httpcore = ">=0.14.5,<0.15.0" -rfc3986 = {version = ">=1.3,<2", extras = ["idna2008"]} -sniffio = "*" - -[package.extras] -brotli = ["brotlicffi", "brotli"] -cli = ["click (>=8.0.0,<9.0.0)", "rich (>=10.0.0,<11.0.0)", "pygments (>=2.0.0,<3.0.0)"] -http2 = ["h2 (>=3,<5)"] -socks = ["socksio (>=1.0.0,<2.0.0)"] - [[package]] name = "idna" version = "2.10" @@ -438,20 +337,6 @@ category = "dev" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -[[package]] -name = "rfc3986" -version = "1.5.0" -description = "Validating URI References per RFC 3986" -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -idna = {version = "*", optional = true, markers = "extra == \"idna2008\""} - -[package.extras] -idna2008 = ["idna"] - [[package]] name = "sentry-sdk" version = "1.5.12" @@ -498,22 +383,6 @@ category = "main" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -[[package]] -name = "sniffio" -version = "1.2.0" -description = "Sniff out which async library your code is running under" -category = "main" -optional = false -python-versions = ">=3.5" - -[[package]] -name = "soupsieve" -version = "2.0.1" -description = "A modern CSS selector implementation for Beautiful Soup." -category = "main" -optional = false -python-versions = ">=3.5" - [[package]] name = "stevedore" version = "3.2.2" @@ -561,7 +430,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "e8199989b5c151e94125cfd1b22816f20c07d9a22448c140c9dfb1efaca561fe" +content-hash = "21905c21e32a1bc158cd0e05d96ed0011f32a21fbeee6d1502ffd61d864cfbaa" [metadata.files] aiocontextvars = [ @@ -569,7 +438,6 @@ aiocontextvars = [ {file = "aiocontextvars-0.2.2.tar.gz", hash = "sha256:f027372dc48641f683c559f247bd84962becaacdc9ba711d583c3871fb5652aa"}, ] aiohttp = [] -anyio = [] async-timeout = [ {file = "async-timeout-3.0.1.tar.gz", hash = "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f"}, {file = "async_timeout-3.0.1-py3-none-any.whl", hash = "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"}, @@ -580,11 +448,6 @@ attrs = [ {file = "attrs-20.2.0.tar.gz", hash = "sha256:26b54ddbbb9ee1d34d5d3668dd37d6cf74990ab23c828c2888dccdceee395594"}, ] bandit = [] -beautifulsoup4 = [ - {file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"}, - {file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"}, - {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"}, -] certifi = [ {file = "certifi-2020.6.20-py2.py3-none-any.whl", hash = "sha256:8fc0819f1f30ba15bdb34cceffb9ef04d99f420f68eb75d901e9560b8749fc41"}, {file = "certifi-2020.6.20.tar.gz", hash = "sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3"}, @@ -593,10 +456,6 @@ chardet = [ {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, ] -charset-normalizer = [ - {file = "charset-normalizer-2.0.10.tar.gz", hash = "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd"}, - {file = "charset_normalizer-2.0.10-py3-none-any.whl", hash = "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455"}, -] colorama = [ {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, @@ -633,15 +492,6 @@ gitdb = [ {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"}, ] gitpython = [] -h11 = [ - {file = "h11-0.11.0-py2.py3-none-any.whl", hash = "sha256:ab6c335e1b6ef34b205d5ca3e228c9299cc7218b049819ec84a388c2525e5d87"}, - {file = "h11-0.11.0.tar.gz", hash = "sha256:3c6c61d69c6f13d41f1b80ab0322f1872702a3ba26e12aa864c928f6a43fbaab"}, -] -html2markdown = [ - {file = "html2markdown-0.1.7.tar.gz", hash = "sha256:92baf932c7f216be6d9459a191d45b6401e204bda7a5413febafa875512cfa8c"}, -] -httpcore = [] -httpx = [] idna = [ {file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, {file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, @@ -724,7 +574,6 @@ python-dateutil = [ {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, ] pyyaml = [] -rfc3986 = [] sentry-sdk = [] six = [ {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, @@ -734,11 +583,6 @@ smmap = [ {file = "smmap-3.0.4-py2.py3-none-any.whl", hash = "sha256:54c44c197c819d5ef1991799a7e30b662d1e520f2ac75c9efbeb54a742214cf4"}, {file = "smmap-3.0.4.tar.gz", hash = "sha256:9c98bbd1f9786d22f14b3d4126894d56befb835ec90cef151af566c7e19b5d24"}, ] -sniffio = [ - {file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"}, - {file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"}, -] -soupsieve = [] stevedore = [ {file = "stevedore-3.2.2-py3-none-any.whl", hash = "sha256:5e1ab03eaae06ef6ce23859402de785f08d97780ed774948ef16c4652c41bc62"}, {file = "stevedore-3.2.2.tar.gz", hash = "sha256:f845868b3a3a77a2489d226568abe7328b5c2d4f6a011cc759dfa99144a521f0"}, diff --git a/pyproject.toml b/pyproject.toml index c61c7887..7911973f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,8 +14,6 @@ asyncpg = "^0.25.0" sentry-sdk = "^1.5.12" Pillow = "^8.1" gitpython = "^3" -httpx = "^0.22.0" -html2markdown = "^0.1.7" aiocontextvars = "^0.2.2" [tool.poetry.dev-dependencies]