Repository: Pycord-Development/pycord

Issue:
Can't create bridge group in a cog
### Summary

Cog with bridge group throws error

### Reproduction Steps

Create bridge group inside a cog

### Minimal Reproducible Code

```python
class TestCog(commands.Cog):
    @bridge.bridge_group()
    async def test(self, ctx):
        await ctx.respond("ok")
```


### Expected Results

Cog creation

### Actual Results

```py
Traceback (most recent call last):
  File "D:\coding\DandelionMusic\run.py", line 36, in <module>
    class TestCog(commands.Cog):
  File "D:\coding\dandelion_env\lib\site-packages\discord\cog.py", line 238, in __new__
    new_cls.__cog_commands__ = tuple(c._update_copy(cmd_attrs) for c in new_cls.__cog_commands__)  # type: ignore
  File "D:\coding\dandelion_env\lib\site-packages\discord\cog.py", line 238, in <genexpr>
    new_cls.__cog_commands__ = tuple(c._update_copy(cmd_attrs) for c in new_cls.__cog_commands__)  # type: ignore
  File "D:\coding\dandelion_env\lib\site-packages\discord\commands\core.py", line 1262, in _update_copy
    return self.copy()
  File "D:\coding\dandelion_env\lib\site-packages\discord\commands\core.py", line 1230, in copy
    ret = self.__class__(
TypeError: __init__() missing 1 required positional argument: 'callback'
```

### Intents

default + message_content

### System Information

- Python v3.9.9-final
- py-cord v2.1.3-final
- aiohttp v3.8.1
- system info: Windows 10 10.0.17763

### 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

_No response_


Discussion:

Resolving patch:
diff --git a/discord/cog.py b/discord/cog.py
--- a/discord/cog.py
+++ b/discord/cog.py
@@ -178,12 +178,9 @@ def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta:
                 if elem in listeners:
                     del listeners[elem]
 
-                try:
-                    if getattr(value, "parent") is not None and isinstance(value, ApplicationCommand):
-                        # Skip commands if they are a part of a group
-                        continue
-                except AttributeError:
-                    pass
+                if getattr(value, "parent", None) and isinstance(value, ApplicationCommand):
+                    # Skip commands if they are a part of a group
+                    continue
 
                 is_static_method = isinstance(value, staticmethod)
                 if is_static_method:
@@ -195,10 +192,8 @@ def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta:
                         raise TypeError(no_bot_cog.format(base, elem))
                     commands[elem] = value
 
-                try:
-                    # a test to see if this value is a BridgeCommand
-                    getattr(value, "add_to")
-
+                # a test to see if this value is a BridgeCommand
+                if hasattr(value, "add_to") and not getattr(value, "parent", None):
                     if is_static_method:
                         raise TypeError(f"Command in method {base}.{elem!r} must not be staticmethod.")
                     if elem.startswith(("cog_", "bot_")):
@@ -206,9 +201,6 @@ def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta:
 
                     commands[f"ext_{elem}"] = value.ext_variant
                     commands[f"application_{elem}"] = value.slash_variant
-                except AttributeError:
-                    # we are confident that the value is not a Bridge Command
-                    pass
 
                 if inspect.iscoroutinefunction(value):
                     try:
diff --git a/discord/ext/bridge/core.py b/discord/ext/bridge/core.py
--- a/discord/ext/bridge/core.py
+++ b/discord/ext/bridge/core.py
@@ -87,6 +87,7 @@ class BridgeSlashGroup(SlashCommandGroup):
     def __init__(self, callback, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.callback = callback
+        self.__original_kwargs__["callback"] = callback
         self.__command = None
 
     async def _invoke(self, ctx: BridgeApplicationContext) -> None:
@@ -107,6 +108,7 @@ class BridgeExtGroup(BridgeExtCommand, Group):
     """A subclass of :class:`.ext.commands.Group` that is used for bridge commands."""
     pass
 
+
 class BridgeCommand:
     """Compatibility class between prefixed-based commands and slash commands.
 
@@ -122,10 +124,13 @@ class BridgeCommand:
     callback: Callable[[:class:`.BridgeContext`, ...], Awaitable[Any]]
         The callback to invoke when the command is executed. The first argument will be a :class:`BridgeContext`,
         and any additional arguments will be passed to the callback. This callback must be a coroutine.
+    parent: Optional[:class:`.BridgeCommandGroup`]:
+        Parent of the BridgeCommand.
     kwargs: Optional[Dict[:class:`str`, Any]]
         Keyword arguments that are directly passed to the respective command constructors. (:class:`.SlashCommand` and :class:`.ext.commands.Command`)
     """
     def __init__(self, callback, **kwargs):
+        self.parent = kwargs.pop("parent", None)
         self.slash_variant: BridgeSlashCommand = kwargs.pop("slash_variant", None) or BridgeSlashCommand(callback, **kwargs)
         self.ext_variant: BridgeExtCommand = kwargs.pop("ext_variant", None) or BridgeExtCommand(callback, **kwargs)
 
@@ -295,8 +300,8 @@ def command(self, *args, **kwargs):
         """
         def wrap(callback):
             slash = self.slash_variant.command(*args, **filter_params(kwargs, brief="description"), cls=BridgeSlashCommand)(callback)
-            ext = self.ext_variant.command(*args, **filter_params(kwargs, description="brief"), cls=BridgeExtGroup)(callback)
-            command = BridgeCommand(callback, slash_variant=slash, ext_variant=ext)
+            ext = self.ext_variant.command(*args, **filter_params(kwargs, description="brief"), cls=BridgeExtCommand)(callback)
+            command = BridgeCommand(callback, parent=self, slash_variant=slash, ext_variant=ext)
             self.subcommands.append(command)
             return command
 


Test patch: