From a393a10ceb54cd27222409c80f1fd9569349244e Mon Sep 17 00:00:00 2001 From: Michael Oliveira <34169552+Flame442@users.noreply.github.com> Date: Sun, 7 Jan 2024 19:31:35 -0500 Subject: [PATCH 1/8] Fix spelling mistake in [p]slash sync error (#6285) --- redbot/core/core_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 3930ac79408..944e9ff059e 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -2377,7 +2377,7 @@ async def slash_sync_error(self, ctx: commands.Context, error: commands.CommandE await ctx.send( _( "You seem to be attempting to sync after recently syncing. Discord does not like it " - "when bots sync more often than neccecary, so this command has a cooldown. You " + "when bots sync more often than necessary, so this command has a cooldown. You " "should enable/disable all commands you want to change first, and run this command " "one time only after all changes have been made. " ) From 569840e9e68478f41f8754dd7005414d251fdf11 Mon Sep 17 00:00:00 2001 From: goettner Date: Mon, 8 Jan 2024 16:34:48 -0800 Subject: [PATCH 2/8] [Alias] Aliased commands retain newlines (#4656) Co-authored-by: Michael Oliveira <34169552+Flame442@users.noreply.github.com> --- redbot/cogs/alias/alias.py | 12 +++++++++++- redbot/cogs/alias/alias_entry.py | 3 +-- redbot/pytest/core.py | 14 ++++++++++++++ tests/cogs/test_alias.py | 14 ++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/redbot/cogs/alias/alias.py b/redbot/cogs/alias/alias.py index b47d39ff978..cdc38066842 100644 --- a/redbot/cogs/alias/alias.py +++ b/redbot/cogs/alias/alias.py @@ -150,6 +150,15 @@ async def get_prefix(self, message: discord.Message) -> str: raise ValueError("No prefix found.") async def call_alias(self, message: discord.Message, prefix: str, alias: AliasEntry): + new_message = self.translate_alias_message(message, prefix, alias) + await self.bot.process_commands(new_message) + + def translate_alias_message(self, message: discord.Message, prefix: str, alias: AliasEntry): + """ + Translates a discord message using an alias + for a command to a discord message using the + alias' base command. + """ new_message = copy(message) try: args = alias.get_extra_args_from_alias(message, prefix) @@ -163,7 +172,8 @@ async def call_alias(self, message: discord.Message, prefix: str, alias: AliasEn new_message.content = "{}{} {}".format( prefix, command, " ".join(args[trackform.max + 1 :]) ).strip() - await self.bot.process_commands(new_message) + + return new_message async def paginate_alias_list( self, ctx: commands.Context, alias_list: List[AliasEntry] diff --git a/redbot/cogs/alias/alias_entry.py b/redbot/cogs/alias/alias_entry.py index 49cf224ab6b..159e68fa4ab 100644 --- a/redbot/cogs/alias/alias_entry.py +++ b/redbot/cogs/alias/alias_entry.py @@ -62,8 +62,7 @@ def get_extra_args_from_alias(self, message: discord.Message, prefix: str) -> st word = view.get_quoted_word() if len(word) < view.index - prev: word = "".join((view.buffer[prev], word, view.buffer[view.index - 1])) - extra.append(word) - view.skip_ws() + extra.append(word.strip(" ")) return extra def to_json(self) -> dict: diff --git a/redbot/pytest/core.py b/redbot/pytest/core.py index 4eb60b3cf05..57450f8e41c 100644 --- a/redbot/pytest/core.py +++ b/redbot/pytest/core.py @@ -23,7 +23,9 @@ "empty_role", "empty_user", "member_factory", + "newline_message", "user_factory", + "prefix", "ctx", ] @@ -142,6 +144,18 @@ def empty_message(): return mock_msg("No content.") +@pytest.fixture(scope="module") +def newline_message(): + mock_msg = type("", (), {})() + mock_msg.content = "!test a\nb\nc" + return mock_msg + + +@pytest.fixture(scope="module") +def prefix(): + return "!" + + @pytest.fixture() def ctx(empty_member, empty_channel, red): mock_ctx = namedtuple("Context", "author guild channel message bot") diff --git a/tests/cogs/test_alias.py b/tests/cogs/test_alias.py index 261c85dcb38..97b20058240 100644 --- a/tests/cogs/test_alias.py +++ b/tests/cogs/test_alias.py @@ -30,6 +30,20 @@ async def test_add_guild_alias(alias, ctx): assert alias_obj.name == "test" +async def test_translate_alias_message(alias, ctx, newline_message, prefix): + await create_test_guild_alias(alias, ctx) + alias_obj = await alias._aliases.get_alias(ctx.guild, "test") + + translated_message = alias.translate_alias_message(newline_message, prefix, alias_obj) + + original_content = newline_message.content.split(" ", 1)[1] + original_content = original_content.replace(" ", "") + new_content = translated_message.content.split(" ", 1)[1] + new_content = new_content.replace(" ", "") + + assert new_content == original_content + + async def test_delete_guild_alias(alias, ctx): await create_test_guild_alias(alias, ctx) alias_obj = await alias._aliases.get_alias(ctx.guild, "test") From 409ece427f9b8014cf0f28ff03a019cab323107e Mon Sep 17 00:00:00 2001 From: yeetbruises <61666396+yeetbruises@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:17:19 -0500 Subject: [PATCH 3/8] Add a start_dm option to SimpleMenu (#6286) Co-authored-by: Jakub Kuczys --- redbot/core/utils/views.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/redbot/core/utils/views.py b/redbot/core/utils/views.py index 10c1f23ecab..f6d2fea48a1 100644 --- a/redbot/core/utils/views.py +++ b/redbot/core/utils/views.py @@ -242,6 +242,19 @@ async def start(self, ctx: Context, *, ephemeral: bool = False): kwargs = await self.get_page(self.current_page) self.message = await ctx.send(**kwargs, ephemeral=ephemeral) + async def start_dm(self, user: discord.User): + """ + Used to start displaying the menu in a direct message. + + Parameters + ---------- + user: `discord.User` + The user that will be direct messaged by the bot. + """ + self.author = user + kwargs = await self.get_page(self.current_page) + self.message = await user.send(**kwargs) + async def get_page(self, page_num: int) -> Dict[str, Optional[Any]]: try: page = await self.source.get_page(page_num) From dbd71db6a8392e6fe9b9a8a33501c2595e4f7bac Mon Sep 17 00:00:00 2001 From: Dav Date: Fri, 19 Jan 2024 21:06:14 +0100 Subject: [PATCH 4/8] [Help] Send menus to dm if maxpages is 0 (#5375) Co-authored-by: Dav Co-authored-by: Michael Oliveira <34169552+Flame442@users.noreply.github.com> --- docs/cog_guides/core.rst | 5 +---- redbot/core/commands/help.py | 21 +++++++++++++++++---- redbot/core/core_commands.py | 2 -- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/cog_guides/core.rst b/docs/cog_guides/core.rst index 69e1895494f..71bc5113dc8 100644 --- a/docs/cog_guides/core.rst +++ b/docs/cog_guides/core.rst @@ -1475,9 +1475,6 @@ helpset maxpages Set the maximum number of help pages sent in a server channel. -.. Note:: This setting does not apply to menu help. - - If a help message contains more pages than this value, the help message will be sent to the command author via DM. This is to help reduce spam in server text channels. @@ -4378,4 +4375,4 @@ uptime **Description** -Shows Red's uptime. \ No newline at end of file +Shows Red's uptime. diff --git a/redbot/core/commands/help.py b/redbot/core/commands/help.py index dcff3f0410e..66920780d59 100644 --- a/redbot/core/commands/help.py +++ b/redbot/core/commands/help.py @@ -856,23 +856,36 @@ async def send_pages( if help_settings.use_menus.value >= HelpMenuSetting.buttons.value: use_select = help_settings.use_menus.value == 3 select_only = help_settings.use_menus.value == 4 - await SimpleMenu( + menu = SimpleMenu( pages, timeout=help_settings.react_timeout, use_select_menu=use_select, use_select_only=select_only, - ).start(ctx) + ) + # Send menu to DMs if max pages is 0 + if help_settings.max_pages_in_guild == 0: + await menu.start_dm(ctx.author) + else: + await menu.start(ctx) elif ( can_user_react_in(ctx.me, ctx.channel) and help_settings.use_menus is HelpMenuSetting.reactions ): + use_DMs = help_settings.max_pages_in_guild == 0 + destination = ctx.author if use_DMs else ctx.channel # 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 (destination.send(embed=pages[0]) if embed else destination.send(pages[0])) c = menus.DEFAULT_CONTROLS if len(pages) > 1 else {"\N{CROSS MARK}": menus.close_menu} # Allow other things to happen during menu timeout/interaction. + if use_DMs: + menu_ctx = await ctx.bot.get_context(m) + # Monkeypatch so help listens for reactions from the original author, not the bot + menu_ctx.author = ctx.author + else: + menu_ctx = ctx asyncio.create_task( - menus.menu(ctx, pages, c, message=m, timeout=help_settings.react_timeout) + menus.menu(menu_ctx, pages, c, message=m, timeout=help_settings.react_timeout) ) # menu needs reactions added manually since we fed it a message menus.start_adding_reactions(m, c.keys()) diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 944e9ff059e..1b780b1ff7d 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -4446,8 +4446,6 @@ async def helpset_pagecharlimt(self, ctx: commands.Context, limit: int): async def helpset_maxpages(self, ctx: commands.Context, pages: int): """Set the maximum number of help pages sent in a server channel. - Note: This setting does not apply to menu help. - If a help message contains more pages than this value, the help message will be sent to the command author via DM. This is to help reduce spam in server text channels. From ff09713aadd207c85fe0848c0555def1eb245981 Mon Sep 17 00:00:00 2001 From: Michael Oliveira <34169552+Flame442@users.noreply.github.com> Date: Sun, 11 Feb 2024 04:42:25 -0500 Subject: [PATCH 5/8] Fix edge case where perm names are not validated in custom Red decos (#6291) --- redbot/core/commands/requires.py | 1 + 1 file changed, 1 insertion(+) diff --git a/redbot/core/commands/requires.py b/redbot/core/commands/requires.py index ca455121c59..b5526a6712c 100644 --- a/redbot/core/commands/requires.py +++ b/redbot/core/commands/requires.py @@ -357,6 +357,7 @@ def decorator(func: "_CommandOrCoro") -> "_CommandOrCoro": if user_perms is None: func.__requires_user_perms__ = None else: + _validate_perms_dict(user_perms) if getattr(func, "__requires_user_perms__", None) is None: func.__requires_user_perms__ = discord.Permissions.none() func.__requires_user_perms__.update(**user_perms) From 185b607544fb3b3e8cd5863a954715e41c7977d4 Mon Sep 17 00:00:00 2001 From: Kreusada Ignad Amredes <67752638+Kreusada@users.noreply.github.com> Date: Mon, 26 Feb 2024 23:09:36 +0000 Subject: [PATCH 6/8] Fix markdown formatting in `[p]streamalert list` (#6292) --- redbot/cogs/streams/streams.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/redbot/cogs/streams/streams.py b/redbot/cogs/streams/streams.py index 60ceb619d41..54e32f6ec11 100644 --- a/redbot/cogs/streams/streams.py +++ b/redbot/cogs/streams/streams.py @@ -418,10 +418,10 @@ async def streamalert_list(self, ctx: commands.Context): return for channel_id, stream_platform in streams_list.items(): - msg += f"** - #{ctx.guild.get_channel(channel_id)}**\n" + msg += f"- {ctx.guild.get_channel(channel_id).mention}\n" for platform, streams in stream_platform.items(): - msg += f"\t** - {platform}**\n" - msg += f"\t\t{humanize_list(streams)}\n" + msg += f" - **{platform}**\n" + msg += f" {humanize_list(streams)}\n" for page in pagify(msg): await ctx.send(page) From 9345b691b3258ef7d2aec88a43e23c01529cdb9b Mon Sep 17 00:00:00 2001 From: Jakub Kuczys Date: Tue, 27 Feb 2024 00:15:07 +0100 Subject: [PATCH 7/8] Ask for confirmation before setting prefix on first-time setup (#6287) Co-authored-by: Michael Oliveira <34169552+Flame442@users.noreply.github.com> --- redbot/core/_cli.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/redbot/core/_cli.py b/redbot/core/_cli.py index bc263713f73..b8dbc65e492 100644 --- a/redbot/core/_cli.py +++ b/redbot/core/_cli.py @@ -80,7 +80,7 @@ async def interactive_config(red, token_set, prefix_set, *, print_header=True): print( "\nPick a prefix. A prefix is what you type before a " "command. Example:\n" - "!help\n^ The exclamation mark is the prefix in this case.\n" + "!help\n^ The exclamation mark (!) is the prefix in this case.\n" "The prefix can be multiple characters. You will be able to change it " "later and add more of them.\nChoose your prefix:\n" ) @@ -94,6 +94,12 @@ async def interactive_config(red, token_set, prefix_set, *, print_header=True): "Prefixes cannot start with '/', as it conflicts with Discord's slash commands." ) prefix = "" + if prefix and not confirm( + f'You chose "{prefix}" as your prefix. To run the help command,' + f" you will have to send:\n{prefix}help\n\n" + "Do you want to continue with this prefix?" + ): + prefix = "" if prefix: await red._config.prefix.set([prefix]) From 9dc7462d0f0fc6f7690c705cc652eaec9b2aadbb Mon Sep 17 00:00:00 2001 From: Lemon Rose <78662983+japandotorg@users.noreply.github.com> Date: Tue, 27 Feb 2024 20:48:33 +0530 Subject: [PATCH 8/8] Prohibit zero-length prefixes in `[p]set [server]prefix` (#6013) Co-authored-by: Kreusada Ignad Amredes <67752638+Kreusada@users.noreply.github.com> --- redbot/core/core_commands.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/redbot/core/core_commands.py b/redbot/core/core_commands.py index 1b780b1ff7d..13c3d4c86b7 100644 --- a/redbot/core/core_commands.py +++ b/redbot/core/core_commands.py @@ -117,6 +117,7 @@ def entity_transformer(statement: str) -> str: TokenConverter = commands.get_dict_converter(delims=[" ", ",", ";"]) MAX_PREFIX_LENGTH = 25 +MINIMUM_PREFIX_LENGTH = 1 class CoreLogic: @@ -4052,6 +4053,24 @@ async def _set_prefix(self, ctx: commands.Context, *prefixes: str): _("Prefixes cannot start with '/', as it conflicts with Discord's slash commands.") ) return + if any(len(x) < MINIMUM_PREFIX_LENGTH for x in prefixes): + await ctx.send( + _( + "Warning: A prefix is below the recommended length (1 character).\n" + "Do you want to continue?" + ) + + " (yes/no)" + ) + pred = MessagePredicate.yes_or_no(ctx) + try: + await self.bot.wait_for("message", check=pred, timeout=30) + except asyncio.TimeoutError: + await ctx.send(_("Response timed out.")) + return + else: + if pred.result is False: + await ctx.send(_("Cancelled.")) + return if any(len(x) > MAX_PREFIX_LENGTH for x in prefixes): await ctx.send( _( @@ -4111,6 +4130,9 @@ async def _set_serverprefix( _("Prefixes cannot start with '/', as it conflicts with Discord's slash commands.") ) return + if any(len(x) < MINIMUM_PREFIX_LENGTH for x in prefixes): + await ctx.send(_("You cannot have a prefix shorter than 1 character.")) + return if any(len(x) > MAX_PREFIX_LENGTH for x in prefixes): await ctx.send(_("You cannot have a prefix longer than 25 characters.")) return