import logging import re from typing import Union, Dict from datetime import timedelta from discord.ext.commands.converter import Converter from redbot.core import commands log = logging.getLogger("red.cogs.mutes") # the following regex is slightly modified from Red # it's changed to be slightly more strict on matching with finditer # this is to prevent "empty" matches when parsing the full reason # This is also designed more to allow time interval at the beginning or the end of the mute # to account for those times when you think of adding time *after* already typing out the reason # https://github.com/Cog-Creators/Red-DiscordBot/blob/V3/develop/redbot/core/commands/converter.py#L55 TIME_RE_STRING = r"|".join( [ r"((?P\d+?)\s?(weeks?|w))", r"((?P\d+?)\s?(days?|d))", r"((?P\d+?)\s?(hours?|hrs|hr?))", r"((?P\d+?)\s?(minutes?|mins?|m(?!o)))", # prevent matching "months" r"((?P\d+?)\s?(seconds?|secs?|s))", ] ) TIME_RE = re.compile(TIME_RE_STRING, re.I) TIME_SPLIT = re.compile(r"t(?:ime)?=") class MuteTime(Converter): """ This will parse my defined multi response pattern and provide usable formats to be used in multiple reponses """ async def convert( self, ctx: commands.Context, argument: str ) -> Dict[str, Union[timedelta, str, None]]: time_split = TIME_SPLIT.split(argument) result: Dict[str, Union[timedelta, str, None]] = {} if time_split: maybe_time = time_split[-1] else: maybe_time = argument time_data = {} for time in TIME_RE.finditer(maybe_time): argument = argument.replace(time[0], "") for k, v in time.groupdict().items(): if v: time_data[k] = int(v) if time_data: result["duration"] = timedelta(**time_data) result["reason"] = argument return result