Skip to content

Commit

Permalink
chore: refactor send/edit message
Browse files Browse the repository at this point in the history
  • Loading branch information
hawk-tomy committed May 18, 2024
1 parent 8ef0c90 commit ba7281f
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 67 deletions.
32 changes: 5 additions & 27 deletions discord/ext/flow/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@

from typing import TYPE_CHECKING

from discord import Interaction
from discord.utils import maybe_coroutine

from .util import into_edit_kwargs, send_helper
from .util import send_helper
from .view import _View

if TYPE_CHECKING:
from typing import Self

from discord import Client
from discord import Client, Interaction
from discord.abc import Messageable

from .model import Message, ModelBase
from .model import ModelBase
from .util import _Editable

__all__ = ('Controller',)
Expand Down Expand Up @@ -65,12 +64,12 @@ async def _send(
msg = await maybe_coroutine(model.message)

if msg.items is None:
await self._send_helper(messageable, msg, None, edit_target)
await send_helper(messageable, msg, None, edit_target)
await maybe_coroutine(model.after_invoke)
return None

view = _View(await maybe_coroutine(model.view_config), msg.items)
message = await self._send_helper(messageable, msg, view, edit_target)
message = await send_helper(messageable, msg, view, edit_target)

await view.wait()
if msg.disable_items:
Expand All @@ -81,24 +80,3 @@ async def _send(
await maybe_coroutine(model.after_invoke)

return None if view.result is None else (*view.result, message)

async def _send_helper(
self,
messageable: Messageable | Interaction[Client],
message: Message,
view: _View | None,
edit_target: _Editable | None,
) -> _Editable:
kwargs = message._to_dict()
if view is not None:
kwargs['view'] = view

if message.edit_original:
if isinstance(messageable, Interaction) and not messageable.response.is_done():
if messageable.message is not None: # Interaction.message is not None -> can edit
await messageable.response.edit_message(**into_edit_kwargs(**kwargs))
return await messageable.original_response() # type: ignore[reportReturnType, return-value]
elif edit_target is not None:
return await edit_target.edit(**into_edit_kwargs(**kwargs))
# fallback to send message
return await send_helper(messageable, **kwargs)
92 changes: 66 additions & 26 deletions discord/ext/flow/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@

if TYPE_CHECKING:
from collections.abc import Sequence
from typing import Self, TypeVar, Unpack
from typing import Self, TypeVar

from discord import AllowedMentions, Attachment, Client, Embed, File
from discord.abc import Messageable
from discord.ui import View

from .model import MessageKwargs
from .model import Message as MessageData, MessageKwargs
from .view import _View

T = TypeVar('T')
U = TypeVar('U')
Expand Down Expand Up @@ -50,29 +51,26 @@ class _SendHelperKWType(TypedDict, total=False):
silent: bool


async def send_helper(
messageable: Messageable | Interaction[Client],
*,
delete_after: float | None = None,
ephemeral: bool = False,
**kwargs: Unpack[_SendHelperKWType],
) -> _Editable:
"""Helper function to send message. use messageable or interaction."""
msg: Message
if isinstance(messageable, Interaction):
if messageable.response.is_done():
msg = await messageable.followup.send(wait=True, ephemeral=ephemeral, **kwargs)
else:
await messageable.response.send_message(ephemeral=ephemeral, **kwargs)
msg = await messageable.original_response()

if delete_after is not None:
await msg.delete(delay=delete_after)
else:
# type-ignore: can pass None to delete_after
msg = await messageable.send(delete_after=delete_after, **kwargs) # type: ignore[reportArgumentType, arg-type]
# type-ignore: return type is Message, InteractionMessage or WebhookMessage, which are also _Editable
return msg # type: ignore[reportReturnType, return-value]
def into_send_kwargs(kwargs: MessageKwargs) -> _SendHelperKWType:
"""Convert MessageKwargs to send kwargs type."""
kw: _SendHelperKWType = {}
if 'content' in kwargs:
kw['content'] = kwargs['content']
if 'tts' in kwargs:
kw['tts'] = kwargs['tts']
if 'embeds' in kwargs:
kw['embeds'] = kwargs['embeds']
if 'files' in kwargs:
kw['files'] = kwargs['files']
if 'allowed_mentions' in kwargs:
kw['allowed_mentions'] = kwargs['allowed_mentions']
if 'view' in kwargs:
kw['view'] = kwargs['view']
if 'suppress_embeds' in kwargs:
kw['suppress_embeds'] = kwargs['suppress_embeds']
if 'silent' in kwargs:
kw['silent'] = kwargs['silent']
return kw


class _EditKWType(TypedDict, total=False):
Expand All @@ -83,7 +81,7 @@ class _EditKWType(TypedDict, total=False):
view: View


def into_edit_kwargs(**kwargs: Unpack[MessageKwargs]) -> _EditKWType:
def into_edit_kwargs(kwargs: MessageKwargs) -> _EditKWType:
"""Convert MessageKwargs to Message.edit kwargs type."""
kw: _EditKWType = {}
if 'content' in kwargs:
Expand All @@ -97,3 +95,45 @@ def into_edit_kwargs(**kwargs: Unpack[MessageKwargs]) -> _EditKWType:
if 'view' in kwargs:
kw['view'] = kwargs['view']
return kw


async def send_helper(
messageable: Messageable | Interaction[Client],
message: MessageData,
view: _View | None,
edit_target: _Editable | None,
) -> _Editable:
"""Helper function to send message. use messageable or interaction."""
kwargs = message._to_dict()
if view is not None:
kwargs['view'] = view

# if edit
if message.edit_original:
if isinstance(messageable, Interaction) and not messageable.response.is_done():
if messageable.message is not None: # Interaction.message is not None -> can edit
await messageable.response.edit_message(**into_edit_kwargs(kwargs))
return await messageable.original_response() # type: ignore[reportReturnType, return-value]
elif edit_target is not None:
return await edit_target.edit(**into_edit_kwargs(kwargs))
# fallback to send message

# if send
msg: Message
delete_after = kwargs.get('delete_after', None)
ephemeral = kwargs.get('ephemeral', False)
kwargs = into_send_kwargs(kwargs)
if isinstance(messageable, Interaction):
if messageable.response.is_done():
msg = await messageable.followup.send(wait=True, ephemeral=ephemeral, **kwargs)
else:
await messageable.response.send_message(ephemeral=ephemeral, **kwargs)
msg = await messageable.original_response()

if delete_after is not None:
await msg.delete(delay=delete_after)
else:
# type-ignore: can pass None to delete_after
msg = await messageable.send(delete_after=delete_after, **kwargs) # type: ignore[reportArgumentType, arg-type]
# type-ignore: return type is Message, InteractionMessage or WebhookMessage, which are also _Editable
return msg # type: ignore[reportReturnType, return-value]
16 changes: 2 additions & 14 deletions discord/ext/flow/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from .model import Button, ChannelSelect, Link, MentionableSelect, RoleSelect, Select, UserSelect
from .result import _ResultTypeEnum
from .util import unwrap_or
from .util import send_helper, unwrap_or

if TYPE_CHECKING:
from collections.abc import Sequence
Expand Down Expand Up @@ -174,19 +174,7 @@ async def set_result(self, result: Result, interaction: Interaction[Client]) ->
msg = result._message
self.clear_items()
self.set_items(msg.items or ())
if msg.edit_original:
await interaction.response.edit_message(
content=msg.content,
embeds=msg.embeds or (),
attachments=msg.files or (),
view=self,
allowed_mentions=msg.allowed_mentions,
delete_after=msg.delete_after,
)
else:
kwargs = msg._to_dict()
kwargs['view'] = self
await interaction.response.send_message(**kwargs)
await send_helper(interaction, msg, self, None)
if not msg.items:
self.stop()
case _ResultTypeEnum.MODEL:
Expand Down

0 comments on commit ba7281f

Please sign in to comment.