Skip to content

Commit

Permalink
fix!: Correct gateway command and subcommand dispatching (#559)
Browse files Browse the repository at this point in the history
* fix!: correct kwarg dictionary when dispatching a command

* undo changes in dispatch

* fix!: argument conversion for non-sub-commands

* fix!: sub-command keyerror

* fix!: _client for attributes and sub_command(_group) convertion

* Update headers

* Update gateway.py

* fix!: add _client to slots

* style: rename dunder

Co-authored-by: fl0w <41456914+goverfl0w@users.noreply.github.com>
  • Loading branch information
EdVraz and i0bs committed Feb 25, 2022
1 parent a500da9 commit acef57f
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 24 deletions.
1 change: 1 addition & 0 deletions interactions/api/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def dispatch(self, __name: str, *args, **kwargs) -> None:
:type \**kwargs: dict
"""
for event in self.events.get(__name, []):

self.loop.create_task(event(*args, **kwargs))
log.debug(f"DISPATCH: {event}")

Expand Down
89 changes: 68 additions & 21 deletions interactions/api/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,17 +310,23 @@ def _dispatch_event(self, event: str, data: dict) -> None:

if _context.data._json.get("options"):
for option in _context.data.options:
__kwargs.update(self.__sub_command_context(option))
__kwargs.update(
self.__option_type_context(
_context,
(
option["type"]
if isinstance(option, dict)
else option.type.value
),
)
_type = self.__option_type_context(
_context,
(
option["type"]
if isinstance(option, dict)
else option.type.value
),
)
if _type:
if isinstance(option, dict):
_type[option["value"]]._client = self._http
option.update({"value": _type[option["value"]]})
else:
_type[option.value]._client = self._http
option._json.update({"value": _type[option.value]})
_option = self.__sub_command_context(option, _context)
__kwargs.update(_option)

self._dispatch.dispatch("on_command", _context)
elif data["type"] == InteractionType.MESSAGE_COMPONENT:
Expand Down Expand Up @@ -390,7 +396,9 @@ def __contextualize(self, data: dict) -> object:
context: object = getattr(__import__("interactions.context"), _context)
return context(**data)

def __sub_command_context(self, data: Union[dict, Option]) -> Union[Tuple[str], dict]:
def __sub_command_context(
self, data: Union[dict, Option], _context: Optional[object] = MISSING
) -> Union[Tuple[str], dict]:
"""
Checks if an application command schema has sub commands
needed for argument collection.
Expand All @@ -404,23 +412,62 @@ def __sub_command_context(self, data: Union[dict, Option]) -> Union[Tuple[str],
_data: dict = data._json if isinstance(data, Option) else data

def _check_auto(option: dict) -> Optional[Tuple[str]]:
if option.get("focused"):
return (option["name"], option["value"])
try:
if option.get("focused"):
return (option["name"], option["value"])
except AttributeError:
return False

x = _check_auto(_data)
if x:
return x
if _data.get("options"):
for option in _data["options"]:
if option["type"] == OptionType.SUB_COMMAND:
for sub_option in _data["options"]:
if _data["type"] == OptionType.SUB_COMMAND:
__kwargs["sub_command"] = _data["name"]
for sub_option in _data["options"]:
_check_auto(sub_option)
_option_context = self.__option_type_context(
_context,
(
sub_option["type"]
if isinstance(sub_option, dict)
else sub_option.type.value
),
)
if _option_context:
if isinstance(sub_option, dict):
_option_context[sub_option["value"]]._client = self._http
sub_option.update({"value": _option_context[sub_option["value"]]})
else:
_option_context[sub_option.value]._client = self._http
sub_option._json.update({"value": _option_context[sub_option.value]})
__kwargs[sub_option["name"]] = sub_option["value"]
elif _data["type"] == OptionType.SUB_COMMAND_GROUP:
__kwargs["sub_command_group"] = _data["name"]
for _group_option in _data["options"]:
_check_auto(_group_option)
__kwargs["sub_command"] = _group_option["name"]
for sub_option in _group_option["options"]:
_check_auto(sub_option)
_option_context = self.__option_type_context(
_context,
(
sub_option["type"]
if isinstance(sub_option, dict)
else sub_option.type.value
),
)
if _option_context:
if isinstance(sub_option, dict):
_option_context[sub_option["value"]]._client = self._http
sub_option.update({"value": _option_context[sub_option["value"]]})
else:
_option_context[sub_option.value]._client = self._http
sub_option._json.update(
{"value": _option_context[sub_option.value]}
)
__kwargs[sub_option["name"]] = sub_option["value"]
else:
for group in _data["options"]:
for _group_option in group:
_check_auto(_group_option)
__kwargs[_group_option["name"]] = _group_option["value"]

elif _data.get("value") and _data.get("name"):
__kwargs[_data["name"]] = _data["value"]

Expand Down
2 changes: 1 addition & 1 deletion interactions/api/gateway.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class WebSocketClient:
async def wait_until_ready(self) -> None: ...
def _dispatch_event(self, event: str, data: dict) -> None: ...
def __contextualize(self, data: dict) -> object: ...
def __sub_command_context(self, data: Union[dict, Option]) -> Union[Tuple[str], dict]: ...
def __sub_command_context(self, data: Union[dict, Option], _context: Optional[object] = MISSING) -> Union[Tuple[str], dict]: ...
def __option_type_context(self, context: object, type: int) -> dict: ...
@property
async def __receive_packet_stream(self) -> Optional[Dict[str, Any]]: ...
Expand Down
13 changes: 11 additions & 2 deletions interactions/api/models/gw.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,16 @@ class MessageReaction(DictSerializerMixin):
:ivar Optional[Emoji] emoji?: The emoji of the event.
"""

__slots__ = ("_json", "user_id", "channel_id", "message_id", "guild_id", "member", "emoji")
__slots__ = (
"_json",
"_client",
"user_id",
"channel_id",
"message_id",
"guild_id",
"member",
"emoji",
)

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand All @@ -416,7 +425,7 @@ class ReactionRemove(MessageReaction):
:ivar Optional[Emoji] emoji?: The emoji of the event.
"""

__slots__ = ("_json", "user_id", "channel_id", "message_id", "guild_id", "emoji")
__slots__ = ("_json", "_client", "user_id", "channel_id", "message_id", "guild_id", "emoji")

def __init__(self, **kwargs):
super().__init__(**kwargs)
Expand Down

0 comments on commit acef57f

Please sign in to comment.