diff --git a/didier/cogs/fun.py b/didier/cogs/fun.py index 6a89833..e147f49 100644 --- a/didier/cogs/fun.py +++ b/didier/cogs/fun.py @@ -9,6 +9,7 @@ from database.crud.dad_jokes import get_random_dad_joke from database.crud.memes import get_all_memes, get_meme_by_name from didier import Didier from didier.data.apis.imgflip import generate_meme +from didier.data.apis.xkcd import fetch_xkcd_post from didier.exceptions.no_match import expect from didier.menus.memes import MemeSource from didier.utils.discord import constants @@ -132,6 +133,18 @@ class Fun(commands.Cog): """Autocompletion for the 'template'-parameter""" return self.client.database_caches.memes.get_autocomplete_suggestions(current) + @commands.hybrid_command(name="xkcd") + @app_commands.rename(comic_id="id") + async def xkcd(self, ctx: commands.Context, comic_id: Optional[int] = None): + """Fetch comic `#id` from xkcd + + If no argument to `id` is passed, this fetches today's comic instead. + """ + async with ctx.typing(): + post = await fetch_xkcd_post(self.client.http_session, num=comic_id) + + await ctx.reply(embed=post.to_embed(), mention_author=False, ephemeral=False) + async def setup(client: Didier): """Load the cog""" diff --git a/didier/data/apis/xkcd.py b/didier/data/apis/xkcd.py new file mode 100644 index 0000000..c0ad766 --- /dev/null +++ b/didier/data/apis/xkcd.py @@ -0,0 +1,16 @@ +from typing import Optional + +from aiohttp import ClientSession + +from didier.data.embeds.xkcd import XKCDPost +from didier.utils.http.requests import ensure_get + +__all__ = ["fetch_xkcd_post"] + + +async def fetch_xkcd_post(http_session: ClientSession, *, num: Optional[int] = None) -> XKCDPost: + """Fetch a post from xkcd.com""" + url = "https://xkcd.com" + (f"/{num}" if num is not None else "") + "/info.0.json" + + async with ensure_get(http_session, url) as response: + return XKCDPost.parse_obj(response) diff --git a/didier/data/embeds/xkcd.py b/didier/data/embeds/xkcd.py new file mode 100644 index 0000000..e4ae80f --- /dev/null +++ b/didier/data/embeds/xkcd.py @@ -0,0 +1,28 @@ +import discord +from overrides import overrides + +from didier.data.embeds.base import EmbedPydantic +from didier.utils.discord.colours import xkcd_blue + +__all__ = ["XKCDPost"] + + +class XKCDPost(EmbedPydantic): + """A post from xkcd.com""" + + num: int + img: str + safe_title: str + day: int + month: int + year: int + + @overrides + def to_embed(self, **kwargs) -> discord.Embed: + embed = discord.Embed(colour=xkcd_blue(), title=self.safe_title) + + embed.set_author(name=f"XKCD #{self.num}") + embed.set_image(url=self.img) + embed.set_footer(text=f"Published {self.day:02d}/{self.month:02d}/{self.year}") + + return embed diff --git a/didier/utils/discord/colours.py b/didier/utils/discord/colours.py index dc58608..d5dce3c 100644 --- a/didier/utils/discord/colours.py +++ b/didier/utils/discord/colours.py @@ -9,6 +9,7 @@ __all__ = [ "google_blue", "steam_blue", "urban_dictionary_green", + "xkcd_blue", ] @@ -46,3 +47,7 @@ def steam_blue() -> discord.Colour: def urban_dictionary_green() -> discord.Colour: return discord.Colour.from_rgb(220, 255, 0) + + +def xkcd_blue() -> discord.Colour: + return discord.Colour.from_rgb(150, 168, 200)