Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions monty/exts/utils/xkcd.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import random
from html.parser import HTMLParser
from typing import Any, TypedDict

import disnake
from disnake.ext import commands, tasks
from rapidfuzz import process
from typing_extensions import NotRequired

from monty.bot import Monty
Expand All @@ -29,6 +31,40 @@
safe_title: str
extra_parts: NotRequired[dict[str, Any]]

# I'm sure there is a better way to do any of this, but this worked
class ComicParser(HTMLParser):
def __init__(self):
super().__init__()
self.comic = False
self.list_of_comics = False
self.comics: dict[str, str] = {}
self.number = None

def handle_starttag(self, tag, attrs):

Check failure on line 43 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN001)

monty/exts/utils/xkcd.py:43:36: ANN001 Missing type annotation for function argument `attrs`

Check failure on line 43 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN001)

monty/exts/utils/xkcd.py:43:31: ANN001 Missing type annotation for function argument `tag`

Check failure on line 43 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (D102)

monty/exts/utils/xkcd.py:43:9: D102 Missing docstring in public method

Check failure on line 43 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN201)

monty/exts/utils/xkcd.py:43:9: ANN201 Missing return type annotation for public function `handle_starttag`
if tag == "a" and self.list_of_comics:
self.comic = True
self.number = None
for attr in attrs:
if attr[0] == "href":
self.number = attr[1].strip("/")

Check failure on line 49 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / pyright

"strip" is not a known attribute of "None" (reportOptionalMemberAccess)
if (
tag == "div"
and len(attrs) > 0
and attrs[0][0] == "id"
and attrs[0][1] == "middleContainer"
):
self.list_of_comics = True

def handle_data(self, data):

Check failure on line 58 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN001)

monty/exts/utils/xkcd.py:58:27: ANN001 Missing type annotation for function argument `data`

Check failure on line 58 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (D102)

monty/exts/utils/xkcd.py:58:9: D102 Missing docstring in public method

Check failure on line 58 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN201)

monty/exts/utils/xkcd.py:58:9: ANN201 Missing return type annotation for public function `handle_data`
if not self.comic:
return
self.comics[data.strip()] = self.number

Check failure on line 61 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / pyright

Argument of type "str | None" cannot be assigned to parameter "value" of type "str" in function "__setitem__"   Type "str | None" is not assignable to type "str"     "None" is not assignable to "str" (reportArgumentType)

def handle_endtag(self, tag):

Check failure on line 63 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN001)

monty/exts/utils/xkcd.py:63:29: ANN001 Missing type annotation for function argument `tag`

Check failure on line 63 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (D102)

monty/exts/utils/xkcd.py:63:9: D102 Missing docstring in public method

Check failure on line 63 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / lint

Ruff (ANN201)

monty/exts/utils/xkcd.py:63:9: ANN201 Missing return type annotation for public function `handle_endtag`
if self.comic and tag == "a":
self.comic = False
if self.list_of_comics and tag == "div":
self.list_of_comics = False

class XKCD(
commands.Cog,
Expand All @@ -42,6 +78,7 @@
def __init__(self, bot: Monty) -> None:
self.bot = bot
self.latest_comic_info: XkcdDict | None = None
self.comics: dict[str, str] | None = None
self.get_latest_comic_info.start()

def cog_unload(self) -> None:
Expand All @@ -56,6 +93,13 @@
self.latest_comic_info = await resp.json()
else:
log.debug(f"Failed to get latest XKCD comic information. Status code {resp.status}")
async with self.bot.http_session.get(f"{BASE_URL}/archive") as resp:
if resp.status == 200:
parser = ComicParser()
parser.feed(resp.text) # parse /archive for all comic titles and comic number

Check failure on line 99 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / pyright

Argument of type "(encoding: str | None = None, errors: str = "strict") -> CoroutineType[Any, Any, str]" cannot be assigned to parameter "data" of type "str" in function "feed"   "MethodType" is not assignable to "str" (reportArgumentType)
self.comics = parser.comics
else:
log.debug(f"Failed to get latest list of XKCD comics. Status code {resp.status}")

@commands.slash_command(name="xkcd")
async def xkcd(self, _: disnake.ApplicationCommandInteraction) -> None:
Expand Down Expand Up @@ -142,6 +186,17 @@

await self.send_xkcd(inter, info)

@number.autocomplete("comic")
async def number_autocomplete(self, _: disnake.CommandInteraction, query: str) -> list[disnake.OptionChoice]:
"""Autocomplete names of XKCD comics when searching for number."""
searches = process.extract(query, self.comics.keys(), limit=5)

Check failure on line 192 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / pyright

"keys" is not a known attribute of "None" (reportOptionalMemberAccess)
return [
# Probably shouldn't be returning value as a str, but I am.
disnake.OptionChoice(name=comic, value=self.comics[comic])

Check failure on line 195 in monty/exts/utils/xkcd.py

View workflow job for this annotation

GitHub Actions / pyright

Object of type "None" is not subscriptable (reportOptionalSubscript)
for comic
in [res[0] for res in searches]
]

@xkcd.sub_command()
async def random(self, inter: disnake.ApplicationCommandInteraction) -> None:
"""View a random xkcd comic."""
Expand Down
Loading