mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
Improve Cooldown UX (#2412)
This improves the feedback given on `command_on_cool_down`, as well as automatically handling cooldowns under 1 second for the user.
This commit is contained in:
parent
7e2e37ab3f
commit
722aaa225b
@ -4,6 +4,7 @@ import codecs
|
|||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@ -15,7 +16,7 @@ from pkg_resources import DistributionNotFound
|
|||||||
from .. import __version__ as red_version, version_info as red_version_info, VersionInfo
|
from .. import __version__ as red_version, version_info as red_version_info, VersionInfo
|
||||||
from . import commands
|
from . import commands
|
||||||
from .data_manager import storage_type
|
from .data_manager import storage_type
|
||||||
from .utils.chat_formatting import inline, bordered, format_perms_list
|
from .utils.chat_formatting import inline, bordered, format_perms_list, humanize_timedelta
|
||||||
from .utils import fuzzy_command_search, format_fuzzy_results
|
from .utils import fuzzy_command_search, format_fuzzy_results
|
||||||
|
|
||||||
log = logging.getLogger("red")
|
log = logging.getLogger("red")
|
||||||
@ -213,8 +214,22 @@ def init_events(bot, cli_flags):
|
|||||||
elif isinstance(error, commands.NoPrivateMessage):
|
elif isinstance(error, commands.NoPrivateMessage):
|
||||||
await ctx.send("That command is not available in DMs.")
|
await ctx.send("That command is not available in DMs.")
|
||||||
elif isinstance(error, commands.CommandOnCooldown):
|
elif isinstance(error, commands.CommandOnCooldown):
|
||||||
|
if error.retry_after < 1:
|
||||||
|
async with ctx.typing():
|
||||||
|
# the sleep here is so that commands using this for ratelimit purposes
|
||||||
|
# are not made more lenient than intended, while still being
|
||||||
|
# more convienient for the user than redoing it less than a second later.
|
||||||
|
await asyncio.sleep(error.retry_after)
|
||||||
|
await ctx.bot.invoke(ctx)
|
||||||
|
# done this way so checks still occur if there are other
|
||||||
|
# failures possible than just cooldown.
|
||||||
|
# do not change to ctx.reinvoke()
|
||||||
|
return
|
||||||
|
|
||||||
await ctx.send(
|
await ctx.send(
|
||||||
"This command is on cooldown. Try again in {:.2f}s".format(error.retry_after)
|
"This command is on cooldown. Try again in {}.".format(
|
||||||
|
humanize_timedelta(seconds=error.retry_after)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
log.exception(type(error).__name__, exc_info=error)
|
log.exception(type(error).__name__, exc_info=error)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import itertools
|
import itertools
|
||||||
from typing import Sequence, Iterator, List
|
import datetime
|
||||||
|
from typing import Sequence, Iterator, List, Optional
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
@ -204,7 +205,7 @@ def pagify(
|
|||||||
priority: bool = False,
|
priority: bool = False,
|
||||||
escape_mass_mentions: bool = True,
|
escape_mass_mentions: bool = True,
|
||||||
shorten_by: int = 8,
|
shorten_by: int = 8,
|
||||||
page_length: int = 2000
|
page_length: int = 2000,
|
||||||
) -> Iterator[str]:
|
) -> Iterator[str]:
|
||||||
"""Generate multiple pages from the given text.
|
"""Generate multiple pages from the given text.
|
||||||
|
|
||||||
@ -386,3 +387,37 @@ def format_perms_list(perms: discord.Permissions) -> str:
|
|||||||
perm_name = '"' + perm.replace("_", " ").title() + '"'
|
perm_name = '"' + perm.replace("_", " ").title() + '"'
|
||||||
perm_names.append(perm_name)
|
perm_names.append(perm_name)
|
||||||
return humanize_list(perm_names).replace("Guild", "Server")
|
return humanize_list(perm_names).replace("Guild", "Server")
|
||||||
|
|
||||||
|
|
||||||
|
def humanize_timedelta(
|
||||||
|
*, timedelta: Optional[datetime.timedelta] = None, seconds: Optional[int] = None
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
Get a human timedelta representation
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = seconds or timedelta.total_seconds()
|
||||||
|
except AttributeError:
|
||||||
|
raise ValueError("You must provide either a timedelta or a number of seconds")
|
||||||
|
|
||||||
|
seconds = int(obj)
|
||||||
|
periods = [
|
||||||
|
(_("year"), _("years"), 60 * 60 * 24 * 365),
|
||||||
|
(_("month"), _("months"), 60 * 60 * 24 * 30),
|
||||||
|
(_("day"), _("days"), 60 * 60 * 24),
|
||||||
|
(_("hour"), _("hours"), 60 * 60),
|
||||||
|
(_("minute"), _("minutes"), 60),
|
||||||
|
(_("second"), _("seconds"), 1),
|
||||||
|
]
|
||||||
|
|
||||||
|
strings = []
|
||||||
|
for period_name, plural_period_name, period_seconds in periods:
|
||||||
|
if seconds >= period_seconds:
|
||||||
|
period_value, seconds = divmod(seconds, period_seconds)
|
||||||
|
if period_value == 0:
|
||||||
|
continue
|
||||||
|
unit = plural_period_name if period_value > 1 else period_name
|
||||||
|
strings.append(f"{period_value} {unit}")
|
||||||
|
|
||||||
|
return ", ".join(strings)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user