Skip to content

Commit 77a0929

Browse files
committed
Calculate datetime only once by including in the _MuteTime response.
- 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.
1 parent 08a551f commit 77a0929

File tree

3 files changed

+54
-36
lines changed

3 files changed

+54
-36
lines changed

redbot/cogs/mutes/converters.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def _edgematch(pattern: re.Pattern[str], argument: str) -> Optional[re.Match[str
2929
class _MuteTime(TypedDict, total=False):
3030
duration: timedelta
3131
reason: str
32+
until: datetime
3233

3334

3435
class _MuteTimeConverter(Converter):
@@ -57,7 +58,7 @@ async def convert(self, ctx: commands.Context, argument: str) -> _MuteTime:
5758
)
5859
try:
5960
result["duration"] = duration = timedelta(**time_data)
60-
datetime.now(timezone.utc) + duration
61+
result["until"] = ctx.message.created_at + duration
6162
# Catch if using the timedelta with the current date will also result in an Overflow error
6263
except OverflowError:
6364
raise commands.BadArgument(

redbot/cogs/mutes/mutes.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,13 +1005,18 @@ async def default_mute_time(self, ctx: commands.Context, *, time: Optional[MuteT
10051005
await self.config.guild(ctx.guild).default_time.clear()
10061006
await ctx.send(_("Default mute time removed."))
10071007
else:
1008-
data = time.get("duration", {})
1009-
if not data:
1008+
duration = time.get("duration", None)
1009+
if not duration:
10101010
return await ctx.send(_("Please provide a valid time format."))
1011-
await self.config.guild(ctx.guild).default_time.set(data.total_seconds())
1011+
if duration >= timedelta(days=365000):
1012+
# prevent setting a default time now that might eventually cause an overflow
1013+
# later as the date goes up. 1000 years gives us approximately 8000 more years
1014+
# of wiggle room.
1015+
return await ctx.send(_("Please provide a more reasonable default time frame."))
1016+
await self.config.guild(ctx.guild).default_time.set(duration.total_seconds())
10121017
await ctx.send(
10131018
_("Default mute time set to {time}.").format(
1014-
time=humanize_timedelta(timedelta=data)
1019+
time=humanize_timedelta(timedelta=duration)
10151020
)
10161021
)
10171022

@@ -1142,15 +1147,15 @@ async def timeout(
11421147
return await ctx.send(_("You cannot mute me."))
11431148
if ctx.author in users:
11441149
return await ctx.send(_("You cannot mute yourself."))
1145-
duration = time_and_reason.get("duration", None)
1146-
if duration and duration > timedelta(days=28):
1147-
await ctx.send(_(MUTE_UNMUTE_ISSUES["mute_is_too_long"]))
1148-
return
1150+
until = time_and_reason.get("until", None)
11491151
reason = time_and_reason.get("reason", None)
11501152
time = ""
1151-
until = None
1152-
if duration:
1153-
until = datetime.now(timezone.utc) + duration
1153+
duration = None
1154+
if until:
1155+
duration = time_and_reason.get("duration")
1156+
if duration and duration > timedelta(days=28):
1157+
await ctx.send(_(MUTE_UNMUTE_ISSUES["mute_is_too_long"]))
1158+
return
11541159
length = humanize_timedelta(timedelta=duration)
11551160
time = _(" for {length} until {duration}").format(
11561161
length=length, duration=discord.utils.format_dt(until)
@@ -1159,7 +1164,8 @@ async def timeout(
11591164
else:
11601165
default_duration = await self.config.guild(ctx.guild).default_time()
11611166
if default_duration:
1162-
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
1167+
duration = timedelta(seconds=default_duration)
1168+
until = ctx.message.created_at + duration
11631169
length = humanize_timedelta(seconds=default_duration)
11641170
time = _(" for {length} until {duration}").format(
11651171
length=length, duration=discord.utils.format_dt(until)
@@ -1227,12 +1233,12 @@ async def mute(
12271233
if not await self._check_for_mute_role(ctx):
12281234
return
12291235
async with ctx.typing():
1230-
duration = time_and_reason.get("duration", None)
1236+
until = time_and_reason.get("until", None)
12311237
reason = time_and_reason.get("reason", None)
12321238
time = ""
1233-
until = None
1234-
if duration:
1235-
until = datetime.now(timezone.utc) + duration
1239+
duration = None
1240+
if until:
1241+
duration = time_and_reason.get("duration")
12361242
length = humanize_timedelta(timedelta=duration)
12371243
time = _(" for {length} until {duration}").format(
12381244
length=length, duration=discord.utils.format_dt(until)
@@ -1241,7 +1247,8 @@ async def mute(
12411247
else:
12421248
default_duration = await self.config.guild(ctx.guild).default_time()
12431249
if default_duration:
1244-
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
1250+
duration = timedelta(seconds=default_duration)
1251+
until = ctx.message.created_at + duration
12451252
length = humanize_timedelta(seconds=default_duration)
12461253
time = _(" for {length} until {duration}").format(
12471254
length=length, duration=discord.utils.format_dt(until)
@@ -1377,18 +1384,26 @@ async def channel_mute(
13771384
if ctx.author in users:
13781385
return await ctx.send(_("You cannot mute yourself."))
13791386
async with ctx.typing():
1380-
duration = time_and_reason.get("duration", None)
1387+
until = time_and_reason.get("until", None)
13811388
reason = time_and_reason.get("reason", None)
13821389
time = ""
1383-
until = None
1384-
if duration:
1385-
until = datetime.now(timezone.utc) + duration
1386-
time = _(" until {duration}").format(duration=discord.utils.format_dt(until))
1390+
duration = None
1391+
if until:
1392+
duration = time_and_reason.get("duration")
1393+
length = humanize_timedelta(timedelta=duration)
1394+
time = _(" for {length} until {duration}").format(
1395+
length=length, duration=discord.utils.format_dt(until)
1396+
)
1397+
13871398
else:
13881399
default_duration = await self.config.guild(ctx.guild).default_time()
13891400
if default_duration:
1390-
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
1391-
time = _(" until {duration}").format(duration=discord.utils.format_dt(until))
1401+
duration = timedelta(seconds=default_duration)
1402+
until = ctx.message.created_at + duration
1403+
length = humanize_timedelta(seconds=default_duration)
1404+
time = _(" for {length} until {duration}").format(
1405+
length=length, duration=discord.utils.format_dt(until)
1406+
)
13921407
author = ctx.message.author
13931408
channel = ctx.message.channel
13941409
if isinstance(channel, discord.Thread):

redbot/cogs/mutes/voicemutes.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,23 +99,25 @@ async def voice_mute(
9999
if not can_move:
100100
issue_list.append((user, perm_reason))
101101
continue
102-
duration = time_and_reason.get("duration", None)
102+
until = time_and_reason.get("until", None)
103103
reason = time_and_reason.get("reason", None)
104104
time = ""
105-
until = None
106-
if duration:
107-
until = datetime.now(timezone.utc) + duration
108-
time = _(" for {duration}").format(
109-
duration=humanize_timedelta(timedelta=duration)
105+
duration = None
106+
if until:
107+
duration = time_and_reason.get("duration")
108+
length = humanize_timedelta(timedelta=duration)
109+
time = _(" for {length} until {duration}").format(
110+
length=length, duration=discord.utils.format_dt(until)
110111
)
112+
111113
else:
112114
default_duration = await self.config.guild(ctx.guild).default_time()
113115
if default_duration:
114-
until = datetime.now(timezone.utc) + timedelta(seconds=default_duration)
115-
time = _(" for {duration}").format(
116-
duration=humanize_timedelta(
117-
timedelta=timedelta(seconds=default_duration)
118-
)
116+
duration = timedelta(seconds=default_duration)
117+
until = ctx.message.created_at + duration
118+
length = humanize_timedelta(seconds=default_duration)
119+
time = _(" for {length} until {duration}").format(
120+
length=length, duration=discord.utils.format_dt(until)
119121
)
120122
guild = ctx.guild
121123
author = ctx.author

0 commit comments

Comments
 (0)