Skip to content

Commit b085121

Browse files
committed
Added option kwargs pass.
1 parent 5976830 commit b085121

File tree

1 file changed

+53
-33
lines changed

1 file changed

+53
-33
lines changed

discord_slash/client.py

Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ def override_remove_cog(name: str):
7676
self.remove_cog_commands(cog)
7777
default_remove_function(name)
7878
self._discord.remove_cog = override_remove_cog
79-
80-
8179

8280
def get_cog_commands(self, cog: commands.Cog):
8381
"""
@@ -608,7 +606,7 @@ def wrapper(cmd):
608606

609607
return wrapper
610608

611-
async def process_options(self, guild: discord.Guild, options: list, auto_convert: dict) -> list:
609+
async def process_options(self, guild: discord.Guild, options: list, auto_convert: dict) -> typing.Union[list, dict]:
612610
"""
613611
Processes Role, User, and Channel option types to discord.py's models.
614612
@@ -618,7 +616,7 @@ async def process_options(self, guild: discord.Guild, options: list, auto_conver
618616
:type options: list
619617
:param auto_convert: Dictionary of how to convert option values.
620618
:type auto_convert: dict
621-
:return: list
619+
:return: Union[list, dict]
622620
"""
623621
if not guild:
624622
self.logger.info("This command invoke is missing guild. Skipping option process.")
@@ -631,6 +629,9 @@ async def process_options(self, guild: discord.Guild, options: list, auto_conver
631629
return [x["value"] for x in options]
632630

633631
converters = [
632+
# If extra converters are added and some needs to fetch it,
633+
# you should pass as a list with 1st item as a cache get method
634+
# and 2nd as a actual fetching method.
634635
[guild.get_member, guild.fetch_member],
635636
guild.get_channel,
636637
guild.get_role
@@ -654,30 +655,58 @@ async def process_options(self, guild: discord.Guild, options: list, auto_conver
654655
"8": 2
655656
}
656657

657-
to_return = []
658+
to_return = {}
658659

659660
for x in options:
660661
selected = x
661662
if selected["name"] in auto_convert:
663+
processed = None # This isn't the best way, but we should to reduce duplicate lines.
662664
if auto_convert[selected["name"]] not in types:
663-
to_return.append(selected["value"])
664-
continue
665-
loaded_converter = converters[types[auto_convert[selected["name"]]]]
666-
if isinstance(loaded_converter, list):
667-
cache_first = loaded_converter[0](int(selected["value"]))
668-
if cache_first:
669-
to_return.append(cache_first)
670-
continue
671-
loaded_converter = loaded_converter[1]
672-
try:
673-
to_return.append(await loaded_converter(int(selected["value"]))) \
674-
if iscoroutinefunction(loaded_converter) else \
675-
to_return.append(loaded_converter(int(selected["value"])))
676-
except (discord.Forbidden, discord.HTTPException):
677-
self.logger.warning("Failed fetching user! Passing ID instead.")
678-
to_return.append(int(selected["value"]))
665+
processed = selected["value"]
666+
else:
667+
loaded_converter = converters[types[auto_convert[selected["name"]]]]
668+
if isinstance(loaded_converter, list): # For user type.
669+
cache_first = loaded_converter[0](int(selected["value"]))
670+
if cache_first:
671+
processed = cache_first
672+
else:
673+
loaded_converter = loaded_converter[1]
674+
if not processed:
675+
try:
676+
processed = await loaded_converter(int(selected["value"])) \
677+
if iscoroutinefunction(loaded_converter) else \
678+
loaded_converter(int(selected["value"]))
679+
except (discord.Forbidden, discord.HTTPException, discord.NotFound): # Just in case.
680+
self.logger.warning("Failed fetching discord object! Passing ID instead.")
681+
processed = int(selected["value"])
682+
to_return[selected["name"]] = processed
683+
else:
684+
to_return[selected["name"]] = selected["value"]
679685
return to_return
680686

687+
async def invoke_command(self, func, ctx, args):
688+
"""
689+
Invokes command.
690+
691+
:param func: Command coroutine.
692+
:param ctx: Context.
693+
:param args: Args. Can be list or dict.
694+
"""
695+
try:
696+
not_kwargs = False
697+
if isinstance(args, dict):
698+
try:
699+
await func.invoke(ctx, **args)
700+
except TypeError:
701+
args = list(args.values())
702+
not_kwargs = True
703+
else:
704+
not_kwargs = True
705+
if not_kwargs:
706+
await func.invoke(ctx, *args)
707+
except Exception as ex:
708+
await self.on_slash_command_error(ctx, ex)
709+
681710
async def on_socket_response(self, msg):
682711
"""
683712
This event listener is automatically registered at initialization of this class.
@@ -721,10 +750,7 @@ async def on_socket_response(self, msg):
721750

722751
self._discord.dispatch("slash_command", ctx)
723752

724-
try:
725-
await selected_cmd.invoke(ctx, *args)
726-
except Exception as ex:
727-
await self.on_slash_command_error(ctx, ex)
753+
await self.invoke_command(selected_cmd, ctx, args)
728754

729755
async def handle_subcommand(self, ctx: context.SlashContext, data: dict):
730756
"""
@@ -755,19 +781,13 @@ async def handle_subcommand(self, ctx: context.SlashContext, data: dict):
755781
args = await self.process_options(ctx.guild, x["options"], selected.auto_convert) \
756782
if "options" in x else []
757783
self._discord.dispatch("slash_command", ctx)
758-
try:
759-
await selected.invoke(ctx, *args)
760-
except Exception as ex:
761-
await self.on_slash_command_error(ctx, ex)
784+
await self.invoke_command(selected, ctx, args)
762785
return
763786
selected = base[sub_name]
764787
args = await self.process_options(ctx.guild, sub_opts, selected.auto_convert) \
765788
if "options" in sub else []
766789
self._discord.dispatch("slash_command", ctx)
767-
try:
768-
await selected.invoke(ctx, *args)
769-
except Exception as ex:
770-
await self.on_slash_command_error(ctx, ex)
790+
await self.invoke_command(selected, ctx, args)
771791

772792
async def on_slash_command_error(self, ctx, ex):
773793
"""

0 commit comments

Comments
 (0)