Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: component sending/editing with context #396

Merged
merged 22 commits into from
Jan 2, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
191 changes: 168 additions & 23 deletions interactions/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .base import CustomFormatter, Data
from .enums import InteractionCallbackType, InteractionType
from .models.command import Choice
from .models.component import ActionRow, Button, Component, Modal, SelectMenu
from .models.component import ActionRow, Button, Modal, SelectMenu
from .models.misc import InteractionData

basicConfig(level=Data.LOGGER)
Expand Down Expand Up @@ -156,7 +156,9 @@ async def send(
# attachments: Optional[List[Any]] = None, # TODO: post-v4: Replace with own file type.
embeds: Optional[Union[Embed, List[Embed]]] = None,
allowed_mentions: Optional[MessageInteraction] = None,
components: Optional[Union[Component, List[Component]]] = None,
components: Optional[
Union[Union[ActionRow, Button, SelectMenu], List[Union[ActionRow, Button, SelectMenu]]]
Toricane marked this conversation as resolved.
Show resolved Hide resolved
] = None,
ephemeral: Optional[bool] = False,
) -> Message:
"""
Expand All @@ -172,7 +174,7 @@ async def send(
:param allowed_mentions?: The message interactions/mention limits that the message can refer to.
:type allowed_mentions: Optional[MessageInteraction]
:param components?: A component, or list of components for the message.
:type components: Optional[Union[Component, List[Component]]]
:type components: Optional[Union[Union[ActionRow, Button, SelectMenu], List[Union[ActionRow, Button, SelectMenu]]]]
:param ephemeral?: Whether the response is hidden or not.
:type ephemeral: Optional[bool]
:return: The sent message as an object.
Expand All @@ -188,26 +190,97 @@ async def send(
else ([embed._json for embed in embeds] if isinstance(embeds, list) else [embeds._json])
)
_allowed_mentions: dict = {} if allowed_mentions is None else allowed_mentions
_components: list = [{"type": 1, "components": []}]
_components: List[dict] = [{"type": 1, "components": []}]

if (
isinstance(components, list)
and components
and (isinstance(action_row, ActionRow) for action_row in components)
and all(isinstance(action_row, ActionRow) for action_row in components)
):
_components = [
{"type": 1, "components": [component._json for component in action_row.components]}
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in action_row.components
],
}
for action_row in components
]
elif (
isinstance(components, list)
and components
and all(isinstance(component, (Button, SelectMenu)) for component in components)
):
if isinstance(components[0], SelectMenu):
components[0]._json["options"] = [option._json for option in components[0].options]
_components = [
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in components
],
}
]
elif (
isinstance(components, list)
and components
and all(isinstance(action_row, (list, ActionRow)) for action_row in components)
):
_components = []
for action_row in components:
for component in (
action_row if isinstance(action_row, list) else action_row.components
):
if isinstance(component, SelectMenu):
component._json["options"] = [option._json for option in component.options]
_components.append(
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in (
action_row
if isinstance(action_row, list)
else action_row.components
)
],
}
)
elif isinstance(components, ActionRow):
_components[0]["components"] = [component._json for component in components.components]
elif isinstance(components, Button):
_components[0]["components"] = [] if components is None else [components._json]
elif isinstance(components, SelectMenu):
components._json["options"] = [option._json for option in components.options]
_components[0]["components"] = [] if components is None else [components._json]
_components[0]["components"] = [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in components.components
]
elif isinstance(components, (Button, SelectMenu)):
if isinstance(components, SelectMenu):
components._json["options"] = [option._json for option in components.options]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

components._json["options"] should not need to be overwritten as of the latest unstable commit, since we have a recursive generator being applied.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed lines 257 and 258, and the respective lines in edit() as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah @goverfl0w, this is why I put it in the first place:

ERROR:asyncio:Task exception was never retrieved
future: <Task finished name='Task-16' coro=<my_command() done, defined at c:\Users\hi\Desktop\Coding\Python\discord-interactions v4\main.py:31> exception=TypeError('Object of type SelectOption is not JSON serializable')>
Traceback (most recent call last):
  File "c:\Users\hi\Desktop\Coding\Python\discord-interactions v4\main.py", line 143, in my_command
    await ctx.send("b", components=select)
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\interactions\context.py", line 343, in send
    await func()
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\interactions\context.py", line 336, in func
    await self.client.create_interaction_response(
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\interactions\api\http.py", line 2061, in create_interaction_response
    return await self._req.request(
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\interactions\api\http.py", line 200, in request
    async with self.session.request(
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\client.py", line 1117, in __aenter__
    self._resp = await self._coro
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\client.py", line 390, in _request
    data = payload.JsonPayload(json, dumps=self._json_serialize)
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\site-packages\aiohttp\payload.py", line 381, in __init__
    dumps(value).encode(encoding),
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "C:\Users\hi\AppData\Local\Programs\Python\Python39\lib\json\encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type SelectOption is not JSON serializable

I'm gonna revert the commit and keep the lines and try again

_components[0]["components"] = (
[components._json]
if components._json.get("custom_id") or components._json.get("url")
else []
)
elif components is None:
_components = None
else:
_components = [] if components is None else [components]
_components = []

_ephemeral: int = (1 << 6) if ephemeral else 0

Expand Down Expand Up @@ -281,7 +354,9 @@ async def edit(
embeds: Optional[Union[Embed, List[Embed]]] = None,
allowed_mentions: Optional[MessageInteraction] = None,
message_reference: Optional[MessageReference] = None,
components: Optional[Union[ActionRow, Button, SelectMenu]] = None,
components: Optional[
Union[Union[ActionRow, Button, SelectMenu], List[Union[ActionRow, Button, SelectMenu]]]
Toricane marked this conversation as resolved.
Show resolved Hide resolved
] = None,
) -> Message:
"""
This allows the invocation state described in the "context"
Expand All @@ -307,20 +382,90 @@ async def edit(
if (
isinstance(components, list)
and components
and (isinstance(action_row, ActionRow) for action_row in components)
and all(isinstance(action_row, ActionRow) for action_row in components)
):
_components = [
{"type": 1, "components": [component._json for component in action_row.components]}
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in action_row.components
],
}
for action_row in components
]
elif (
isinstance(components, list)
and components
and all(isinstance(component, (Button, SelectMenu)) for component in components)
):
if isinstance(components[0], SelectMenu):
components[0]._json["options"] = [option._json for option in components[0].options]
_components = [
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in components
],
}
]
elif (
isinstance(components, list)
and components
and all(isinstance(action_row, (list, ActionRow)) for action_row in components)
):
_components = []
for action_row in components:
for component in (
action_row if isinstance(action_row, list) else action_row.components
):
if isinstance(component, SelectMenu):
component._json["options"] = [option._json for option in component.options]
_components.append(
{
"type": 1,
"components": [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in (
action_row
if isinstance(action_row, list)
else action_row.components
)
],
}
)
elif isinstance(components, ActionRow):
_components[0]["components"] = [component._json for component in components.components]
elif isinstance(components, Button):
_components[0]["components"] = [] if components is None else [components._json]
elif isinstance(components, SelectMenu):
components._json["options"] = [option._json for option in components.options]
_components[0]["components"] = [] if components is None else [components._json]

_components[0]["components"] = [
(
component._json
if component._json.get("custom_id") or component._json.get("url")
else []
)
for component in components.components
]
elif isinstance(components, (Button, SelectMenu)):
if isinstance(components, SelectMenu):
components._json["options"] = [option._json for option in components.options]
_components[0]["components"] = (
[components._json]
if components._json.get("custom_id") or components._json.get("url")
else []
)
elif components is None:
_components = None
else:
_components = []

Expand Down
8 changes: 6 additions & 2 deletions interactions/context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ class CommandContext(Context):
# attachments: Optional[List[Any]] = None, # TODO: post-v4: Replace with own file type.
embeds: Optional[Union[Embed, List[Embed]]] = None,
allowed_mentions: Optional[MessageInteraction] = None,
components: Optional[Union[Component, List[Component]]] = None,
components: Optional[
Union[Union[ActionRow, Button, SelectMenu], List[Union[ActionRow, Button, SelectMenu]]]
] = None,
ephemeral: Optional[bool] = False,
) -> Message: ...
async def edit(
Expand All @@ -58,7 +60,9 @@ class CommandContext(Context):
# attachments: Optional[List[Any]] = None, # TODO: post-v4: Replace with own file type.
embeds: Optional[Union[Embed, List[Embed]]] = None,
allowed_mentions: Optional[MessageInteraction] = None,
components: Optional[Union[Component, List[Component]]] = None,
components: Optional[
Union[Union[ActionRow, Button, SelectMenu], List[Union[ActionRow, Button, SelectMenu]]]
] = None,
) -> Message: ...
async def delete(self) -> None: ...
async def popup(self, modal: Modal): ...
Expand Down