aboutsummaryrefslogtreecommitdiffstats
path: root/arthur/exts/fun/quotes.py
blob: 1c2698ce3674929b6ad1003ec4b9a00c946b7e39 (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
58
59
60
61
62
63
64
65
66
67
import random
from typing import NamedTuple

import aiohttp
from bs4 import BeautifulSoup
from discord.ext import commands

from arthur.bot import KingArthur
from arthur.log import logger


class Quote(NamedTuple):
    """A data structure to hold quotes and their source."""

    text: str
    source: str | None

    def __str__(self):
        return f"{self.text}\n-- {self.source}"


class QuotesCog(commands.Cog):
    """A cog that sends programming quotes."""

    def __init__(self, bot: KingArthur) -> None:
        self.bot = bot
        self.quotes = []

    async def cog_load(self) -> None:
        """Fetch the quotes to be used."""
        try:
            async with self.bot.http_session.get(
                "http://quotes.cat-v.org/programming/"
            ) as response:
                content = await response.content.read()
        except aiohttp.ClientResponseError:
            logger.exception("Couldn't fetch programming quotes.")
            return

        soup = BeautifulSoup(content, "html.parser")
        prev_text = None

        for item in soup.article.find_all("p"):
            text = item.get_text().replace("\xa0", "")

            if prev_text is not None:
                if text.startswith("—"):
                    self.quotes.append(Quote(text=prev_text, source=text.removeprefix("— ")))
                elif not prev_text.startswith("—"):
                    self.quotes.append(Quote(text=prev_text, source=None))

            prev_text = text

    @commands.command(name="quote")
    async def quote(self, ctx: commands.Context) -> None:
        """Send a random programming quote."""
        if not self.quotes:
            await ctx.reply(":x: Couldn't fetch quotes, try reloading the cog.")
            return

        quote = random.choice(self.quotes)
        await ctx.reply(str(quote))


async def setup(bot: KingArthur) -> None:
    """Load the QuotesCog."""
    await bot.add_cog(QuotesCog(bot))