Skip to content

Commit

Permalink
Calculate datetime only once by including in the _MuteTime response.
Browse files Browse the repository at this point in the history
- Use the same formatting of time for all mute methods for consistency.
- Use ctx.message.created_at to prevent an extremely difficult edge case.
- Prevent default duration from exceeding 1000 years so it doesn't get set to a value that would reasonably change to cause defaults to OverFlow.
  • Loading branch information
TrustyJAID committed Apr 19, 2024
1 parent 08a551f commit 77a0929
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 36 deletions.
3 changes: 2 additions & 1 deletion redbot/cogs/mutes/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def _edgematch(pattern: re.Pattern[str], argument: str) -> Optional[re.Match[str
class _MuteTime(TypedDict, total=False):
duration: timedelta
reason: str
until: datetime


class _MuteTimeConverter(Converter):
Expand Down Expand Up @@ -57,7 +58,7 @@ async def convert(self, ctx: commands.Context, argument: str) -> _MuteTime:
)
try:
result["duration"] = duration = timedelta(**time_data)
datetime.now(timezone.utc) + duration
result["until"] = ctx.message.created_at + duration
# Catch if using the timedelta with the current date will also result in an Overflow error
except OverflowError:
raise commands.BadArgument(
Expand Down
63 changes: 39 additions & 24 deletions redbot/cogs/mutes/mutes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,13 +1005,18 @@ async def default_mute_time(self, ctx: commands.Context, *, time: Optional[MuteT
await self.config.guild(ctx.guild).default_time.clear()
await ctx.send(_("Default mute time removed."))
else:
data = time.get("duration", {})
if not data:
duration = time.get("duration", None)
if not duration:
return await ctx.send(_("Please provide a valid time format."))
await self.config.guild(ctx.guild).default_time.set(data.total_seconds())
if duration >= timedelta(days=365000):
# prevent setting a default time now that might eventually cause an overflow
# later as the date goes up. 1000 years gives us approximately 8000 more years
# of wiggle room.
return await ctx.send(_("Please provide a more reasonable default time frame."))
await self.config.guild(ctx.guild).default_time.set(duration.total_seconds())
await ctx.send(
_("Default mute time set to {time}.").format(
time=humanize_timedelta(timedelta=data)
time=humanize_timedelta(timedelta=duration)
)
)

Expand Down Expand Up @@ -1142,15 +1147,15 @@ async def timeout(
return await ctx.send(_("You cannot mute me."))
if ctx.author in users:
return await ctx.send(_("You cannot mute yourself."))
duration = time_and_reason.get("duration", None)
if duration and duration > timedelta(days=28):
await ctx.send(_(MUTE_UNMUTE_ISSUES["mute_is_too_long"]))
return
until = time_and_reason.get("until", None)
reason = time_and_reason.get("reason", None)
time = ""
until = None
if duration:
until = datetime.now(timezone.utc) + duration
duration = None
if until:
duration = time_and_reason.get("duration")
if duration and duration > timedelta(days=28):
await ctx.send(_(MUTE_UNMUTE_ISSUES["mute_is_too_long"]))
return
length = humanize_timedelta(timedelta=duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
Expand All @@ -1159,7 +1164,8 @@ async def timeout(
else:
default_duration = await self.config.guild(ctx.guild).default_time()
if default_duration:
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
duration = timedelta(seconds=default_duration)
until = ctx.message.created_at + duration
length = humanize_timedelta(seconds=default_duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
Expand Down Expand Up @@ -1227,12 +1233,12 @@ async def mute(
if not await self._check_for_mute_role(ctx):
return
async with ctx.typing():
duration = time_and_reason.get("duration", None)
until = time_and_reason.get("until", None)
reason = time_and_reason.get("reason", None)
time = ""
until = None
if duration:
until = datetime.now(timezone.utc) + duration
duration = None
if until:
duration = time_and_reason.get("duration")
length = humanize_timedelta(timedelta=duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
Expand All @@ -1241,7 +1247,8 @@ async def mute(
else:
default_duration = await self.config.guild(ctx.guild).default_time()
if default_duration:
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
duration = timedelta(seconds=default_duration)
until = ctx.message.created_at + duration
length = humanize_timedelta(seconds=default_duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
Expand Down Expand Up @@ -1377,18 +1384,26 @@ async def channel_mute(
if ctx.author in users:
return await ctx.send(_("You cannot mute yourself."))
async with ctx.typing():
duration = time_and_reason.get("duration", None)
until = time_and_reason.get("until", None)
reason = time_and_reason.get("reason", None)
time = ""
until = None
if duration:
until = datetime.now(timezone.utc) + duration
time = _(" until {duration}").format(duration=discord.utils.format_dt(until))
duration = None
if until:
duration = time_and_reason.get("duration")
length = humanize_timedelta(timedelta=duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
)

else:
default_duration = await self.config.guild(ctx.guild).default_time()
if default_duration:
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
time = _(" until {duration}").format(duration=discord.utils.format_dt(until))
duration = timedelta(seconds=default_duration)
until = ctx.message.created_at + duration
length = humanize_timedelta(seconds=default_duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
)
author = ctx.message.author
channel = ctx.message.channel
if isinstance(channel, discord.Thread):
Expand Down
24 changes: 13 additions & 11 deletions redbot/cogs/mutes/voicemutes.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,23 +99,25 @@ async def voice_mute(
if not can_move:
issue_list.append((user, perm_reason))
continue
duration = time_and_reason.get("duration", None)
until = time_and_reason.get("until", None)
reason = time_and_reason.get("reason", None)
time = ""
until = None
if duration:
until = datetime.now(timezone.utc) + duration
time = _(" for {duration}").format(
duration=humanize_timedelta(timedelta=duration)
duration = None
if until:
duration = time_and_reason.get("duration")
length = humanize_timedelta(timedelta=duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
)

else:
default_duration = await self.config.guild(ctx.guild).default_time()
if default_duration:
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
time = _(" for {duration}").format(
duration=humanize_timedelta(
timedelta=timedelta(seconds=default_duration)
)
duration = timedelta(seconds=default_duration)
until = ctx.message.created_at + duration
length = humanize_timedelta(seconds=default_duration)
time = _(" for {length} until {duration}").format(
length=length, duration=discord.utils.format_dt(until)
)
guild = ctx.guild
author = ctx.author
Expand Down

0 comments on commit 77a0929

Please sign in to comment.