Skip to content

Commit 9cb0aa6

Browse files
committed
Ask for confirmation if a duration isn't provided
1 parent 4ee3d51 commit 9cb0aa6

File tree

1 file changed

+60
-43
lines changed

1 file changed

+60
-43
lines changed
Lines changed: 60 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,67 +1,84 @@
1+
import asyncio
2+
3+
import discord
14
from discord.ext import commands
25

36
from bot import ModmailBot
47
from core import time
58

69

7-
class StrictUserFriendlyDuration(time.UserFriendlyTime):
10+
async def close_after_confirmation(ctx: commands.Context, converted_arg: time.UserFriendlyTime) -> None:
811
"""
9-
A converter which parses user-friendly time durations.
10-
11-
Since this converter is meant for parsing close messages while
12-
closing threads, both custom close messages and time durations are
13-
parsed.
12+
Send a message and allow users to react to it to close the thread.
1413
15-
Unlike the parent class, a time duration must be provided when
16-
a custom close message is provided.
14+
The reaction times out after 5 minutes.
1715
"""
16+
unicode_reaction = '\N{WHITE HEAVY CHECK MARK}'
17+
warning_message = ("\N{WARNING SIGN} A time duration wasn't provided, reacting to this message will close"
18+
" this thread instantly with the provided custom close message.")
19+
20+
message = await ctx.send(warning_message)
21+
await message.add_reaction(unicode_reaction)
22+
23+
def checkmark_press_check(reaction: discord.Reaction, user: discord.User) -> bool:
24+
is_right_reaction = (
25+
user != ctx.bot.user
26+
and reaction.message.id == message.id
27+
and str(reaction.emoji) == unicode_reaction
28+
)
29+
30+
return is_right_reaction
31+
32+
try:
33+
await ctx.bot.wait_for('reaction_add', check=checkmark_press_check, timeout=5 * 60)
34+
except asyncio.TimeoutError:
35+
await message.edit(content=message.content+'\n\n**Timed out.**')
36+
await message.clear_reactions()
37+
else:
38+
await original_close_command(ctx, after=converted_arg)
39+
40+
41+
async def safe_close(
42+
self: time.UserFriendlyTime,
43+
ctx: commands.Context,
44+
*,
45+
after: time.UserFriendlyTime = None
46+
) -> None:
47+
"""
48+
Close the current thread.
1849
19-
MODIFIERS = {'silently', 'silent', 'cancel'}
20-
21-
async def convert(self, ctx: commands.Context, argument: str) -> "StrictUserFriendlyDuration":
22-
"""
23-
Parse the provided time duration along with any close message.
24-
25-
Fail if a custom close message is provided without a time
26-
duration.
27-
"""
28-
await super().convert(ctx, argument)
29-
30-
argument_passed = bool(argument)
31-
not_a_modifier = argument not in self.MODIFIERS
32-
if argument_passed and not_a_modifier and self.arg == argument:
33-
# Fail since only a close message was provided.
34-
raise commands.BadArgument("A time duration must be provided when closing with a custom message.")
35-
36-
return self
50+
Unlike the original close command, confirmation is awaited when
51+
a time duration isn't provided but a custom close message is.
52+
"""
53+
modifiers = {'silently', 'silent', 'cancel'}
3754

55+
argument_passed = bool(after)
56+
not_a_modifier = after.arg not in modifiers
3857

39-
ADDED_HELP_TEXT = '\n\n*Note: Providing a time duration is necessary when closing with a custom message.*'
58+
if argument_passed and not_a_modifier and after.arg == after.raw:
59+
# Ask for confirmation since only a close message was provided.
60+
await close_after_confirmation(ctx, after)
61+
else:
62+
await original_close_command(ctx, after=after)
4063

4164

4265
def setup(bot: ModmailBot) -> None:
4366
"""
44-
Monkey patch the close command's callback.
67+
Monkey patch the close command's callback to safe_close.
4568
46-
This makes it use the StrictUserFriendlyTime converter and updates
47-
the help text to reflect the new behaviour.
69+
The help text is also updated to reflect the new behaviour.
4870
"""
49-
global previous_converter
71+
global original_close_command
5072

5173
command = bot.get_command('close')
74+
original_close_command = command.copy()
75+
original_close_command.cog = command.cog
5276

53-
previous_converter = command.callback.__annotations__['after']
54-
command.callback.__annotations__['after'] = StrictUserFriendlyDuration
55-
command.callback = command.callback
56-
57-
command.help += ADDED_HELP_TEXT
77+
command.callback = safe_close
78+
command.help += '\n\n*Note: A time duration should be provided when closing with a custom message.*'
5879

5980

6081
def teardown(bot: ModmailBot) -> None:
61-
"""Undo changes to the close command."""
62-
command = bot.get_command('close')
63-
64-
command.callback.__annotations__['after'] = previous_converter
65-
command.callback = command.callback
66-
67-
command.help = command.help.remove_suffix(ADDED_HELP_TEXT)
82+
"""Restore the original close command."""
83+
bot.remove_command('close')
84+
bot.add_command(original_close_command)

0 commit comments

Comments
 (0)