From ee53d50c3aec2c2bbbe3a55df603635bb4a8b80d Mon Sep 17 00:00:00 2001 From: DevilXD Date: Wed, 22 Jan 2020 23:15:51 +0100 Subject: [PATCH] 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 --- changelog.d/3433.feature.rst | 1 + redbot/core/bot.py | 11 +++--- redbot/core/commands/help.py | 71 ++++++++++++++++++++++-------------- redbot/core/core_commands.py | 24 ++++++++++++ 4 files changed, 75 insertions(+), 32 deletions(-) create mode 100644 changelog.d/3433.feature.rst diff --git a/changelog.d/3433.feature.rst b/changelog.d/3433.feature.rst new file mode 100644 index 000000000..7a7d6446f --- /dev/null +++ b/changelog.d/3433.feature.rst @@ -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. diff --git a/redbot/core/bot.py b/redbot/core/bot.py index 5ad380f62..c3d609e19 100644 --- a/redbot/core/bot.py +++ b/redbot/core/bot.py @@ -88,6 +88,7 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d custom_info=None, help__page_char_limit=1000, help__max_pages_in_guild=2, + help__delete_delay=0, help__use_menus=False, help__show_hidden=False, 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: """ Overridden decorator method for Red's ``before_invoke`` behavior. - + This can safely be used purely functionally as well. - + 3rd party cogs should remove any hooks which they register at unload 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 without error. If any check or argument parsing procedures fail then the hooks are not called. - + Parameters ---------- coro: Callable[[commands.Context], Awaitable[Any]] The coroutine to register as the pre-invoke hook. - + Raises ------ TypeError @@ -298,7 +299,7 @@ class RedBase(commands.GroupMixin, commands.bot.BotBase, RPCMixin): # pylint: d ------ TypeError Did not provide ``who`` or ``who_id`` - + Returns ------- bool diff --git a/redbot/core/commands/help.py b/redbot/core/commands/help.py index 783ef1dc5..acb5d6d61 100644 --- a/redbot/core/commands/help.py +++ b/redbot/core/commands/help.py @@ -44,6 +44,7 @@ from . import commands from .context import Context from ..i18n import Translator from ..utils import menus +from ..utils.mod import mass_purge from ..utils._internal_utils import fuzzy_command_search, format_fuzzy_results from ..utils.chat_formatting import box, pagify @@ -627,36 +628,52 @@ class RedHelpFormatter: Sends pages based on settings. """ - if not ( - ctx.channel.permissions_for(ctx.me).add_reactions - and await ctx.bot._config.help.use_menus() - ): + # save on config calls + config_help = await ctx.bot._config.help() + channel_permissions = ctx.channel.permissions_for(ctx.me) - max_pages_in_guild = await ctx.bot._config.help.max_pages_in_guild() - destination = ctx.author if len(pages) > max_pages_in_guild else ctx + if not (channel_permissions.add_reactions and config_help["use_menus"]): - if embed: - for page in pages: - try: - await destination.send(embed=page) - except discord.Forbidden: - return await ctx.send( - T_( - "I couldn't send the help message to you in DM. " - "Either you blocked me or you disabled DMs in this server." - ) - ) - else: - for page in pages: - try: - await destination.send(page) - except discord.Forbidden: - return await ctx.send( - T_( - "I couldn't send the help message to you in DM. " - "Either you blocked me or you disabled DMs in this server." - ) + max_pages_in_guild = config_help["max_pages_in_guild"] + use_DMs = len(pages) > max_pages_in_guild + destination = ctx.author if use_DMs else ctx.channel + delete_delay = config_help["delete_delay"] + + messages: List[discord.Message] = [] + for page in pages: + try: + if embed: + msg = await destination.send(embed=page) + else: + msg = await destination.send(page) + except discord.Forbidden: + return await ctx.send( + 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: # 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])) diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 5c1cac0d8..31872df37 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -1368,6 +1368,30 @@ class Core(commands.Cog, CoreLogic): await ctx.bot._config.help.max_pages_in_guild.set(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") async def helpset_tagline(self, ctx: commands.Context, *, tagline: str = None): """