Help delete pages delay feature (#3433)

* Added 'deletedelay' feature for help

* Fixes

* More fixes

* Use better message when disabling

* Added changelog entry

* Addressed feedback

* Improved the pages check

* Added additional command check

* Improved command description

* Final feedback improvements
This commit is contained in:
DevilXD 2020-01-22 23:15:51 +01:00 committed by Michael H
parent 8570971f68
commit ee53d50c3a
4 changed files with 75 additions and 32 deletions

View File

@ -0,0 +1 @@
Added a ``[p]helpset deletedelay`` command, that lets you set a delay (in seconds) after which help messages / pages will be deleted.

View File

@ -88,6 +88,7 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
custom_info=None, custom_info=None,
help__page_char_limit=1000, help__page_char_limit=1000,
help__max_pages_in_guild=2, help__max_pages_in_guild=2,
help__delete_delay=0,
help__use_menus=False, help__use_menus=False,
help__show_hidden=False, help__show_hidden=False,
help__verify_checks=True, help__verify_checks=True,
@ -186,9 +187,9 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
def before_invoke(self, coro: T_BIC) -> T_BIC: def before_invoke(self, coro: T_BIC) -> T_BIC:
""" """
Overridden decorator method for Red's ``before_invoke`` behavior. Overridden decorator method for Red's ``before_invoke`` behavior.
This can safely be used purely functionally as well. This can safely be used purely functionally as well.
3rd party cogs should remove any hooks which they register at unload 3rd party cogs should remove any hooks which they register at unload
using `remove_before_invoke_hook` using `remove_before_invoke_hook`
@ -199,12 +200,12 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
only called if all checks and argument parsing procedures pass only called if all checks and argument parsing procedures pass
without error. If any check or argument parsing procedures fail without error. If any check or argument parsing procedures fail
then the hooks are not called. then the hooks are not called.
Parameters Parameters
---------- ----------
coro: Callable[[commands.Context], Awaitable[Any]] coro: Callable[[commands.Context], Awaitable[Any]]
The coroutine to register as the pre-invoke hook. The coroutine to register as the pre-invoke hook.
Raises Raises
------ ------
TypeError TypeError
@ -298,7 +299,7 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d
------ ------
TypeError TypeError
Did not provide ``who`` or ``who_id`` Did not provide ``who`` or ``who_id``
Returns Returns
------- -------
bool bool

View File

@ -44,6 +44,7 @@ from . import commands
from .context import Context from .context import Context
from ..i18n import Translator from ..i18n import Translator
from ..utils import menus from ..utils import menus
from ..utils.mod import mass_purge
from ..utils._internal_utils import fuzzy_command_search, format_fuzzy_results from ..utils._internal_utils import fuzzy_command_search, format_fuzzy_results
from ..utils.chat_formatting import box, pagify from ..utils.chat_formatting import box, pagify
@ -627,36 +628,52 @@ class RedHelpFormatter:
Sends pages based on settings. Sends pages based on settings.
""" """
if not ( # save on config calls
ctx.channel.permissions_for(ctx.me).add_reactions config_help = await ctx.bot._config.help()
and await ctx.bot._config.help.use_menus() channel_permissions = ctx.channel.permissions_for(ctx.me)
):
max_pages_in_guild = await ctx.bot._config.help.max_pages_in_guild() if not (channel_permissions.add_reactions and config_help["use_menus"]):
destination = ctx.author if len(pages) > max_pages_in_guild else ctx
if embed: max_pages_in_guild = config_help["max_pages_in_guild"]
for page in pages: use_DMs = len(pages) > max_pages_in_guild
try: destination = ctx.author if use_DMs else ctx.channel
await destination.send(embed=page) delete_delay = config_help["delete_delay"]
except discord.Forbidden:
return await ctx.send( messages: List[discord.Message] = []
T_( for page in pages:
"I couldn't send the help message to you in DM. " try:
"Either you blocked me or you disabled DMs in this server." if embed:
) msg = await destination.send(embed=page)
) else:
else: msg = await destination.send(page)
for page in pages: except discord.Forbidden:
try: return await ctx.send(
await destination.send(page) T_(
except discord.Forbidden: "I couldn't send the help message to you in DM. "
return await ctx.send( "Either you blocked me or you disabled DMs in this server."
T_(
"I couldn't send the help message to you in DM. "
"Either you blocked me or you disabled DMs in this server."
)
) )
)
else:
messages.append(msg)
# The if statement takes into account that 'destination' will be
# the context channel in non-DM context, reusing 'channel_permissions' to avoid
# computing the permissions twice.
if (
not use_DMs # we're not in DMs
and delete_delay > 0 # delete delay is enabled
and channel_permissions.manage_messages # we can manage messages here
):
# We need to wrap this in a task to not block after-sending-help interactions.
# The channel has to be TextChannel as we can't bulk-delete from DMs
async def _delete_delay_help(
channel: discord.TextChannel, messages: List[discord.Message], delay: int
):
await asyncio.sleep(delay)
await mass_purge(messages, channel)
asyncio.create_task(_delete_delay_help(destination, messages, delete_delay))
else: else:
# Specifically ensuring the menu's message is sent prior to returning # Specifically ensuring the menu's message is sent prior to returning
m = await (ctx.send(embed=pages[0]) if embed else ctx.send(pages[0])) m = await (ctx.send(embed=pages[0]) if embed else ctx.send(pages[0]))

View File

@ -1368,6 +1368,30 @@ class Core(commands.Cog, CoreLogic):
await ctx.bot._config.help.max_pages_in_guild.set(pages) await ctx.bot._config.help.max_pages_in_guild.set(pages)
await ctx.send(_("Done. The page limit has been set to {}.").format(pages)) await ctx.send(_("Done. The page limit has been set to {}.").format(pages))
@helpset.command(name="deletedelay")
@commands.bot_has_permissions(manage_messages=True)
async def helpset_deletedelay(self, ctx: commands.Context, seconds: int):
"""Set the delay after which help pages will be deleted.
The setting is disabled by default, and only applies to non-menu help,
sent in server text channels.
Setting the delay to 0 disables this feature.
The bot has to have MANAGE_MESSAGES permission for this to work.
"""
if seconds < 0:
await ctx.send(_("You must give a value of zero or greater!"))
return
if seconds > 60 * 60 * 24 * 14: # 14 days
await ctx.send(_("The delay cannot be longer than 14 days!"))
return
await ctx.bot._config.help.delete_delay.set(seconds)
if seconds == 0:
await ctx.send(_("Done. Help messages will not be deleted now."))
else:
await ctx.send(_("Done. The delete delay has been set to {} seconds.").format(seconds))
@helpset.command(name="tagline") @helpset.command(name="tagline")
async def helpset_tagline(self, ctx: commands.Context, *, tagline: str = None): async def helpset_tagline(self, ctx: commands.Context, *, tagline: str = None):
""" """