Repository: Cog-Creators/Red-DiscordBot

Issue:
[V3 Menu] Listen before adding reactions
# Feature request

<!-- This template is for feature requests. Please fill out the following: -->


#### Select the type of feature you are requesting:

<!-- To check a box, replace the space between the [] with a x -->

- [ ] Cog
- [ ] Command
- [x] API functionality

#### Describe your requested feature

<!--
Feel free to describe in as much detail as you wish.

If you are requesting a cog to be included in core: 
    - Describe the functionality in as much detail as possible
    - Include the command structure, if possible
    - Please note that unless it's something that should be core functionality,
      we reserve the right to reject your suggestion and point you to our cog 
      board to request it for a third-party cog
      
If you are requesting a command:
    - Include what cog it should be in and a name for the command
    - Describe the intended functionality for the command
    - Note any restrictions on who can use the command or where it can be used

If you are requesting API functionality:
    - Describe what it should do
    - Note whether it is to extend existing functionality or introduce new functionality
   
-->


The menu tool provided by Red currently do the following steps when called:

1. Post the message
2. Add the reactions to the message
3. Start listening to the reactions
4. Do something when the message received a reaction.

This should be modified to work like that:

1. Post the message
2. **Start listening to the reactions**
3. **Add the reactions to the message**
4. Do something when the message received a reaction.

Currently, we have to wait for all of the reactions before clicking on something. This is quite annoying, especially with the `[p]search` command of Audio, which adds a lot of reactions. For example, if we already know that we want the number 2 result, we can't click on 2️⃣, we need to wait for all reactions before acting.


Discussion:
I'll give this a go but I don't think I'll be able to make the order of execution so deterministic, but rather allow the event loop to give the impression that it happens in this order, using `create_task`

Resolving patch:
diff --git a/redbot/core/utils/menus.py b/redbot/core/utils/menus.py
--- a/redbot/core/utils/menus.py
+++ b/redbot/core/utils/menus.py
@@ -5,10 +5,14 @@
 Ported to Red V3 by Palm\_\_ (https://github.com/palmtree5)
 """
 import asyncio
+import contextlib
+from typing import Union, Iterable
 import discord
 
 from redbot.core import commands
 
+_ReactableEmoji = Union[str, discord.Emoji]
+
 
 async def menu(
     ctx: commands.Context,
@@ -66,8 +70,8 @@ async def menu(
             message = await ctx.send(embed=current_page)
         else:
             message = await ctx.send(current_page)
-        for key in controls.keys():
-            await message.add_reaction(key)
+        # Don't wait for reactions to be added (GH-1797)
+        ctx.bot.loop.create_task(_add_menu_reactions(message, controls.keys()))
     else:
         if isinstance(current_page, discord.Embed):
             await message.edit(embed=current_page)
@@ -148,4 +152,12 @@ async def close_menu(
     return None
 
 
+async def _add_menu_reactions(message: discord.Message, emojis: Iterable[_ReactableEmoji]):
+    """Add the reactions"""
+    # The task should exit silently if the message is deleted
+    with contextlib.suppress(discord.NotFound):
+        for emoji in emojis:
+            await message.add_reaction(emoji)
+
+
 DEFAULT_CONTROLS = {"⬅": prev_page, "❌": close_menu, "➡": next_page}


Test patch: