From 04f122348eca25dbbf44afdcc6fcd417aa98bf89 Mon Sep 17 00:00:00 2001 From: Rohan Date: Wed, 2 Dec 2020 21:53:29 +0530 Subject: Add Subreddit converter. --- bot/utils/converters.py | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'bot/utils/converters.py') diff --git a/bot/utils/converters.py b/bot/utils/converters.py index 228714c9..27804170 100644 --- a/bot/utils/converters.py +++ b/bot/utils/converters.py @@ -1,5 +1,6 @@ import discord -from discord.ext.commands.converter import MessageConverter +from discord.ext.commands import BadArgument, Context +from discord.ext.commands.converter import Converter, MessageConverter class WrappedMessageConverter(MessageConverter): @@ -14,3 +15,32 @@ class WrappedMessageConverter(MessageConverter): argument = argument[1:-1] return await super().convert(ctx, argument) + + +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 -- cgit v1.2.3 From 888f83170bce384315a0a5c47b87b7ffbfb5d8ea Mon Sep 17 00:00:00 2001 From: ToxicKidz <78174417+ToxicKidz@users.noreply.github.com> Date: Wed, 5 May 2021 13:46:08 -0400 Subject: chore: Add all of the converters into bot/utils/converters.py --- bot/exts/evergreen/minesweeper.py | 28 +------------- bot/exts/evergreen/source.py | 23 +----------- bot/exts/evergreen/space.py | 19 ++-------- bot/utils/converters.py | 77 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 67 deletions(-) (limited to 'bot/utils/converters.py') diff --git a/bot/exts/evergreen/minesweeper.py b/bot/exts/evergreen/minesweeper.py index bd28d365..7a31dfde 100644 --- a/bot/exts/evergreen/minesweeper.py +++ b/bot/exts/evergreen/minesweeper.py @@ -8,6 +8,7 @@ from discord.ext import commands from bot.bot import Bot from bot.constants import Client +from bot.utils.converters import CoordinateConverter from bot.utils.exceptions import UserNotPlayingError from bot.utils.extensions import invoke_help_command @@ -32,33 +33,6 @@ MESSAGE_MAPPING = { log = logging.getLogger(__name__) -class CoordinateConverter(commands.Converter): - """Converter for Coordinates.""" - - async def convert(self, ctx: commands.Context, coordinate: str) -> typing.Tuple[int, int]: - """Take in a coordinate string and turn it into an (x, y) tuple.""" - if not 2 <= len(coordinate) <= 3: - raise commands.BadArgument("Invalid co-ordinate provided.") - - coordinate = coordinate.lower() - if coordinate[0].isalpha(): - digit = coordinate[1:] - letter = coordinate[0] - else: - digit = coordinate[:-1] - letter = coordinate[-1] - - if not digit.isdigit(): - raise commands.BadArgument - - x = ord(letter) - ord("a") - y = int(digit) - 1 - - if (not 0 <= x <= 9) or (not 0 <= y <= 9): - raise commands.BadArgument - return x, y - - GameBoard = typing.List[typing.List[typing.Union[str, int]]] diff --git a/bot/exts/evergreen/source.py b/bot/exts/evergreen/source.py index 685b3111..8fb72143 100644 --- a/bot/exts/evergreen/source.py +++ b/bot/exts/evergreen/source.py @@ -1,32 +1,13 @@ import inspect from pathlib import Path -from typing import Optional, Tuple, Union +from typing import Optional, Tuple from discord import Embed from discord.ext import commands from bot.bot import Bot from bot.constants import Source - -SourceType = Union[commands.Command, commands.Cog, str, commands.ExtensionNotLoaded] - - -class SourceConverter(commands.Converter): - """Convert an argument into a help command, tag, command, or cog.""" - - async def convert(self, ctx: commands.Context, argument: str) -> SourceType: - """Convert argument into source object.""" - cog = ctx.bot.get_cog(argument) - if cog: - return cog - - cmd = ctx.bot.get_command(argument) - if cmd: - return cmd - - raise commands.BadArgument( - f"Unable to convert `{argument}` to valid command or Cog." - ) +from bot.utils.converters import SourceConverter, SourceType class BotSource(commands.Cog): diff --git a/bot/exts/evergreen/space.py b/bot/exts/evergreen/space.py index 7d83dbfb..77b63946 100644 --- a/bot/exts/evergreen/space.py +++ b/bot/exts/evergreen/space.py @@ -1,15 +1,16 @@ import logging import random from datetime import date, datetime -from typing import Any, Dict, Optional, Union +from typing import Any, Dict, Optional from urllib.parse import urlencode from discord import Embed from discord.ext import tasks -from discord.ext.commands import BadArgument, Cog, Context, Converter, group +from discord.ext.commands import Cog, Context, group from bot.bot import Bot from bot.constants import Tokens +from bot.utils.converters import DateConverter from bot.utils.extensions import invoke_help_command logger = logging.getLogger(__name__) @@ -21,20 +22,6 @@ NASA_EPIC_BASE_URL = "https://epic.gsfc.nasa.gov" APOD_MIN_DATE = date(1995, 6, 16) -class DateConverter(Converter): - """Parse SOL or earth date (in format YYYY-MM-DD) into `int` or `datetime`. When invalid input, raise error.""" - - async def convert(self, ctx: Context, argument: str) -> Union[int, datetime]: - """Parse date (SOL or earth) into `datetime` or `int`. When invalid value, raise error.""" - if argument.isdigit(): - return int(argument) - try: - date = datetime.strptime(argument, "%Y-%m-%d") - except ValueError: - raise BadArgument(f"Can't convert `{argument}` to `datetime` in format `YYYY-MM-DD` or `int` in SOL.") - return date - - class Space(Cog): """Space Cog contains commands, that show images, facts or other information about space.""" diff --git a/bot/utils/converters.py b/bot/utils/converters.py index 228714c9..98607087 100644 --- a/bot/utils/converters.py +++ b/bot/utils/converters.py @@ -1,11 +1,15 @@ +from datetime import datetime +from typing import Tuple, Union + import discord -from discord.ext.commands.converter import MessageConverter +from discord.ext import commands -class WrappedMessageConverter(MessageConverter): +class WrappedMessageConverter(commands.MessageConverter): """A converter that handles embed-suppressed links like .""" - async def convert(self, ctx: discord.ext.commands.Context, argument: str) -> discord.Message: + @staticmethod + async def convert(ctx: commands.Context, argument: str) -> discord.Message: """Wrap the commands.MessageConverter to handle <> delimited message links.""" # It's possible to wrap a message in [<>] as well, and it's supported because its easy if argument.startswith("[") and argument.endswith("]"): @@ -14,3 +18,70 @@ class WrappedMessageConverter(MessageConverter): argument = argument[1:-1] return await super().convert(ctx, argument) + + +class CoordinateConverter(commands.Converter): + """Converter for Coordinates.""" + + @staticmethod + async def convert(ctx: commands.Context, coordinate: str) -> Tuple[int, int]: + """Take in a coordinate string and turn it into an (x, y) tuple.""" + if len(coordinate) not in (2, 3): + raise commands.BadArgument("Invalid co-ordinate provided.") + + coordinate = coordinate.lower() + if coordinate[0].isalpha(): + digit = coordinate[1:] + letter = coordinate[0] + else: + digit = coordinate[:-1] + letter = coordinate[-1] + + if not digit.isdigit(): + raise commands.BadArgument + + x = ord(letter) - ord("a") + y = int(digit) - 1 + + if (not 0 <= x <= 9) or (not 0 <= y <= 9): + raise commands.BadArgument + return x, y + + +SourceType = Union[commands.Command, commands.Cog] + + +class SourceConverter(commands.Converter): + """Convert an argument into a command or cog.""" + + @staticmethod + async def convert(ctx: commands.Context, argument: str) -> SourceType: + """Convert argument into source object.""" + cog = ctx.bot.get_cog(argument) + if cog: + return cog + + cmd = ctx.bot.get_command(argument) + if cmd: + return cmd + + raise commands.BadArgument( + f"Unable to convert `{argument}` to valid command or Cog." + ) + + +class DateConverter(commands.Converter): + """Parse SOL or earth date (in format YYYY-MM-DD) into `int` or `datetime`. When invalid input, raise error.""" + + @staticmethod + async def convert(ctx: commands.Context, argument: str) -> Union[int, datetime]: + """Parse date (SOL or earth) into `datetime` or `int`. When invalid value, raise error.""" + if argument.isdigit(): + return int(argument) + try: + date = datetime.strptime(argument, "%Y-%m-%d") + except ValueError: + raise commands.BadArgument( + f"Can't convert `{argument}` to `datetime` in format `YYYY-MM-DD` or `int` in SOL." + ) + return date -- cgit v1.2.3 From 4503a3307b989b251826f36e9370bda7471640b3 Mon Sep 17 00:00:00 2001 From: ToxicKidz Date: Sun, 9 May 2021 17:49:53 -0400 Subject: fix: Use str.isdecimal instead of str.isdigit --- bot/utils/__init__.py | 4 ++-- bot/utils/converters.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'bot/utils/converters.py') diff --git a/bot/utils/__init__.py b/bot/utils/__init__.py index 2fac2086..09a4dfc3 100644 --- a/bot/utils/__init__.py +++ b/bot/utils/__init__.py @@ -51,7 +51,7 @@ async def disambiguate( choices = (f"{index}: {entry}" for index, entry in enumerate(entries, start=1)) def check(message: discord.Message) -> bool: - return (message.content.isdigit() + return (message.content.isdecimal() and message.author == ctx.author and message.channel == ctx.channel) @@ -87,7 +87,7 @@ async def disambiguate( except asyncio.TimeoutError: raise BadArgument("Timed out.") - # Guaranteed to not error because of isdigit() in check + # Guaranteed to not error because of isdecimal() in check index = int(result.content) try: diff --git a/bot/utils/converters.py b/bot/utils/converters.py index 98607087..72b64848 100644 --- a/bot/utils/converters.py +++ b/bot/utils/converters.py @@ -37,7 +37,7 @@ class CoordinateConverter(commands.Converter): digit = coordinate[:-1] letter = coordinate[-1] - if not digit.isdigit(): + if not digit.isdecimal(): raise commands.BadArgument x = ord(letter) - ord("a") @@ -76,7 +76,7 @@ class DateConverter(commands.Converter): @staticmethod async def convert(ctx: commands.Context, argument: str) -> Union[int, datetime]: """Parse date (SOL or earth) into `datetime` or `int`. When invalid value, raise error.""" - if argument.isdigit(): + if argument.isdecimal(): return int(argument) try: date = datetime.strptime(argument, "%Y-%m-%d") -- cgit v1.2.3