aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/evergreen/cheatsheet.py
blob: 86fae16724523c566009b6fb9e71632f6d6c3f11 (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
import random
import re
import typing as t
from urllib.parse import quote_plus

from discord import Embed
from discord.ext import commands
from discord.ext.commands import BucketType, Context

from bot import constants
from bot.bot import Bot
from bot.constants import Categories, Channels, Colours, ERROR_REPLIES
from bot.utils.decorators import whitelist_override

ERROR_MESSAGE = f"""
Unknown cheat sheet. Please try to reformulate your query.

**Examples**:
```md
{constants.Client.prefix}cht read json
{constants.Client.prefix}cht hello world
{constants.Client.prefix}cht lambda
```
If the problem persists send a message in <#{Channels.dev_contrib}>
"""

URL = "https://cheat.sh/python/{search}"
ESCAPE_TT = str.maketrans({"`": "\\`"})
ANSI_RE = re.compile(r"\x1b\[.*?m")
# We need to pass headers as curl otherwise it would default to aiohttp which would return raw html.
HEADERS = {"User-Agent": "curl/7.68.0"}


class CheatSheet(commands.Cog):
    """Commands that sends a result of a cht.sh search in code blocks."""

    def __init__(self, bot: Bot):
        self.bot = bot

    @staticmethod
    def fmt_error_embed() -> Embed:
        """
        Format the Error Embed.

        If the cht.sh search returned 404, overwrite it to send a custom error embed.
        link -> https://github.com/chubin/cheat.sh/issues/198
        """
        embed = Embed(
            title=random.choice(ERROR_REPLIES),
            description=ERROR_MESSAGE,
            colour=Colours.soft_red
        )
        return embed

    def result_fmt(self, url: str, body_text: str) -> t.Tuple[bool, t.Union[str, Embed]]:
        """Format Result."""
        if body_text.startswith("#  404 NOT FOUND"):
            embed = self.fmt_error_embed()
            return True, embed

        body_space = min(1986 - len(url), 1000)

        if len(body_text) > body_space:
            description = (f"**Result Of cht.sh**\n"
                           f"```python\n{body_text[:body_space]}\n"
                           f"... (truncated - too many lines)```\n"
                           f"Full results: {url} ")
        else:
            description = (f"**Result Of cht.sh**\n"
                           f"```python\n{body_text}```\n"
                           f"{url}")
        return False, description

    @commands.command(
        name="cheat",
        aliases=("cht.sh", "cheatsheet", "cheat-sheet", "cht"),
    )
    @commands.cooldown(1, 10, BucketType.user)
    @whitelist_override(categories=[Categories.help_in_use])
    async def cheat_sheet(self, ctx: Context, *search_terms: str) -> None:
        """
        Search cheat.sh.

        Gets a post from https://cheat.sh/python/ by default.
        Usage:
        --> .cht read json
        """
        async with ctx.typing():
            search_string = quote_plus(" ".join(search_terms))

            async with self.bot.http_session.get(
                    URL.format(search=search_string), headers=HEADERS
            ) as response:
                result = ANSI_RE.sub("", await response.text()).translate(ESCAPE_TT)

            is_embed, description = self.result_fmt(
                URL.format(search=search_string),
                result
            )
            if is_embed:
                await ctx.send(embed=description)
            else:
                await ctx.send(content=description)


def setup(bot: Bot) -> None:
    """Load the CheatSheet cog."""
    bot.add_cog(CheatSheet(bot))