aboutsummaryrefslogtreecommitdiffstats
path: root/bot/converters.py
diff options
context:
space:
mode:
Diffstat (limited to 'bot/converters.py')
-rw-r--r--bot/converters.py73
1 files changed, 32 insertions, 41 deletions
diff --git a/bot/converters.py b/bot/converters.py
index 67525cd4d..2a3943831 100644
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -15,6 +15,7 @@ from discord.utils import DISCORD_EPOCH, snowflake_time
from bot.api import ResponseCodeError
from bot.constants import URLs
+from bot.exts.info.doc import _inventory_parser
from bot.utils.regex import INVITE_RE
from bot.utils.time import parse_duration_string
@@ -127,22 +128,20 @@ class ValidFilterListType(Converter):
return list_type
-class ValidPythonIdentifier(Converter):
+class PackageName(Converter):
"""
- A converter that checks whether the given string is a valid Python identifier.
+ A converter that checks whether the given string is a valid package name.
- This is used to have package names that correspond to how you would use the package in your
- code, e.g. `import package`.
-
- Raises `BadArgument` if the argument is not a valid Python identifier, and simply passes through
- the given argument otherwise.
+ Package names are used for stats and are restricted to the a-z and _ characters.
"""
- @staticmethod
- async def convert(ctx: Context, argument: str) -> str:
- """Checks whether the given string is a valid Python identifier."""
- if not argument.isidentifier():
- raise BadArgument(f"`{argument}` is not a valid Python identifier")
+ PACKAGE_NAME_RE = re.compile(r"[^a-z0-9_]")
+
+ @classmethod
+ async def convert(cls, ctx: Context, argument: str) -> str:
+ """Checks whether the given string is a valid package name."""
+ if cls.PACKAGE_NAME_RE.search(argument):
+ raise BadArgument("The provided package name is not valid; please only use the _, 0-9, and a-z characters.")
return argument
@@ -178,6 +177,27 @@ class ValidURL(Converter):
return url
+class Inventory(Converter):
+ """
+ Represents an Intersphinx inventory URL.
+
+ This converter checks whether intersphinx accepts the given inventory URL, and raises
+ `BadArgument` if that is not the case or if the url is unreachable.
+
+ Otherwise, it returns the url and the fetched inventory dict in a tuple.
+ """
+
+ @staticmethod
+ async def convert(ctx: Context, url: str) -> t.Tuple[str, _inventory_parser.InventoryDict]:
+ """Convert url to Intersphinx inventory URL."""
+ await ctx.trigger_typing()
+ if (inventory := await _inventory_parser.fetch_inventory(url)) is None:
+ raise BadArgument(
+ f"Failed to fetch inventory file after {_inventory_parser.FAILED_REQUEST_ATTEMPTS} attempts."
+ )
+ return url, inventory
+
+
class Snowflake(IDConverter):
"""
Converts to an int if the argument is a valid Discord snowflake.
@@ -216,35 +236,6 @@ class Snowflake(IDConverter):
return snowflake
-class Subreddit(Converter):
- """Forces a string to begin with "r/" and checks if it's a valid subreddit."""
-
- @staticmethod
- async def convert(ctx: Context, sub: str) -> str:
- """
- Force sub to begin with "r/" and check if it's a valid subreddit.
-
- If sub is a valid subreddit, return it prepended with "r/"
- """
- sub = sub.lower()
-
- if not sub.startswith("r/"):
- sub = f"r/{sub}"
-
- resp = await ctx.bot.http_session.get(
- "https://www.reddit.com/subreddits/search.json",
- params={"q": sub}
- )
-
- json = await resp.json()
- if not json["data"]["children"]:
- raise BadArgument(
- f"The subreddit `{sub}` either doesn't exist, or it has no posts."
- )
-
- return sub
-
-
class TagNameConverter(Converter):
"""
Ensure that a proposed tag name is valid.