diff options
author | 2025-06-30 22:32:49 +0100 | |
---|---|---|
committer | 2025-06-30 23:16:42 +0100 | |
commit | a798c38763e4fd95b4192528ab6e648e4ec4cf3e (patch) | |
tree | 250abfeb0a84e8bd15559868e9cfc2fc72b37a71 | |
parent | Refactor slowmode command to use Duration converter; Combine redis caches int... (diff) |
General refactoring, change message formatting, update tests
-rw-r--r-- | bot/exts/moderation/slowmode.py | 52 | ||||
-rw-r--r-- | tests/bot/exts/moderation/test_slowmode.py | 28 |
2 files changed, 44 insertions, 36 deletions
diff --git a/bot/exts/moderation/slowmode.py b/bot/exts/moderation/slowmode.py index 9caf776b1..c03fc1e27 100644 --- a/bot/exts/moderation/slowmode.py +++ b/bot/exts/moderation/slowmode.py @@ -5,6 +5,7 @@ from async_rediscache import RedisCache from dateutil.relativedelta import relativedelta from discord import TextChannel, Thread from discord.ext.commands import Cog, Context, group, has_any_role +from pydis_core.utils.channel import get_or_fetch_channel from pydis_core.utils.scheduling import Scheduler from bot.bot import Bot @@ -12,7 +13,7 @@ from bot.constants import Channels, Emojis, MODERATION_ROLES from bot.converters import Duration, DurationDelta from bot.log import get_logger from bot.utils import time -from bot.utils.time import TimestampFormats, discord_timestamp +from bot.utils.time import format_relative, humanize_delta log = get_logger(__name__) @@ -52,11 +53,14 @@ class Slowmode(Cog): channel = ctx.channel humanized_delay = time.humanize_delta(seconds=channel.slowmode_delay) - if await self.slowmode_cache.contains(channel.id): - expiration_time = await self.slowmode_cache.get(channel.id).split(", ")[1] - expiration_timestamp = discord_timestamp(expiration_time, TimestampFormats.RELATIVE) + cached_data = await self.slowmode_cache.get(channel.id, None) + if cached_data is not None: + original_delay, expiration_time = cached_data.partition(", ") + humanized_original_delay = time.humanize_delta(seconds=int(original_delay)) + expiration_timestamp = format_relative(expiration_time) await ctx.send( - f"The slowmode delay for {channel.mention} is {humanized_delay} and expires in {expiration_timestamp}." + f"The slowmode delay for {channel.mention} is {humanized_delay}" + f" and will revert to {humanized_original_delay} {expiration_timestamp}." ) else: await ctx.send(f"The slowmode delay for {channel.mention} is {humanized_delay}.") @@ -88,7 +92,7 @@ class Slowmode(Cog): humanized_delay = time.humanize_delta(delay) # Ensure the delay is within discord's limits - if not slowmode_delay <= SLOWMODE_MAX_DELAY: + if slowmode_delay > SLOWMODE_MAX_DELAY: log.info( f"{ctx.author} tried to set the slowmode delay of #{channel} to {humanized_delay}, " "which is not between 0 and 6 hours." @@ -100,27 +104,28 @@ class Slowmode(Cog): return if expiry is not None: - humanized_expiry = time.humanize_delta(expiry) - expiration_timestamp = discord_timestamp(expiry, TimestampFormats.RELATIVE) + expiration_timestamp = format_relative(expiry) # Only cache the original slowmode delay if there is not already an ongoing temporary slowmode. if not await self.slowmode_cache.contains(channel.id): - await self.slowmode_cache.set(channel.id, f"{channel.slowmode_delay}, {expiry}") + delay_to_cache = channel.slowmode_delay else: - cached_delay = await self.slowmode_cache.get(channel.id) - await self.slowmode_cache.set(channel.id, f"{cached_delay}, {expiry}") + cached_data = await self.slowmode_cache.get(channel.id) + delay_to_cache = cached_data.split(", ")[0] self.scheduler.cancel(channel.id) + await self.slowmode_cache.set(channel.id, f"{delay_to_cache}, {expiry}") + humanized_original_delay = humanize_delta(seconds=int(delay_to_cache)) self.scheduler.schedule_at(expiry, channel.id, self._revert_slowmode(channel.id)) log.info( - f"{ctx.author} set the slowmode delay for #{channel} to" - f"{humanized_delay} which expires in {humanized_expiry}." + f"{ctx.author} set the slowmode delay for #{channel} to {humanized_delay}" + f" which will revert to {humanized_original_delay} in {humanize_delta(expiry)}." ) await channel.edit(slowmode_delay=slowmode_delay) await ctx.send( - f"{Emojis.check_mark} The slowmode delay for {channel.mention}" - f" is now {humanized_delay} and expires in {expiration_timestamp}." - ) + f"{Emojis.check_mark} The slowmode delay for {channel.mention}" + f" is now {humanized_delay} and will revert to {humanized_original_delay} {expiration_timestamp}." + ) else: if await self.slowmode_cache.contains(channel.id): await self.slowmode_cache.delete(channel.id) @@ -148,11 +153,13 @@ class Slowmode(Cog): cached_data = await self.slowmode_cache.get(channel_id) original_slowmode = int(cached_data.split(", ")[0]) slowmode_delay = time.humanize_delta(seconds=original_slowmode) - channel = self.bot.get_channel(channel_id) - log.info(f"Slowmode in #{channel} ({channel.id}) has expired and has reverted to {slowmode_delay}.") + channel = await get_or_fetch_channel(self.bot, channel_id) + mod_channel = await get_or_fetch_channel(self.bot, Channels.mods) + log.info(f"Slowmode in #{channel.name} ({channel.id}) has expired and has reverted to {slowmode_delay}.") await channel.edit(slowmode_delay=original_slowmode) - await channel.send( - f"{Emojis.check_mark} A previously applied slowmode has expired and has been reverted to {slowmode_delay}." + await mod_channel.send( + f"{Emojis.check_mark} A previously applied slowmode in {channel.jump_url} ({channel.id})" + f" has expired and has been reverted to {slowmode_delay}." ) await self.slowmode_cache.delete(channel.id) @@ -160,11 +167,6 @@ class Slowmode(Cog): async def reset_slowmode(self, ctx: Context, channel: MessageHolder) -> None: """Reset the slowmode delay for a text channel to 0 seconds.""" await self.set_slowmode(ctx, channel, relativedelta(seconds=0)) - if channel is None: - channel = ctx.channel - if await self.slowmode_cache.contains(channel.id): - await self.slowmode_cache.delete(channel.id) - self.scheduler.cancel(channel.id) async def cog_check(self, ctx: Context) -> bool: """Only allow moderators to invoke the commands in this cog.""" diff --git a/tests/bot/exts/moderation/test_slowmode.py b/tests/bot/exts/moderation/test_slowmode.py index d88ffd784..212934242 100644 --- a/tests/bot/exts/moderation/test_slowmode.py +++ b/tests/bot/exts/moderation/test_slowmode.py @@ -104,12 +104,12 @@ class SlowmodeTests(RedisTestCase): mock_datetime.now.return_value = fixed_datetime test_cases = ( - ("python-general", 6, 6000, f"{Emojis.check_mark} The slowmode delay for #python-general is now 6 seconds" - " and expires in <t:1748871600:R>."), - ("mod-spam", 5, 600, f"{Emojis.check_mark} The slowmode delay for #mod-spam is now 5 seconds and expires" - " in <t:1748866200:R>."), - ("changelog", 12, 7200, f"{Emojis.check_mark} The slowmode delay for #changelog is now 12 seconds and" - " expires in <t:1748872800:R>.") + ("python-general", 6, 6000, f"{Emojis.check_mark} The slowmode delay for #python-general is now 6 seconds " + "and will revert to 0 seconds <t:1748871600:R>."), + ("mod-spam", 5, 600, f"{Emojis.check_mark} The slowmode delay for #mod-spam is now 5 seconds and will " + "revert to 0 seconds <t:1748866200:R>."), + ("changelog", 12, 7200, f"{Emojis.check_mark} The slowmode delay for #changelog is now 12 seconds and will " + "revert to 0 seconds <t:1748872800:R>.") ) for channel_name, seconds, expiry, result_msg in test_cases: with self.subTest( @@ -147,10 +147,15 @@ class SlowmodeTests(RedisTestCase): args = (expiry, text_channel.id, mock.ANY) self.cog.scheduler.schedule_at.assert_called_once_with(*args) - async def test_revert_slowmode_callback(self) -> None: + @mock.patch("bot.exts.moderation.slowmode.get_or_fetch_channel") + async def test_revert_slowmode_callback(self, mock_get_or_fetch_channel) -> None: """Check that the slowmode is reverted""" - text_channel = MockTextChannel(name="python-general", slowmode_delay=2, id=123) - self.bot.get_channel = mock.MagicMock(return_value=text_channel) + text_channel = MockTextChannel(name="python-general", slowmode_delay=2, id=123, jump_url="#python-general") + mod_channel = MockTextChannel(name="mods", id=999, ) + # mock.MagicMock(return_value=text_channel) + + mock_get_or_fetch_channel.side_effect = [text_channel, mod_channel] + await self.cog.set_slowmode( self.cog, self.ctx, @@ -160,8 +165,9 @@ class SlowmodeTests(RedisTestCase): ) await self.cog._revert_slowmode(text_channel.id) text_channel.edit.assert_awaited_with(slowmode_delay=2) - text_channel.send.assert_called_once_with( - f"{Emojis.check_mark} A previously applied slowmode has expired and has been reverted to 2 seconds." + mod_channel.send.assert_called_once_with( + f"{Emojis.check_mark} A previously applied slowmode in {text_channel.jump_url} ({text_channel.id}) " + "has expired and has been reverted to 2 seconds." ) async def test_reschedule_slowmodes(self) -> None: |