diff options
Diffstat (limited to 'bot/exts/info/pypi.py')
-rw-r--r-- | bot/exts/info/pypi.py | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/bot/exts/info/pypi.py b/bot/exts/info/pypi.py new file mode 100644 index 000000000..2e42e7d6b --- /dev/null +++ b/bot/exts/info/pypi.py @@ -0,0 +1,78 @@ +import itertools +import logging +import random +import re + +from discord import Embed +from discord.ext.commands import Cog, Context, command +from discord.utils import escape_markdown + +from bot.bot import Bot +from bot.constants import Colours, NEGATIVE_REPLIES, RedirectOutput + +URL = "https://pypi.org/pypi/{package}/json" +PYPI_ICON = "https://cdn.discordapp.com/emojis/766274397257334814.png" + +PYPI_COLOURS = itertools.cycle((Colours.yellow, Colours.blue, Colours.white)) + +ILLEGAL_CHARACTERS = re.compile(r"[^-_.a-zA-Z0-9]+") +INVALID_INPUT_DELETE_DELAY = RedirectOutput.delete_delay + +log = logging.getLogger(__name__) + + +class PyPi(Cog): + """Cog for getting information about PyPi packages.""" + + def __init__(self, bot: Bot): + self.bot = bot + + @command(name="pypi", aliases=("package", "pack")) + async def get_package_info(self, ctx: Context, package: str) -> None: + """Provide information about a specific package from PyPI.""" + embed = Embed(title=random.choice(NEGATIVE_REPLIES), colour=Colours.soft_red) + embed.set_thumbnail(url=PYPI_ICON) + + error = True + + if characters := re.search(ILLEGAL_CHARACTERS, package): + embed.description = f"Illegal character(s) passed into command: '{escape_markdown(characters.group(0))}'" + + else: + async with self.bot.http_session.get(URL.format(package=package)) as response: + if response.status == 404: + embed.description = "Package could not be found." + + elif response.status == 200 and response.content_type == "application/json": + response_json = await response.json() + info = response_json["info"] + + embed.title = f"{info['name']} v{info['version']}" + + embed.url = info["package_url"] + embed.colour = next(PYPI_COLOURS) + + summary = escape_markdown(info["summary"]) + + # Summary could be completely empty, or just whitespace. + if summary and not summary.isspace(): + embed.description = summary + else: + embed.description = "No summary provided." + + error = False + + else: + embed.description = "There was an error when fetching your PyPi package." + log.trace(f"Error when fetching PyPi package: {response.status}.") + + if error: + await ctx.send(embed=embed, delete_after=INVALID_INPUT_DELETE_DELAY) + await ctx.message.delete(delay=INVALID_INPUT_DELETE_DELAY) + else: + await ctx.send(embed=embed) + + +def setup(bot: Bot) -> None: + """Load the PyPi cog.""" + bot.add_cog(PyPi(bot)) |