aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Den4200 <[email protected]>2020-07-01 16:37:48 +0000
committerGravatar Den4200 <[email protected]>2020-07-01 16:37:48 +0000
commitbd041ef4363ad8750d619d97fb7e8f3a4c6ae757 (patch)
treea3336e27cc7aea31af80eab97d303d370c1316a7
parentAdd some logging for the Slowmode cog (diff)
Create DurationDelta converter and humanize timedelta output for Slowmode cog.
The DurationDelta converter will allow the Slowmode cog to use a formatted timestamp instead of an integer representing seconds. I created a new converter because the Duration converter returned a datetime.datetime object, instead of a time delta. Joe mentioned that I could just subtract the datetime.datetime object from datetime.utcnow(), but there is a small delay between conversion and when the function is actually executed. This caused something like `!slowmode set #python-general 5s` to set the slowmode delay to 4 seconds instead of 5. Now, with this new converter, the set command can be invoked using a formatted timestamp like so: `!slowmode set #python-general 4h23M19s`. This would set the slowmode delay in #python-general to 4 hours, 23 minutes, and 19 seconds. Of course that delay would be quite overkill for #python-general, but that's just for the sake of this example.
-rw-r--r--bot/cogs/slowmode.py31
-rw-r--r--bot/converters.py22
2 files changed, 39 insertions, 14 deletions
diff --git a/bot/cogs/slowmode.py b/bot/cogs/slowmode.py
index 7bbd61623..898f4bf52 100644
--- a/bot/cogs/slowmode.py
+++ b/bot/cogs/slowmode.py
@@ -1,11 +1,15 @@
import logging
+from datetime import datetime
+from dateutil.relativedelta import relativedelta
from discord import TextChannel
from discord.ext.commands import Cog, Context, group
from bot.bot import Bot
from bot.constants import Emojis, MODERATION_ROLES
+from bot.converters import DurationDelta
from bot.decorators import with_role
+from bot.utils import time
log = logging.getLogger(__name__)
@@ -24,28 +28,35 @@ class Slowmode(Cog):
@slowmode_group.command(name='get', aliases=['g'])
async def get_slowmode(self, ctx: Context, channel: TextChannel) -> None:
"""Get the slowmode delay for a given text channel."""
- slowmode_delay = channel.slowmode_delay
- await ctx.send(f'The slowmode delay for {channel.mention} is {slowmode_delay} seconds.')
+ delay = relativedelta(seconds=channel.slowmode_delay)
+ await ctx.send(f'The slowmode delay for {channel.mention} is {time.humanize_delta(delay, precision=3)}.')
@slowmode_group.command(name='set', aliases=['s'])
@with_role(*MODERATION_ROLES)
- async def set_slowmode(self, ctx: Context, channel: TextChannel, seconds: int) -> None:
+ async def set_slowmode(self, ctx: Context, channel: TextChannel, delay: DurationDelta) -> None:
"""Set the slowmode delay for a given text channel."""
- if 0 <= seconds <= 21600:
- await channel.edit(slowmode_delay=seconds)
+ # Convert `dateutil.relativedelta.relativedelta` to `datetime.timedelta`
+ # Must do this to get the delta in a particular unit of time
+ utcnow = datetime.utcnow()
+ slowmode_delay = (utcnow + delay - utcnow).seconds
+
+ humanized_delay = time.humanize_delta(delay, precision=3)
+
+ if 0 <= slowmode_delay <= 21600:
+ await channel.edit(slowmode_delay=slowmode_delay)
await ctx.send(
- f'{Emojis.check_mark} The slowmode delay for {channel.mention} is now {seconds} seconds.'
+ f'{Emojis.check_mark} The slowmode delay for {channel.mention} is now {humanized_delay}.'
)
- log.info(f'{ctx.author} set the slowmode delay for #{channel} to {seconds} seconds.')
+ log.info(f'{ctx.author} set the slowmode delay for #{channel} to {humanized_delay}.')
else:
await ctx.send(
- f'{Emojis.cross_mark} The slowmode delay must be between 0 and 21600 seconds.'
+ f'{Emojis.cross_mark} The slowmode delay must be between 0 and 6 hours.'
)
log.info(
- f'{ctx.author} tried to set the slowmode delay of #{channel} to {seconds} seconds, '
- 'which is not between 0 and 21600 seconds.'
+ f'{ctx.author} tried to set the slowmode delay of #{channel} to {humanized_delay}, '
+ 'which is not between 0 and 6 hours.'
)
@slowmode_group.command(name='reset', aliases=['r'])
diff --git a/bot/converters.py b/bot/converters.py
index 4deb59f87..65963f513 100644
--- a/bot/converters.py
+++ b/bot/converters.py
@@ -181,8 +181,8 @@ class TagContentConverter(Converter):
return tag_content
-class Duration(Converter):
- """Convert duration strings into UTC datetime.datetime objects."""
+class DurationDelta(Converter):
+ """Convert duration strings into dateutil.relativedelta.relativedelta objects."""
duration_parser = re.compile(
r"((?P<years>\d+?) ?(years|year|Y|y) ?)?"
@@ -194,9 +194,9 @@ class Duration(Converter):
r"((?P<seconds>\d+?) ?(seconds|second|S|s))?"
)
- async def convert(self, ctx: Context, duration: str) -> datetime:
+ async def convert(self, ctx: Context, duration: str) -> relativedelta:
"""
- Converts a `duration` string to a datetime object that's `duration` in the future.
+ Converts a `duration` string to a relativedelta object.
The converter supports the following symbols for each unit of time:
- years: `Y`, `y`, `year`, `years`
@@ -215,6 +215,20 @@ class Duration(Converter):
duration_dict = {unit: int(amount) for unit, amount in match.groupdict(default=0).items()}
delta = relativedelta(**duration_dict)
+
+ return delta
+
+
+class Duration(DurationDelta):
+ """Convert duration strings into UTC datetime.datetime objects."""
+
+ async def convert(self, ctx: Context, duration: str) -> datetime:
+ """
+ Converts a `duration` string to a datetime object that's `duration` in the future.
+
+ The converter supports the same symbols for each unit of time as its parent class.
+ """
+ delta = super().convert(ctx, duration)
now = datetime.utcnow()
try: