From 61cc544abdc0463c3e3fe866b12bda6a2064333c Mon Sep 17 00:00:00 2001 From: YoggieS <61660055+yoggys@users.noreply.github.com> Date: Wed, 5 Jun 2024 22:49:43 +0200 Subject: [PATCH] fix: overall type-hinting improvements (#2457) * fix: RawMemberRemoveEvent type-hinting * Update CHANGELOG.md Signed-off-by: YoggieS <61660055+yoggys@users.noreply.github.com> * style(pre-commit): auto fixes from pre-commit.com hooks * Update CHANGELOG.md Co-authored-by: plun1331 Signed-off-by: YoggieS <61660055+yoggys@users.noreply.github.com> * fix: overall type-hinting * style(pre-commit): auto fixes from pre-commit.com hooks * fix: further types lookup & fixes * style(pre-commit): auto fixes from pre-commit.com hooks * Update discord/guild.py Co-authored-by: UK <41271523+NeloBlivion@users.noreply.github.com> Signed-off-by: YoggieS <61660055+yoggys@users.noreply.github.com> * review suggestions * review suggestions v2 * style(pre-commit): auto fixes from pre-commit.com hooks * review suggestions v3 * update changelog with correct # * nonce typing partial revert * onboarding PromptOption types * Update CHANGELOG.md Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com> Signed-off-by: YoggieS <61660055+yoggys@users.noreply.github.com> --------- Signed-off-by: YoggieS <61660055+yoggys@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: plun1331 Co-authored-by: UK <41271523+NeloBlivion@users.noreply.github.com> Co-authored-by: Dorukyum <53639936+Dorukyum@users.noreply.github.com> --- CHANGELOG.md | 2 ++ discord/abc.py | 12 ++++++------ discord/audit_logs.py | 10 +++++----- discord/channel.py | 2 +- discord/commands/context.py | 4 ++-- discord/commands/core.py | 6 +++--- discord/context_managers.py | 2 +- discord/ext/commands/converter.py | 4 ++-- discord/ext/commands/help.py | 8 +++++++- discord/guild.py | 10 +++++----- discord/http.py | 12 ++++++------ discord/interactions.py | 2 +- discord/invite.py | 3 ++- discord/member.py | 12 ++++++++++-- discord/message.py | 4 ++-- discord/partial_emoji.py | 4 +++- discord/raw_models.py | 2 +- discord/reaction.py | 2 +- discord/sinks/core.py | 4 +++- discord/state.py | 20 ++++++++------------ discord/types/channel.py | 4 ++-- discord/types/message.py | 4 ++++ discord/types/onboarding.py | 2 +- discord/types/webhook.py | 14 +++++++------- discord/user.py | 5 ++++- discord/voice_client.py | 4 ++-- discord/webhook/async_.py | 13 +++++++------ 27 files changed, 98 insertions(+), 73 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9300e62a2f..ea7687928c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,8 @@ These changes are available on the `master` branch, but have not yet been releas ([#2448](https://github.com/Pycord-Development/pycord/pull/2448)) - Fixed missing `application_id` in `Entitlement.delete`. ([#2458](https://github.com/Pycord-Development/pycord/pull/2458)) +- Fixed many inaccurate type hints throughout the library. + ([#2457](https://github.com/Pycord-Development/pycord/pull/2457)) ### Changed diff --git a/discord/abc.py b/discord/abc.py index dc2237151d..270103b700 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -115,7 +115,7 @@ async def _single_delete_strategy( async def _purge_messages_helper( - channel: TextChannel | Thread | VoiceChannel, + channel: TextChannel | StageChannel | Thread | VoiceChannel, *, limit: int | None = 100, check: Callable[[Message], bool] = MISSING, @@ -1345,7 +1345,7 @@ async def send( file: File = ..., stickers: Sequence[GuildSticker | StickerItem] = ..., delete_after: float = ..., - nonce: str | int = ..., + nonce: int | str = ..., enforce_nonce: bool = ..., allowed_mentions: AllowedMentions = ..., reference: Message | MessageReference | PartialMessage = ..., @@ -1365,7 +1365,7 @@ async def send( files: list[File] = ..., stickers: Sequence[GuildSticker | StickerItem] = ..., delete_after: float = ..., - nonce: str | int = ..., + nonce: int | str = ..., enforce_nonce: bool = ..., allowed_mentions: AllowedMentions = ..., reference: Message | MessageReference | PartialMessage = ..., @@ -1385,7 +1385,7 @@ async def send( file: File = ..., stickers: Sequence[GuildSticker | StickerItem] = ..., delete_after: float = ..., - nonce: str | int = ..., + nonce: int | str = ..., enforce_nonce: bool = ..., allowed_mentions: AllowedMentions = ..., reference: Message | MessageReference | PartialMessage = ..., @@ -1405,7 +1405,7 @@ async def send( files: list[File] = ..., stickers: Sequence[GuildSticker | StickerItem] = ..., delete_after: float = ..., - nonce: str | int = ..., + nonce: int | str = ..., enforce_nonce: bool = ..., allowed_mentions: AllowedMentions = ..., reference: Message | MessageReference | PartialMessage = ..., @@ -1465,7 +1465,7 @@ async def send( The file to upload. files: List[:class:`~discord.File`] A list of files to upload. Must be a maximum of 10. - nonce: :class:`int` + nonce: Union[:class:`str`, :class:`int`] The nonce to use for sending this message. If the message was successfully sent, then the message will have a nonce with this value. enforce_nonce: Optional[:class:`bool`] diff --git a/discord/audit_logs.py b/discord/audit_logs.py index 297635038b..4bac078c4f 100644 --- a/discord/audit_logs.py +++ b/discord/audit_logs.py @@ -193,7 +193,7 @@ def _transform_type( def _transform_actions( entry: AuditLogEntry, data: list[AutoModActionPayload] | None -) -> AutoModAction | None: +) -> list[AutoModAction] | None: if data is None: return None else: @@ -201,8 +201,8 @@ def _transform_actions( def _transform_trigger_metadata( - entry: AuditLogEntry, data: list[AutoModActionPayload] | None -) -> AutoModAction | None: + entry: AuditLogEntry, data: AutoModTriggerMetadataPayload | None +) -> AutoModTriggerMetadata | None: if data is None: return None else: @@ -309,7 +309,7 @@ def __init__( "$add_allow_list", ]: self._handle_trigger_metadata( - self.before, self.after, entry, elem["new_value"], attr + self.before, self.after, entry, elem["new_value"], attr # type: ignore ) continue elif attr in [ @@ -318,7 +318,7 @@ def __init__( "$remove_allow_list", ]: self._handle_trigger_metadata( - self.after, self.before, entry, elem["new_value"], attr + self.after, self.before, entry, elem["new_value"], attr # type: ignore ) continue diff --git a/discord/channel.py b/discord/channel.py index 2586e3eed7..77c733194f 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -1218,7 +1218,7 @@ async def create_thread( A list of stickers to upload. Must be a maximum of 3. delete_message_after: :class:`int` The time to wait before deleting the thread. - nonce: :class:`int` + nonce: Union[:class:`str`, :class:`int`] The nonce to use for sending this message. If the message was successfully sent, then the message will have a nonce with this value. allowed_mentions: :class:`~discord.AllowedMentions` diff --git a/discord/commands/context.py b/discord/commands/context.py index dda6efa539..27c3b0acba 100644 --- a/discord/commands/context.py +++ b/discord/commands/context.py @@ -37,7 +37,7 @@ import discord from .. import Bot from ..state import ConnectionState - from ..voice_client import VoiceProtocol + from ..voice_client import VoiceClient from .core import ApplicationCommand, Option from ..interactions import InteractionChannel @@ -211,7 +211,7 @@ def user(self) -> Member | User: author: Member | User = user @property - def voice_client(self) -> VoiceProtocol | None: + def voice_client(self) -> VoiceClient | None: """Returns the voice client associated with this context's command. Shorthand for :attr:`Interaction.guild.voice_client<~discord.Guild.voice_client>`, if applicable. """ diff --git a/discord/commands/core.py b/discord/commands/core.py index 6f34c0c9d9..26469472e8 100644 --- a/discord/commands/core.py +++ b/discord/commands/core.py @@ -328,7 +328,7 @@ def is_on_cooldown(self, ctx: ApplicationContext) -> bool: if not self._buckets.valid: return False - bucket = self._buckets.get_bucket(ctx) + bucket = self._buckets.get_bucket(ctx) # type: ignore current = utcnow().timestamp() return bucket.get_tokens(current) == 0 @@ -363,7 +363,7 @@ def get_cooldown_retry_after(self, ctx: ApplicationContext) -> float: If this is ``0.0`` then the command isn't on cooldown. """ if self._buckets.valid: - bucket = self._buckets.get_bucket(ctx) + bucket = self._buckets.get_bucket(ctx) # type: ignore current = utcnow().timestamp() return bucket.get_retry_after(current) @@ -1245,7 +1245,7 @@ def to_dict(self) -> dict: return as_dict - def add_command(self, command: SlashCommand) -> None: + def add_command(self, command: SlashCommand | SlashCommandGroup) -> None: if command.cog is None and self.cog is not None: command.cog = self.cog diff --git a/discord/context_managers.py b/discord/context_managers.py index c9d930b5e4..9f1a282b3f 100644 --- a/discord/context_managers.py +++ b/discord/context_managers.py @@ -38,7 +38,7 @@ __all__ = ("Typing",) -def _typing_done_callback(fut: asyncio.Future) -> None: +def _typing_done_callback(fut: asyncio.Task) -> None: # just retrieve any exception and call it a day try: fut.exception() diff --git a/discord/ext/commands/converter.py b/discord/ext/commands/converter.py index 7a4bbabf46..3ed53fa1d0 100644 --- a/discord/ext/commands/converter.py +++ b/discord/ext/commands/converter.py @@ -1166,7 +1166,7 @@ async def _actual_conversion( async def run_converters( - ctx: Context, converter, argument: str, param: inspect.Parameter + ctx: Context, converter, argument: str | None, param: inspect.Parameter ): """|coro| @@ -1182,7 +1182,7 @@ async def run_converters( The invocation context to run the converters under. converter: Any The converter to run, this corresponds to the annotation in the function. - argument: :class:`str` + argument: Optional[:class:`str`] The argument to convert to. param: :class:`inspect.Parameter` The parameter being converted. This is mainly for error reporting. diff --git a/discord/ext/commands/help.py b/discord/ext/commands/help.py index 90899ef6a8..25b44388bd 100644 --- a/discord/ext/commands/help.py +++ b/discord/ext/commands/help.py @@ -90,7 +90,13 @@ class Paginator: .. versionadded:: 1.7 """ - def __init__(self, prefix="```", suffix="```", max_size=2000, linesep="\n"): + def __init__( + self, + prefix: str | None = "```", + suffix: str | None = "```", + max_size: int = 2000, + linesep: str = "\n", + ): self.prefix = prefix self.suffix = suffix self.max_size = max_size diff --git a/discord/guild.py b/discord/guild.py index 83758b0ad9..15bf1394a3 100644 --- a/discord/guild.py +++ b/discord/guild.py @@ -107,7 +107,7 @@ from .types.member import Member as MemberPayload from .types.threads import Thread as ThreadPayload from .types.voice import GuildVoiceState - from .voice_client import VoiceProtocol + from .voice_client import VoiceClient from .webhook import Webhook VocalGuildChannel = Union[VoiceChannel, StageChannel] @@ -647,8 +647,8 @@ def me(self) -> Member: return self.get_member(self_id) # type: ignore @property - def voice_client(self) -> VoiceProtocol | None: - """Returns the :class:`VoiceProtocol` associated with this guild, if any.""" + def voice_client(self) -> VoiceClient | None: + """Returns the :class:`VoiceClient` associated with this guild, if any.""" return self._state._get_voice_client(self.id) @property @@ -3121,7 +3121,7 @@ async def bulk_ban( *users: Snowflake, delete_message_seconds: int | None = None, reason: str | None = None, - ) -> list[list[Snowflake], list[Snowflake]]: + ) -> tuple[list[Snowflake], list[Snowflake]]: r"""|coro| Bulk ban users from the guild. @@ -3152,7 +3152,7 @@ async def bulk_ban( Returns ------- - List[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]] + Tuple[List[:class:`abc.Snowflake`], List[:class:`abc.Snowflake`]] Returns two lists: the first contains members that were successfully banned, while the second is members that could not be banned. Raises diff --git a/discord/http.py b/discord/http.py index 3622afc2bd..1132ca3338 100644 --- a/discord/http.py +++ b/discord/http.py @@ -464,7 +464,7 @@ def send_message( tts: bool = False, embed: embed.Embed | None = None, embeds: list[embed.Embed] | None = None, - nonce: str | None = None, + nonce: int | str | None = None, enforce_nonce: bool | None = None, allowed_mentions: message.AllowedMentions | None = None, message_reference: message.MessageReference | None = None, @@ -524,7 +524,7 @@ def send_multipart_helper( tts: bool = False, embed: embed.Embed | None = None, embeds: Iterable[embed.Embed | None] | None = None, - nonce: str | None = None, + nonce: int | str | None = None, enforce_nonce: bool | None = None, allowed_mentions: message.AllowedMentions | None = None, message_reference: message.MessageReference | None = None, @@ -587,7 +587,7 @@ def send_files( tts: bool = False, embed: embed.Embed | None = None, embeds: list[embed.Embed] | None = None, - nonce: str | None = None, + nonce: int | str | None = None, enforce_nonce: bool | None = None, allowed_mentions: message.AllowedMentions | None = None, message_reference: message.MessageReference | None = None, @@ -1203,7 +1203,7 @@ def start_forum_thread( files: Sequence[File] | None = None, embed: embed.Embed | None = None, embeds: list[embed.Embed] | None = None, - nonce: str | None = None, + nonce: int | str | None = None, allowed_mentions: message.AllowedMentions | None = None, stickers: list[sticker.StickerItem] | None = None, components: list[components.Component] | None = None, @@ -2151,8 +2151,8 @@ def edit_channel_permissions( self, channel_id: Snowflake, target: Snowflake, - allow: str, - deny: str, + allow: int | str, + deny: int | str, type: channel.OverwriteType, *, reason: str | None = None, diff --git a/discord/interactions.py b/discord/interactions.py index 1362acfac4..51574ce0b3 100644 --- a/discord/interactions.py +++ b/discord/interactions.py @@ -1221,7 +1221,7 @@ async def premium_required(self) -> Interaction: self._responded = True return self._parent - async def _locked_response(self, coro: Coroutine[Any]): + async def _locked_response(self, coro: Coroutine[Any, Any, Any]) -> None: """|coro| Wraps a response and makes sure that it's locked while executing. diff --git a/discord/invite.py b/discord/invite.py index 2560bf9996..12d1d0f28a 100644 --- a/discord/invite.py +++ b/discord/invite.py @@ -49,6 +49,7 @@ from .types.invite import GatewayInvite as GatewayInvitePayload from .types.invite import Invite as InvitePayload from .types.invite import InviteGuild as InviteGuildPayload + from .types.invite import VanityInvite as VanityInvitePayload from .types.scheduled_events import ScheduledEvent as ScheduledEventPayload from .user import User @@ -353,7 +354,7 @@ def __init__( self, *, state: ConnectionState, - data: InvitePayload, + data: InvitePayload | VanityInvitePayload, guild: PartialInviteGuild | Guild | None = None, channel: PartialInviteChannel | GuildChannel | None = None, ): diff --git a/discord/member.py b/discord/member.py index c854e12979..57c04b2936 100644 --- a/discord/member.py +++ b/discord/member.py @@ -62,6 +62,7 @@ from .types.member import MemberWithUser as MemberWithUserPayload from .types.member import UserWithMember as UserWithMemberPayload from .types.user import User as UserPayload + from .types.voice import GuildVoiceState as GuildVoiceStatePayload from .types.voice import VoiceState as VoiceStatePayload VocalGuildChannel = Union[VoiceChannel, StageChannel] @@ -125,12 +126,19 @@ class VoiceState: ) def __init__( - self, *, data: VoiceStatePayload, channel: VocalGuildChannel | None = None + self, + *, + data: VoiceStatePayload | GuildVoiceStatePayload, + channel: VocalGuildChannel | None = None, ): self.session_id: str = data.get("session_id") self._update(data, channel) - def _update(self, data: VoiceStatePayload, channel: VocalGuildChannel | None): + def _update( + self, + data: VoiceStatePayload | GuildVoiceStatePayload, + channel: VocalGuildChannel | None, + ): self.self_mute: bool = data.get("self_mute", False) self.self_deaf: bool = data.get("self_deaf", False) self.self_stream: bool = data.get("self_stream", False) diff --git a/discord/message.py b/discord/message.py index 701bcc5ee5..23307434e8 100644 --- a/discord/message.py +++ b/discord/message.py @@ -240,14 +240,14 @@ def __init__(self, *, data: AttachmentPayload, state: ConnectionState): setattr(self, attr, value) @property - def expires_at(self) -> datetime.datetime: + def expires_at(self) -> datetime.datetime | None: """This attachment URL's expiry time in UTC.""" if not self._ex: return None return datetime.datetime.utcfromtimestamp(int(self._ex, 16)) @property - def issued_at(self) -> datetime.datetime: + def issued_at(self) -> datetime.datetime | None: """The attachment URL's issue time in UTC.""" if not self._is: return None diff --git a/discord/partial_emoji.py b/discord/partial_emoji.py index 171d6390c5..89009cc741 100644 --- a/discord/partial_emoji.py +++ b/discord/partial_emoji.py @@ -100,7 +100,9 @@ class PartialEmoji(_EmojiTag, AssetMixin): if TYPE_CHECKING: id: int | None - def __init__(self, *, name: str, animated: bool = False, id: int | None = None): + def __init__( + self, *, name: str | None, animated: bool = False, id: int | None = None + ): self.animated = animated self.name = name self.id = id diff --git a/discord/raw_models.py b/discord/raw_models.py index e3d38e558d..94226ff459 100644 --- a/discord/raw_models.py +++ b/discord/raw_models.py @@ -30,7 +30,6 @@ from .automod import AutoModAction, AutoModTriggerType from .enums import AuditLogAction, ChannelType, ReactionType, try_enum -from .types.user import User if TYPE_CHECKING: from .abc import MessageableChannel @@ -58,6 +57,7 @@ TypingEvent, VoiceChannelStatusUpdateEvent, ) + from .user import User __all__ = ( diff --git a/discord/reaction.py b/discord/reaction.py index 426b5474ef..2726e8984f 100644 --- a/discord/reaction.py +++ b/discord/reaction.py @@ -111,7 +111,7 @@ def __init__( self.me: bool = data.get("me") self.burst: bool = data.get("burst") self.me_burst: bool = data.get("me_burst") - self._burst_colours: list[Colour] = data.get("burst_colors", []) + self._burst_colours: list[str] = data.get("burst_colors", []) @property def burst_colours(self) -> list[Colour]: diff --git a/discord/sinks/core.py b/discord/sinks/core.py index 20d6d3a9ac..c8ea31a82a 100644 --- a/discord/sinks/core.py +++ b/discord/sinks/core.py @@ -23,6 +23,8 @@ DEALINGS IN THE SOFTWARE. """ +from __future__ import annotations + import io import os import struct @@ -202,7 +204,7 @@ def __init__(self, *, filters=None): filters = default_filters self.filters = filters Filters.__init__(self, **self.filters) - self.vc: VoiceClient = None + self.vc: VoiceClient | None = None self.audio_data = {} def init(self, vc): # called under listen diff --git a/discord/state.py b/discord/state.py index 0f9a6dc438..c3ae777f5f 100644 --- a/discord/state.py +++ b/discord/state.py @@ -43,8 +43,6 @@ Union, ) -import discord - from . import utils from .activity import BaseActivity from .audit_logs import AuditLogEntry @@ -88,7 +86,7 @@ from .types.message import Message as MessagePayload from .types.sticker import GuildSticker as GuildStickerPayload from .types.user import User as UserPayload - from .voice_client import VoiceProtocol + from .voice_client import VoiceClient T = TypeVar("T") CS = TypeVar("CS", bound="ConnectionState") @@ -146,9 +144,7 @@ def done(self) -> None: _log = logging.getLogger(__name__) -async def logging_coroutine( - coroutine: Coroutine[Any, Any, T], *, info: str -) -> T | None: +async def logging_coroutine(coroutine: Coroutine[Any, Any, T], *, info: str) -> None: try: await coroutine except Exception: @@ -281,7 +277,7 @@ def clear(self, *, views: bool = True) -> None: if views: self._view_store: ViewStore = ViewStore(self) self._modal_store: ModalStore = ModalStore(self) - self._voice_clients: dict[int, VoiceProtocol] = {} + self._voice_clients: dict[int, VoiceClient] = {} # LRU of max size 128 self._private_channels: OrderedDict[int, PrivateChannel] = OrderedDict() @@ -334,14 +330,14 @@ def intents(self) -> Intents: return ret @property - def voice_clients(self) -> list[VoiceProtocol]: + def voice_clients(self) -> list[VoiceClient]: return list(self._voice_clients.values()) - def _get_voice_client(self, guild_id: int | None) -> VoiceProtocol | None: + def _get_voice_client(self, guild_id: int | None) -> VoiceClient | None: # the keys of self._voice_clients are ints return self._voice_clients.get(guild_id) # type: ignore - def _add_voice_client(self, guild_id: int, voice: VoiceProtocol) -> None: + def _add_voice_client(self, guild_id: int, voice: VoiceClient) -> None: self._voice_clients[guild_id] = voice def _remove_voice_client(self, guild_id: int) -> None: @@ -531,9 +527,9 @@ async def chunker( async def query_members( self, guild: Guild, - query: str, + query: str | None, limit: int, - user_ids: list[int], + user_ids: list[int] | None, cache: bool, presences: bool, ): diff --git a/discord/types/channel.py b/discord/types/channel.py index 0f4c044aed..1b7fb1fe5e 100644 --- a/discord/types/channel.py +++ b/discord/types/channel.py @@ -32,7 +32,7 @@ from ..flags import ChannelFlags from .snowflake import Snowflake from .threads import ThreadArchiveDuration, ThreadMember, ThreadMetadata -from .user import PartialUser +from .user import User OverwriteType = Literal[0, 1] @@ -159,7 +159,7 @@ class DMChannel(TypedDict): id: Snowflake type: Literal[1] last_message_id: Snowflake | None - recipients: list[PartialUser] + recipients: list[User] class GroupDMChannel(_BaseChannel): diff --git a/discord/types/message.py b/discord/types/message.py index 10d819ebd4..ee453f9694 100644 --- a/discord/types/message.py +++ b/discord/types/message.py @@ -55,6 +55,9 @@ class Reaction(TypedDict): me: bool emoji: PartialEmoji burst: bool + me_burst: bool + burst_colors: list[str] + count_details: ReactionCountDetails class ReactionCountDetails(TypedDict): @@ -66,6 +69,7 @@ class Attachment(TypedDict): height: NotRequired[int | None] width: NotRequired[int | None] content_type: NotRequired[str] + description: NotRequired[str] spoiler: NotRequired[bool] id: Snowflake filename: str diff --git a/discord/types/onboarding.py b/discord/types/onboarding.py index 4fd4027bcc..7bfa44dc13 100644 --- a/discord/types/onboarding.py +++ b/discord/types/onboarding.py @@ -61,4 +61,4 @@ class PromptOption(TypedDict): emoji_name: NotRequired[str] emoji_animated: NotRequired[bool] title: str - description: NotRequired[str] + description: str | None diff --git a/discord/types/webhook.py b/discord/types/webhook.py index b5db096e11..20fa0e900e 100644 --- a/discord/types/webhook.py +++ b/discord/types/webhook.py @@ -42,13 +42,6 @@ class SourceGuild(TypedDict): WebhookType = Literal[1, 2, 3] -class FollowerWebhook(TypedDict): - source_channel: NotRequired[PartialChannel] - source_guild: NotRequired[SourceGuild] - channel_id: Snowflake - webhook_id: Snowflake - - class PartialWebhook(TypedDict): guild_id: NotRequired[Snowflake] user: NotRequired[User] @@ -57,6 +50,13 @@ class PartialWebhook(TypedDict): type: WebhookType +class FollowerWebhook(PartialWebhook): + source_channel: NotRequired[PartialChannel] + source_guild: NotRequired[SourceGuild] + channel_id: Snowflake + webhook_id: Snowflake + + class Webhook(PartialWebhook): name: NotRequired[str | None] avatar: NotRequired[str | None] diff --git a/discord/user.py b/discord/user.py index 5cd0352df3..57580575a0 100644 --- a/discord/user.py +++ b/discord/user.py @@ -43,6 +43,7 @@ from .message import Message from .state import ConnectionState from .types.channel import DMChannel as DMChannelPayload + from .types.user import PartialUser as PartialUserPayload from .types.user import User as UserPayload @@ -89,7 +90,9 @@ class BaseUser(_UserTag): _avatar_decoration: dict | None _public_flags: int - def __init__(self, *, state: ConnectionState, data: UserPayload) -> None: + def __init__( + self, *, state: ConnectionState, data: UserPayload | PartialUserPayload + ) -> None: self._state = state self._update(data) diff --git a/discord/voice_client.py b/discord/voice_client.py index 46fc293e12..b9d4766883 100644 --- a/discord/voice_client.py +++ b/discord/voice_client.py @@ -532,14 +532,14 @@ async def disconnect(self, *, force: bool = False) -> None: if self.socket: self.socket.close() - async def move_to(self, channel: abc.Snowflake) -> None: + async def move_to(self, channel: abc.Connectable) -> None: """|coro| Moves you to a different voice channel. Parameters ---------- - channel: :class:`abc.Snowflake` + channel: :class:`abc.Connectable` The channel to move to. Must be a voice channel. """ await self.channel.guild.change_voice_state(channel=channel) diff --git a/discord/webhook/async_.py b/discord/webhook/async_.py index d14f9e6c5d..37e8d4c894 100644 --- a/discord/webhook/async_.py +++ b/discord/webhook/async_.py @@ -76,6 +76,7 @@ from ..mentions import AllowedMentions from ..state import ConnectionState from ..types.message import Message as MessagePayload + from ..types.webhook import FollowerWebhook as FollowerWebhookPayload from ..types.webhook import Webhook as WebhookPayload from ..ui.view import View @@ -401,7 +402,7 @@ def edit_webhook_message( payload: dict[str, Any] | None = None, multipart: list[dict[str, Any]] | None = None, files: list[File] | None = None, - ) -> Response[Message]: + ) -> Response[WebhookMessage]: params = {} if thread_id: @@ -460,7 +461,7 @@ def fetch_webhook( session: aiohttp.ClientSession, proxy: str | None = None, proxy_auth: aiohttp.BasicAuth | None = None, - ) -> Response[WebhookPayload]: + ) -> Response[WebhookPayload | FollowerWebhookPayload]: route = Route("GET", "/webhooks/{webhook_id}", webhook_id=webhook_id) return self.request( route, session=session, proxy=proxy, proxy_auth=proxy_auth, auth_token=token @@ -474,7 +475,7 @@ def fetch_webhook_with_token( session: aiohttp.ClientSession, proxy: str | None = None, proxy_auth: aiohttp.BasicAuth | None = None, - ) -> Response[WebhookPayload]: + ) -> Response[WebhookPayload | FollowerWebhookPayload]: route = Route( "GET", "/webhooks/{webhook_id}/{webhook_token}", @@ -985,7 +986,7 @@ class BaseWebhook(Hashable): def __init__( self, - data: WebhookPayload, + data: WebhookPayload | FollowerWebhookPayload, token: str | None = None, state: ConnectionState | None = None, ): @@ -995,7 +996,7 @@ def __init__( ) self._update(data) - def _update(self, data: WebhookPayload): + def _update(self, data: WebhookPayload | FollowerWebhookPayload): self.id = int(data["id"]) self.type = try_enum(WebhookType, int(data["type"])) self.channel_id = utils._get_as_snowflake(data, "channel_id") @@ -1154,7 +1155,7 @@ async def foo(): def __init__( self, - data: WebhookPayload, + data: WebhookPayload | FollowerWebhookPayload, session: aiohttp.ClientSession, proxy: str | None = None, proxy_auth: aiohttp.BasicAuth | None = None,