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

refactor: Improve webhook typing. #1193

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/626.misc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Improve type annotations for :attr:`Interaction.followup`\'s ``.send`` method.
8 changes: 5 additions & 3 deletions disnake/interactions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
overload,
)

from disnake.webhook.interaction import InteractionFollowupWebhook

from .. import utils
from ..app_commands import OptionChoice
from ..channel import PartialMessageable, _threaded_guild_channel_factory
Expand Down Expand Up @@ -52,7 +54,7 @@
from ..role import Role
from ..ui.action_row import components_to_dict
from ..user import ClientUser, User
from ..webhook.async_ import Webhook, async_context, handle_message_parameters
from ..webhook.async_ import async_context, handle_message_parameters

__all__ = (
"Interaction",
Expand Down Expand Up @@ -310,14 +312,14 @@ def response(self) -> InteractionResponse:
return InteractionResponse(self)

@utils.cached_slot_property("_cs_followup")
def followup(self) -> Webhook:
def followup(self) -> InteractionFollowupWebhook:
""":class:`Webhook`: Returns the follow up webhook for follow up interactions."""
payload = {
"id": self.application_id,
"type": WebhookType.application.value,
"token": self.token,
}
return Webhook.from_state(data=payload, state=self._state)
return InteractionFollowupWebhook.from_state(data=payload, state=self._state)

@utils.cached_slot_property("_cs_expires_at")
def expires_at(self) -> datetime:
Expand Down
5 changes: 4 additions & 1 deletion disnake/webhook/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
:license: MIT, see LICENSE for more details.

"""
from . import async_, sync

from . import async_, interaction, sync
from .async_ import *
from .interaction import *
from .sync import *

__all__ = []
__all__.extend(async_.__all__)
__all__.extend(interaction.__all__)
__all__.extend(sync.__all__)
4 changes: 3 additions & 1 deletion disnake/webhook/async_.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
import datetime
from types import TracebackType

from typing_extensions import Self

from ..abc import Snowflake
from ..asset import AssetBytes
from ..channel import ForumChannel, MediaChannel, StageChannel, TextChannel, VoiceChannel
Expand Down Expand Up @@ -1255,7 +1257,7 @@ def _as_follower(cls, data, *, channel, user) -> Webhook:
return cls(feed, session=session, state=state, token=state.http.token)

@classmethod
def from_state(cls, data, state) -> Webhook:
def from_state(cls, data, state) -> Self:
session = state.http._HTTPClient__session
return cls(data, session=session, state=state, token=state.http.token)

Expand Down
82 changes: 82 additions & 0 deletions disnake/webhook/interaction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# SPDX-License-Identifier: MIT

from __future__ import annotations

from collections.abc import Sequence
from typing import TYPE_CHECKING

from ..utils import MISSING
from .async_ import Webhook

if TYPE_CHECKING:
from typing import List, Optional

from ..abc import Snowflake
from ..embeds import Embed
from ..file import File
from ..flags import MessageFlags
from ..mentions import AllowedMentions
from ..ui.action_row import Components, MessageUIComponent
from ..ui.view import View
from ..webhook.async_ import WebhookMessage

__all__ = ("InteractionFollowupWebhook",)


class InteractionFollowupWebhook(Webhook):
"""A 1:1 copy of :class:`Webhook` meant for :attr:`Interaction.followup`\\'s annotations."""

if TYPE_CHECKING:

async def send(
self,
content: Optional[str] = MISSING,
*,
tts: bool = MISSING,
ephemeral: bool = MISSING,
suppress_embeds: bool = MISSING,
flags: MessageFlags = MISSING,
file: File = MISSING,
files: List[File] = MISSING,
embed: Embed = MISSING,
embeds: List[Embed] = MISSING,
allowed_mentions: AllowedMentions = MISSING,
view: View = MISSING,
components: Components[MessageUIComponent] = MISSING,
thread: Snowflake = MISSING,
thread_name: str = MISSING,
applied_tags: Sequence[Snowflake] = MISSING,
delete_after: float = MISSING,
) -> WebhookMessage:
"""|coro|

Sends a message using the webhook.

This is the same as :meth:`Webhook.send` but with type hints changed. Namely,
this method always returns a :class:`WebhookMessage` because ``wait=True`` for
interaction webhooks, and ``username`` and ``avatar_url`` are not supported.

Returns
-------
:class:`WebhookMessage`
The message that was sent.
"""
return await super().send(
content=content,
tts=tts,
ephemeral=ephemeral,
embeds=embeds,
embed=embed,
file=file,
files=files,
view=view,
components=components,
allowed_mentions=allowed_mentions,
thread=thread,
thread_name=thread_name,
applied_tags=applied_tags,
delete_after=delete_after,
suppress_embeds=suppress_embeds,
flags=flags,
wait=True,
)
Loading