mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-21 02:16:09 -05:00
[Utils] Finish and Refactor Predicate Utility (#2169)
* Uses classmethods to create predicates * Classmethods allow using a combination of different parameters to describe context * Some predicates assign a captured `result` to the predicate object on success * Added `ReactionPredicate` equivalent to `MessagePredicate` * Added `utils.menus.start_adding_reactions`, a non-blocking method for adding reactions asynchronously * Added documentation * Uses these new utils throughout the core bot Happened to also find some bugs in places, and places where we were waiting for events without catching `asyncio.TimeoutError` Signed-off-by: Toby Harradine <tobyharradine@gmail.com>
This commit is contained in:
@@ -11,6 +11,8 @@ from redbot.core import checks, commands, config
|
||||
from redbot.core.bot import Red
|
||||
from redbot.core.i18n import Translator, cog_i18n
|
||||
from redbot.core.utils.chat_formatting import box
|
||||
from redbot.core.utils.menus import start_adding_reactions
|
||||
from redbot.core.utils.predicates import ReactionPredicate, MessagePredicate
|
||||
|
||||
from .converters import CogOrCommand, RuleType, ClearableRuleType
|
||||
|
||||
@@ -20,9 +22,6 @@ COG = "COG"
|
||||
COMMAND = "COMMAND"
|
||||
GLOBAL = 0
|
||||
|
||||
# noinspection PyDictDuplicateKeys
|
||||
REACTS = {"\N{WHITE HEAVY CHECK MARK}": True, "\N{NEGATIVE SQUARED CROSS MARK}": False}
|
||||
Y_OR_N = {"y": True, "yes": True, "n": False, "no": False}
|
||||
# The strings in the schema are constants and should get extracted, but not translated until
|
||||
# runtime.
|
||||
translate = _
|
||||
@@ -566,35 +565,29 @@ class Permissions(commands.Cog):
|
||||
"""Ask "Are you sure?" and get the response as a bool."""
|
||||
if ctx.guild is None or ctx.guild.me.permissions_in(ctx.channel).add_reactions:
|
||||
msg = await ctx.send(_("Are you sure?"))
|
||||
for emoji in REACTS.keys():
|
||||
await msg.add_reaction(emoji)
|
||||
# noinspection PyAsyncCall
|
||||
task = start_adding_reactions(msg, ReactionPredicate.YES_OR_NO_EMOJIS, ctx.bot.loop)
|
||||
pred = ReactionPredicate.yes_or_no(msg, ctx.author)
|
||||
try:
|
||||
reaction, user = await ctx.bot.wait_for(
|
||||
"reaction_add",
|
||||
check=lambda r, u: (
|
||||
r.message.id == msg.id and u == ctx.author and r.emoji in REACTS
|
||||
),
|
||||
timeout=30,
|
||||
)
|
||||
await ctx.bot.wait_for("reaction_add", check=pred, timeout=30)
|
||||
except asyncio.TimeoutError:
|
||||
agreed = False
|
||||
await ctx.send(_("Response timed out."))
|
||||
return False
|
||||
else:
|
||||
agreed = REACTS.get(reaction.emoji)
|
||||
task.cancel()
|
||||
agreed = pred.result
|
||||
finally:
|
||||
await msg.delete()
|
||||
else:
|
||||
await ctx.send(_("Are you sure? (y/n)"))
|
||||
pred = MessagePredicate.yes_or_no(ctx)
|
||||
try:
|
||||
message = await ctx.bot.wait_for(
|
||||
"message",
|
||||
check=lambda m: m.author == ctx.author
|
||||
and m.channel == ctx.channel
|
||||
and m.content in Y_OR_N,
|
||||
timeout=30,
|
||||
)
|
||||
await ctx.bot.wait_for("message", check=pred, timeout=30)
|
||||
except asyncio.TimeoutError:
|
||||
agreed = False
|
||||
await ctx.send(_("Response timed out."))
|
||||
return False
|
||||
else:
|
||||
agreed = Y_OR_N.get(message.content.lower())
|
||||
agreed = pred.result
|
||||
|
||||
if agreed is False:
|
||||
await ctx.send(_("Action cancelled."))
|
||||
|
||||
Reference in New Issue
Block a user