Skip to content

Commit 5273ae3

Browse files
committed
Changed all command dict to object
1 parent ce6bb75 commit 5273ae3

File tree

3 files changed

+110
-53
lines changed

3 files changed

+110
-53
lines changed

discord_slash/client.py

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class SlashCommand:
2626
:ivar auto_register: Whether to register commands automatically.
2727
:ivar has_listener: Whether discord client has listener add function.
2828
"""
29+
2930
def __init__(self,
3031
client: typing.Union[discord.Client, commands.Bot],
3132
auto_register: bool = False,
@@ -38,7 +39,8 @@ def __init__(self,
3839
self.auto_register = auto_register
3940
if self.auto_register:
4041
self._discord.loop.create_task(self.register_all_commands())
41-
if not isinstance(client, commands.Bot) and not isinstance(client, commands.AutoShardedBot) and not override_type:
42+
if not isinstance(client, commands.Bot) and not isinstance(client,
43+
commands.AutoShardedBot) and not override_type:
4244
self.logger.info("Detected discord.Client! Overriding on_socket_response.")
4345
self._discord.on_socket_response = self.on_socket_response
4446
self.has_listener = False
@@ -58,12 +60,33 @@ def remove(self):
5860
return
5961
self._discord.remove_listener(self.on_socket_response)
6062

63+
def get_cog_commands(self, cog: commands.Cog):
64+
func_list = [getattr(cog, x) for x in dir(cog)]
65+
res = [x for x in func_list if
66+
isinstance(x, model.CogCommandObject) or isinstance(x, model.CogSubcommandObject)]
67+
for x in res:
68+
if isinstance(x, model.CogCommandObject):
69+
self.commands[x.name] = x
70+
else:
71+
if x.base in self.commands.keys():
72+
self.commands[x.base].allowed_guild_ids += x.allowed_guild_ids
73+
self.commands[x.base].has_subcommands = True
74+
if x.base not in self.subcommands.keys():
75+
self.subcommands[x.base] = {}
76+
if x.subcommand_group:
77+
if x.subcommand_group not in self.subcommands:
78+
self.subcommands[x.base][x.subcommand_group] = {}
79+
else:
80+
self.subcommands[x.base][x.subcommand_group][x.name] = x
81+
else:
82+
self.subcommands[x.base][x.name] = x
83+
6184
async def register_all_commands(self):
6285
"""
6386
Registers all slash commands except subcommands to Discord API.\n
6487
If ``auto_register`` is ``True``, then this will be automatically called.
6588
"""
66-
await self._discord.wait_until_ready() # In case commands are still not registered to SlashCommand.
89+
await self._discord.wait_until_ready() # In case commands are still not registered to SlashCommand.
6790
self.logger.info("Registering commands...")
6891
for x in self.commands.keys():
6992
selected = self.commands[x]
@@ -129,7 +152,7 @@ def add_slash_command(self,
129152
"api_options": options if options else [],
130153
"has_subcommands": has_subcommands
131154
}
132-
self.commands[name] = _cmd
155+
self.commands[name] = model.CommandObject(name, _cmd)
133156
self.logger.debug(f"Added command `{name}`")
134157

135158
def add_subcommand(self,
@@ -163,7 +186,11 @@ def add_subcommand(self,
163186
name = cmd.__name__ if not name else name
164187
name = name.lower()
165188
_cmd = {
189+
"func": None,
190+
"description": description if description else "No description.",
191+
"auto_convert": {},
166192
"guild_ids": guild_ids,
193+
"api_options": [],
167194
"has_subcommands": True
168195
}
169196
_sub = {
@@ -174,18 +201,20 @@ def add_subcommand(self,
174201
"guild_ids": guild_ids,
175202
}
176203
if base not in self.commands.keys():
177-
self.commands[base] = _cmd
204+
self.commands[base] = model.CommandObject(base, _cmd)
178205
else:
179-
self.subcommands[base]["has_subcommands"] = True
206+
self.subcommands[base].has_subcommands = True
207+
self.subcommands[base].guild_ids += guild_ids
180208
if base not in self.subcommands.keys():
181209
self.subcommands[base] = {}
182210
if subcommand_group:
183211
if subcommand_group not in self.subcommands[base].keys():
184212
self.subcommands[base][subcommand_group] = {}
185-
self.subcommands[base][subcommand_group][name] = _sub
213+
self.subcommands[base][subcommand_group][name] = model.SubcommandObject(_sub, base, name, subcommand_group)
186214
else:
187-
self.subcommands[base][name] = _sub
188-
self.logger.debug(f"Added subcommand `{base} {subcommand_group if subcommand_group else ''} {cmd.__name__ if not name else name}`")
215+
self.subcommands[base][name] = model.SubcommandObject(_sub, base, name)
216+
self.logger.debug(
217+
f"Added subcommand `{base} {subcommand_group if subcommand_group else ''} {cmd.__name__ if not name else name}`")
189218

190219
def slash(self,
191220
*,
@@ -259,6 +288,7 @@ async def _pick(ctx, choice1, choice2): # Command with 1 or more args.
259288
def wrapper(cmd):
260289
self.add_slash_command(cmd, name, description, auto_convert, guild_ids, options)
261290
return cmd
291+
262292
return wrapper
263293

264294
def subcommand(self,
@@ -311,6 +341,7 @@ async def _group_kick_user(ctx, user):
311341
def wrapper(cmd):
312342
self.add_subcommand(cmd, base, subcommand_group, name, description, auto_convert, guild_ids)
313343
return cmd
344+
314345
return wrapper
315346

316347
async def process_options(self, guild: discord.Guild, options: list, auto_convert: dict) -> list:
@@ -388,18 +419,21 @@ async def on_socket_response(self, msg):
388419
return
389420
to_use = msg["d"]
390421
if to_use["data"]["name"] in self.commands.keys():
391-
selected_cmd = self.commands[to_use["data"]["name"]]
392422
ctx = model.SlashContext(self.req, to_use, self._discord, self.logger)
393-
if selected_cmd["guild_ids"]:
394-
if ctx.guild.id not in selected_cmd["guild_ids"]:
423+
cmd_name = to_use["data"]["name"]
424+
if cmd_name not in self.commands.keys() and cmd_name in self.subcommands.keys():
425+
return await self.handle_subcommand(ctx, to_use)
426+
selected_cmd = self.commands[to_use["data"]["name"]]
427+
if selected_cmd.allowed_guild_ids:
428+
if ctx.guild.id not in selected_cmd.allowed_guild_ids:
395429
return
396-
if selected_cmd["has_subcommands"]:
430+
if selected_cmd.has_subcommands:
397431
return await self.handle_subcommand(ctx, to_use)
398-
args = await self.process_options(ctx.guild, to_use["data"]["options"], selected_cmd["auto_convert"]) \
432+
args = await self.process_options(ctx.guild, to_use["data"]["options"], selected_cmd.auto_convert) \
399433
if "options" in to_use["data"] else []
400434
self._discord.dispatch("slash_command", ctx)
401435
try:
402-
await selected_cmd["func"](ctx, *args)
436+
await selected_cmd.invoke(ctx, *args)
403437
except Exception as ex:
404438
await self.on_slash_command_error(ctx, ex)
405439

@@ -429,20 +463,20 @@ async def handle_subcommand(self, ctx: model.SlashContext, data: dict):
429463
return
430464
ctx.subcommand_group = sub_group
431465
selected = base[sub_name][sub_group]
432-
args = await self.process_options(ctx.guild, x["options"], selected["auto_convert"]) \
466+
args = await self.process_options(ctx.guild, x["options"], selected.auto_convert) \
433467
if "options" in x.keys() else []
434468
self._discord.dispatch("slash_command", ctx)
435469
try:
436-
await selected["func"](ctx, *args)
470+
await selected.invoke(ctx, *args)
437471
except Exception as ex:
438472
await self.on_slash_command_error(ctx, ex)
439473
return
440474
selected = base[sub_name]
441-
args = await self.process_options(ctx.guild, sub_opts, selected["auto_convert"]) \
475+
args = await self.process_options(ctx.guild, sub_opts, selected.auto_convert) \
442476
if "options" in sub.keys() else []
443477
self._discord.dispatch("slash_command", ctx)
444478
try:
445-
await selected["func"](ctx, *args)
479+
await selected.invoke(ctx, *args)
446480
except Exception as ex:
447481
await self.on_slash_command_error(ctx, ex)
448482

discord_slash/cog_ext.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import typing
2+
from discord.ext import commands
3+
from .model import CogCommandObject, CogSubcommandObject
4+
5+
6+
def cog_slash(*,
7+
name: str = None,
8+
description: str = None,
9+
auto_convert: dict = None,
10+
guild_ids: typing.List[int] = None,
11+
options: typing.List[dict] = None):
12+
def wrapper(cmd):
13+
_cmd = {
14+
"func": cmd,
15+
"description": description if description else "No description.",
16+
"auto_convert": auto_convert,
17+
"guild_ids": guild_ids,
18+
"api_options": options if options else [],
19+
"has_subcommands": False
20+
}
21+
return CogCommandObject(name, _cmd)
22+
return wrapper
23+
24+
25+
def register_cog_slash(cls):
26+
func_list = [getattr(cls, x) for x in dir(cls)]
27+
return [x for x in func_list if isinstance(x, CogCommandObject) or isinstance(x, CogSubcommandObject)]

discord_slash/model.py

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -170,38 +170,34 @@ async def delete(self, message_id: typing.Union[int, str] = "@original"):
170170
await self._http.delete(self._discord.user.id, self.__token, message_id)
171171

172172

173-
"""
174-
{
175-
"type": 2,
176-
"token": "A_UNIQUE_TOKEN",
177-
"member": {
178-
"user": {
179-
"id": 53908232506183680,
180-
"username": "Mason",
181-
"avatar": "a_d5efa99b3eeaa7dd43acca82f5692432",
182-
"discriminator": "1337",
183-
"public_flags": 131141
184-
},
185-
"roles": [539082325061836999],
186-
"premium_since": null,
187-
"permissions": "2147483647",
188-
"pending": false,
189-
"nick": null,
190-
"mute": false,
191-
"joined_at": "2017-03-13T19:19:14.040000+00:00",
192-
"is_pending": false,
193-
"deaf": false
194-
},
195-
"id": "786008729715212338",
196-
"guild_id": "290926798626357999",
197-
"data": {
198-
"options": [{
199-
"name": "cardname",
200-
"value": "The Gitrog Monster"
201-
}],
202-
"name": "cardsearch",
203-
"id": "771825006014889984"
204-
},
205-
"channel_id": "645027906669510667"
206-
}
207-
"""
173+
class CommandObject:
174+
def __init__(self, name, cmd, *subcommands): # Let's reuse old command formatting.
175+
self.name = name
176+
self.invoke = cmd["func"]
177+
self.description = cmd["description"]
178+
self.auto_convert = cmd["auto_convert"]
179+
self.allowed_guild_ids = cmd["guild_ids"]
180+
self.options = cmd["api_options"]
181+
self.has_subcommands = cmd["has_subcommands"]
182+
self.subcommands = subcommands
183+
184+
185+
class SubcommandObject:
186+
def __init__(self, sub, base, name, sub_group=None):
187+
self.base = base
188+
self.subcommand_group = sub_group
189+
self.name = name
190+
self.invoke = sub["func"]
191+
self.description = sub["description"]
192+
self.auto_convert = sub["auto_convert"]
193+
self.allowed_guild_ids = sub["guild_ids"]
194+
195+
196+
class CogCommandObject(CommandObject):
197+
def __init__(self, *args):
198+
super().__init__(*args)
199+
200+
201+
class CogSubcommandObject(SubcommandObject):
202+
def __init__(self, *args):
203+
super().__init__(*args)

0 commit comments

Comments
 (0)