aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/utilities/wtf_python.py
blob: 29a9611ca5256f9daf8919ecd64cc8947df392e6 (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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import logging
import random
import re

import rapidfuzz
from discord import Embed, File
from discord.ext import commands, tasks

from bot import constants
from bot.bot import Bot

log = logging.getLogger(__name__)

WTF_PYTHON_RAW_URL = "http://raw.githubusercontent.com/satwikkansal/wtfpython/master/"
BASE_URL = "https://github.com/satwikkansal/wtfpython"
LOGO_PATH = "./bot/resources/utilities/wtf_python_logo.jpg"

ERROR_MESSAGE = f"""
Unknown WTF Python Query. Please try to reformulate your query.

**Examples**:
```md
{constants.Client.prefix}wtf wild imports
{constants.Client.prefix}wtf subclass
{constants.Client.prefix}wtf del
```
If the problem persists send a message in <#{constants.Channels.dev_contrib}>
"""

MINIMUM_CERTAINTY = 55


class WTFPython(commands.Cog):
    """Cog that allows getting WTF Python entries from the WTF Python repository."""

    def __init__(self, bot: Bot):
        self.bot = bot
        self.headers: dict[str, str] = {}
        self.fetch_readme.start()

    @tasks.loop(minutes=60)
    async def fetch_readme(self) -> None:
        """Gets the content of README.md from the WTF Python Repository."""
        async with self.bot.http_session.get(f"{WTF_PYTHON_RAW_URL}README.md") as resp:
            log.trace("Fetching the latest WTF Python README.md")
            if resp.status == 200:
                raw = await resp.text()
                self.parse_readme(raw)

    def parse_readme(self, data: str) -> None:
        """
        Parses the README.md into a dict.

        It parses the readme into the `self.headers` dict,
        where the key is the heading and the value is the
        link to the heading.
        """
        # Match the start of examples, until the end of the table of contents (toc)
        table_of_contents = re.search(
            r"\[👀 Examples\]\(#-examples\)\n([\w\W]*)<!-- tocstop -->", data
        )[0].split("\n")

        for header in list(map(str.strip, table_of_contents)):
            match = re.search(r"\[▶ (.*)\]\((.*)\)", header)
            if match:
                hyper_link = match[0].split("(")[1].replace(")", "")
                self.headers[match[0]] = f"{BASE_URL}/{hyper_link}"

    def fuzzy_match_header(self, query: str) -> str | None:
        """
        Returns the fuzzy match of a query if its ratio is above "MINIMUM_CERTAINTY" else returns None.

        "MINIMUM_CERTAINTY" is the lowest score at which the fuzzy match will return a result.
        The certainty returned by rapidfuzz.process.extractOne is a score between 0 and 100,
        with 100 being a perfect match.
        """
        match, certainty, _ = rapidfuzz.process.extractOne(query, self.headers.keys())
        return match if certainty > MINIMUM_CERTAINTY else None

    @commands.command(aliases=("wtf",))
    async def wtf_python(self, ctx: commands.Context, *, query: str | None = None) -> None:
        """
        Search WTF Python repository.

        Gets the link of the fuzzy matched query from https://github.com/satwikkansal/wtfpython.
        Usage:
            --> .wtf wild imports
        """
        if query is None:
            no_query_embed = Embed(
                title="WTF Python?!",
                colour=constants.Colours.dark_green,
                description="A repository filled with suprising snippets that can make you say WTF?!\n\n"
                f"[Go to the Repository]({BASE_URL})"
            )
            logo = File(LOGO_PATH, filename="wtf_logo.jpg")
            no_query_embed.set_thumbnail(url="attachment://wtf_logo.jpg")
            await ctx.send(embed=no_query_embed, file=logo)
            return

        if len(query) > 50:
            embed = Embed(
                title=random.choice(constants.ERROR_REPLIES),
                description=ERROR_MESSAGE,
                colour=constants.Colours.soft_red,
            )
            match = None
        else:
            match = self.fuzzy_match_header(query)

        if not match:
            embed = Embed(
                title=random.choice(constants.ERROR_REPLIES),
                description=ERROR_MESSAGE,
                colour=constants.Colours.soft_red,
            )
            await ctx.send(embed=embed)
            return

        embed = Embed(
            title="WTF Python?!",
            colour=constants.Colours.dark_green,
            description=f"""Search result for '{query}': {match.split("]")[0].replace("[", "")}
            [Go to Repository Section]({self.headers[match]})""",
        )
        logo = File(LOGO_PATH, filename="wtf_logo.jpg")
        embed.set_thumbnail(url="attachment://wtf_logo.jpg")
        await ctx.send(embed=embed, file=logo)

    def cog_unload(self) -> None:
        """Unload the cog and cancel the task."""
        self.fetch_readme.cancel()


async def setup(bot: Bot) -> None:
    """Load the WTFPython Cog."""
    await bot.add_cog(WTFPython(bot))