Skip to content

Commit 6170c6b

Browse files
committed
Add support for slash-command groups on cogs
1 parent d8c4da6 commit 6170c6b

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

discord/cog.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import discord.utils
3030
import types
3131
from . import errors
32-
from .commands import SlashCommand, UserCommand, MessageCommand, ApplicationCommand
32+
from .commands import SlashCommand, UserCommand, MessageCommand, ApplicationCommand, SlashCommandGroup
3333

3434
from typing import Any, Callable, Mapping, ClassVar, Dict, Generator, List, Optional, TYPE_CHECKING, Tuple, TypeVar, Type
3535

@@ -145,6 +145,13 @@ def __new__(cls: Type[CogMeta], *args: Any, **kwargs: Any) -> CogMeta:
145145
if elem in listeners:
146146
del listeners[elem]
147147

148+
try:
149+
if getattr(value, "parent") is not None:
150+
# Skip commands if they are apart of a group
151+
continue
152+
except AttributeError:
153+
pass
154+
148155
is_static_method = isinstance(value, staticmethod)
149156
if is_static_method:
150157
value = value.__func__
@@ -445,7 +452,8 @@ def _inject(self: CogT, bot) -> CogT:
445452
# we've added so far for some form of atomic loading.
446453

447454
for index, command in enumerate(self.__cog_commands__):
448-
command.cog = self
455+
command._set_cog(self)
456+
449457
if not isinstance(command, ApplicationCommand):
450458
if command.parent is None:
451459
try:

discord/commands/commands.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,9 @@ def qualified_name(self) -> str:
317317
else:
318318
return self.name
319319

320+
def _set_cog(self, cog):
321+
self.cog = cog
322+
320323
class SlashCommand(ApplicationCommand):
321324
r"""A class that implements the protocol for a slash command.
322325
@@ -771,6 +774,7 @@ def to_dict(self) -> Dict:
771774
"name": self.name,
772775
"description": self.description,
773776
"options": [c.to_dict() for c in self.subcommands],
777+
"default_permission": self.default_permission
774778
}
775779

776780
if self.parent is not None:
@@ -848,6 +852,49 @@ async def invoke_autocomplete_callback(self, ctx: AutocompleteContext) -> None:
848852
ctx.interaction.data = option
849853
await command.invoke_autocomplete_callback(ctx)
850854

855+
def copy(self):
856+
"""Creates a copy of this command group.
857+
858+
Returns
859+
--------
860+
:class:`SlashCommandGroup`
861+
A new instance of this command.
862+
"""
863+
ret = self.__class__(
864+
self.name,
865+
self.description,
866+
**self.__original_kwargs__)
867+
return self._ensure_assignment_on_copy(ret)
868+
869+
def _ensure_assignment_on_copy(self, other):
870+
other.parent = self.parent
871+
872+
other._before_invoke = self._before_invoke
873+
other._after_invoke = self._after_invoke
874+
875+
if self.subcommands != other.subcommands:
876+
other.subcommands = self.subcommands.copy()
877+
878+
if self.checks != other.checks:
879+
other.checks = self.checks.copy()
880+
881+
return other
882+
883+
def _update_copy(self, kwargs: Dict[str, Any]):
884+
if kwargs:
885+
kw = kwargs.copy()
886+
kw.update(self.__original_kwargs__)
887+
copy = self.__class__(self.callback, **kw)
888+
return self._ensure_assignment_on_copy(copy)
889+
else:
890+
return self.copy()
891+
892+
def _set_cog(self, cog):
893+
self.cog = cog
894+
for subcommand in self.subcommands:
895+
subcommand._set_cog(cog)
896+
897+
851898

852899
class ContextMenuCommand(ApplicationCommand):
853900
r"""A class that implements the protocol for context menu commands.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from discord.commands.permissions import Permission
2+
import discord
3+
from discord.commands.commands import SlashCommandGroup
4+
from discord.ext import commands
5+
6+
# Set these
7+
GUILD_ID=0
8+
OWNER_ID=0
9+
10+
bot = discord.Bot(debug_guild=GUILD_ID, owner_id=OWNER_ID)
11+
12+
class Example(commands.Cog):
13+
def __init__(self, bot):
14+
self.bot = bot
15+
16+
greetings = SlashCommandGroup("greetings", "Various greeting from cogs!")
17+
international_greetings = greetings.command_group("international", "International greetings")
18+
19+
secret_greetings = SlashCommandGroup("secret_greetings", "Secret greetings", permissions=[
20+
Permission("owner", 2, True) # Ensures the owner_id user can access this, and noone else
21+
])
22+
23+
@greetings.command()
24+
async def hello(self, ctx):
25+
await ctx.respond("Hi, this is a slash command from a cog!")
26+
27+
@international_greetings.command()
28+
async def aloha(self, ctx):
29+
await ctx.respond("Aloha, a Hawaiian greeting")
30+
31+
32+
@greetings.command()
33+
async def hi(self, ctx):
34+
await ctx.respond(f"Hi, this is a slash sub-command from a cog!")
35+
36+
@secret_greetings.command()
37+
async def secret_handshake(self, ctx, member: discord.Member):
38+
await ctx.respond(f"{member.mention} secret handshakes you")
39+
40+
41+
bot.add_cog(Example(bot))
42+
43+
44+
bot.run("TOKEN")

0 commit comments

Comments
 (0)