Repository: Pycord-Development/pycord

Issue:
SlashCommandGroup.before_invoke
### Summary

before_invoke is not called in Slash Command Group

### Reproduction Steps

Same steps as if i were using Bot.goup()

*  Creating a group
*  Creating  a command
*  Instruct  the program what to do before the command should be invoked

### Minimal Reproducible Code

```python
channel = d.SlashCommandGroup(name = "channel", description = "Create something", default_member_permissions = d.Permissions(manage_channels = True))

    @channel.command()
    async def test(self, ctx:d.ApplicationContext, text = None):
        print(ctx.guild.categories)
        return

    @channel.before_invoke
    async def check_channels(self, ctx:d.ApplicationContext):

        print("test, before_invoke")
        
        return
```


### Expected Results

Expected it to print out "before_invoke " in the terminal, before the command invoked.

### Actual Results

Function not even called

### Intents

bans, guilds, emojis, typing, members, messages, prresence, message_content

### System Information

- Python v3.10.10-final                                                                                                
- py-cord v2.4.None-final                                                                                              
- aiohttp v3.8.4                                                                                                        
- system info: Windows 10 10.0.19045

### Checklist

- [X] I have searched the open issues for duplicates.
- [X] I have shown the entire traceback, if possible.
- [X] I have removed my token from display, if visible.

### Additional Context

For further details on what has been already tested visit discord  channel search for before  & after  invoke by krigjo25

The code above is tested, and is just a demo, to show @before_invoke  doesnt work. The actual code can be found in the authors responsories. if more code information is required, the bot code source can be found at the authors responsories called Discord /pymod

* `@after_invoke` works as expected

Case has been discussed in the discord channel, recently closed since the helper also might think its a library issue. 

Thanks for reading this issues, and for the assistance.

sincerely 
@krigjo25


Discussion:

Resolving patch:
diff --git a/discord/commands/core.py b/discord/commands/core.py
--- a/discord/commands/core.py
+++ b/discord/commands/core.py
@@ -84,6 +84,7 @@
 
     from .. import Permissions
     from ..cog import Cog
+    from ..ext.commands.cooldowns import CooldownMapping, MaxConcurrency
 
 T = TypeVar("T")
 CogT = TypeVar("CogT", bound="Cog")
@@ -294,18 +295,17 @@ async def prepare(self, ctx: ApplicationContext) -> None:
                 f"The check functions for the command {self.name} failed"
             )
 
-        if hasattr(self, "_max_concurrency"):
-            if self._max_concurrency is not None:
-                # For this application, context can be duck-typed as a Message
-                await self._max_concurrency.acquire(ctx)  # type: ignore # ctx instead of non-existent message
+        if self._max_concurrency is not None:
+            # For this application, context can be duck-typed as a Message
+            await self._max_concurrency.acquire(ctx)  # type: ignore # ctx instead of non-existent message
 
-            try:
-                self._prepare_cooldowns(ctx)
-                await self.call_before_hooks(ctx)
-            except:
-                if self._max_concurrency is not None:
-                    await self._max_concurrency.release(ctx)  # type: ignore # ctx instead of non-existent message
-                raise
+        try:
+            self._prepare_cooldowns(ctx)
+            await self.call_before_hooks(ctx)
+        except:
+            if self._max_concurrency is not None:
+                await self._max_concurrency.release(ctx)  # type: ignore # ctx instead of non-existent message
+            raise
 
     def is_on_cooldown(self, ctx: ApplicationContext) -> bool:
         """Checks whether the command is currently on cooldown.
@@ -1119,6 +1119,8 @@ def __init__(
         description: str | None = None,
         guild_ids: list[int] | None = None,
         parent: SlashCommandGroup | None = None,
+        cooldown: CooldownMapping | None = None,
+        max_concurrency: MaxConcurrency | None = None,
         **kwargs,
     ) -> None:
         self.name = str(name)
@@ -1153,6 +1155,33 @@ def __init__(
             "description_localizations", MISSING
         )
 
+        # similar to ApplicationCommand
+        from ..ext.commands.cooldowns import BucketType, CooldownMapping, MaxConcurrency
+
+        # no need to getattr, since slash cmds groups cant be created using a decorator
+
+        if cooldown is None:
+            buckets = CooldownMapping(cooldown, BucketType.default)
+        elif isinstance(cooldown, CooldownMapping):
+            buckets = cooldown
+        else:
+            raise TypeError(
+                "Cooldown must be a an instance of CooldownMapping or None."
+            )
+
+        self._buckets: CooldownMapping = buckets
+
+        # no need to getattr, since slash cmds groups cant be created using a decorator
+
+        if max_concurrency is not None and not isinstance(
+            max_concurrency, MaxConcurrency
+        ):
+            raise TypeError(
+                "max_concurrency must be an instance of MaxConcurrency or None"
+            )
+
+        self._max_concurrency: MaxConcurrency | None = max_concurrency
+
     @property
     def module(self) -> str | None:
         return self.__module__


Test patch: