diff --git a/discord/abc.py b/discord/abc.py index 85cea03af..b0651f44f 100644 --- a/discord/abc.py +++ b/discord/abc.py @@ -471,6 +471,8 @@ class GuildChannel: if isinstance(target, Role): payload['type'] = _Overwrites.ROLE + elif isinstance(target, Object): + payload['type'] = _Overwrites.ROLE if target.type is Role else _Overwrites.MEMBER else: payload['type'] = _Overwrites.MEMBER @@ -548,14 +550,13 @@ class GuildChannel: """:class:`datetime.datetime`: Returns the channel's creation time in UTC.""" return utils.snowflake_time(self.id) - def overwrites_for(self, obj: Union[Role, User]) -> PermissionOverwrite: + def overwrites_for(self, obj: Union[Role, User, Object]) -> PermissionOverwrite: """Returns the channel-specific overwrites for a member or a role. Parameters ----------- - obj: Union[:class:`~discord.Role`, :class:`~discord.abc.User`] - The role or user denoting - whose overwrite to get. + obj: Union[:class:`~discord.Role`, :class:`~discord.abc.User`, :class:`~discord.Object`] + The role or user denoting whose overwrite to get. Returns --------- @@ -579,16 +580,19 @@ class GuildChannel: return PermissionOverwrite() @property - def overwrites(self) -> Dict[Union[Role, Member], PermissionOverwrite]: + def overwrites(self) -> Dict[Union[Role, Member, Object], PermissionOverwrite]: """Returns all of the channel's overwrites. This is returned as a dictionary where the key contains the target which can be either a :class:`~discord.Role` or a :class:`~discord.Member` and the value is the overwrite as a :class:`~discord.PermissionOverwrite`. + .. versionchanged:: 2.0 + Overwrites can now be type-aware :class:`~discord.Object` in case of cache lookup failure + Returns -------- - Dict[Union[:class:`~discord.Role`, :class:`~discord.Member`], :class:`~discord.PermissionOverwrite`] + Dict[Union[:class:`~discord.Role`, :class:`~discord.Member`, :class:`~discord.Object`], :class:`~discord.PermissionOverwrite`] The channel's permission overwrites. """ ret = {} @@ -603,13 +607,11 @@ class GuildChannel: elif ow.is_member(): target = self.guild.get_member(ow.id) - # TODO: There is potential data loss here in the non-chunked - # case, i.e. target is None because get_member returned nothing. - # This can be fixed with a slight breaking change to the return type, - # i.e. adding discord.Object to the list of it - # However, for now this is an acceptable compromise. - if target is not None: - ret[target] = overwrite + if target is None: + target_type = Role if ow.is_role() else User + target = Object(id=ow.id, type=target_type) # type: ignore + + ret[target] = overwrite return ret @property diff --git a/discord/channel.py b/discord/channel.py index 1d06db971..1c0147e6d 100644 --- a/discord/channel.py +++ b/discord/channel.py @@ -38,6 +38,7 @@ from typing import ( TYPE_CHECKING, Sequence, Tuple, + TypeVar, Union, overload, ) @@ -72,6 +73,7 @@ if TYPE_CHECKING: from .types.threads import ThreadArchiveDuration from .role import Role + from .object import Object from .member import Member, VoiceState from .abc import Snowflake, SnowflakeTime from .embeds import Embed @@ -96,6 +98,8 @@ if TYPE_CHECKING: ) from .types.snowflake import SnowflakeList + OverwriteKeyT = TypeVar('OverwriteKeyT', Role, BaseUser, Object, Union[Role, Member, Object]) + class ThreadWithMessage(NamedTuple): thread: Thread @@ -293,7 +297,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable): slowmode_delay: int = ..., default_auto_archive_duration: ThreadArchiveDuration = ..., type: ChannelType = ..., - overwrites: Mapping[Union[Role, Member, Snowflake], PermissionOverwrite] = ..., + overwrites: Mapping[OverwriteKeyT, PermissionOverwrite] = ..., ) -> TextChannel: ... @@ -1329,7 +1333,7 @@ class VoiceChannel(discord.abc.Messageable, VocalGuildChannel): position: int = ..., sync_permissions: int = ..., category: Optional[CategoryChannel] = ..., - overwrites: Mapping[Union[Role, Member], PermissionOverwrite] = ..., + overwrites: Mapping[OverwriteKeyT, PermissionOverwrite] = ..., rtc_region: Optional[str] = ..., video_quality_mode: VideoQualityMode = ..., reason: Optional[str] = ..., @@ -1629,7 +1633,7 @@ class StageChannel(VocalGuildChannel): position: int = ..., sync_permissions: int = ..., category: Optional[CategoryChannel] = ..., - overwrites: Mapping[Union[Role, Member], PermissionOverwrite] = ..., + overwrites: Mapping[OverwriteKeyT, PermissionOverwrite] = ..., rtc_region: Optional[str] = ..., video_quality_mode: VideoQualityMode = ..., reason: Optional[str] = ..., @@ -1802,7 +1806,7 @@ class CategoryChannel(discord.abc.GuildChannel, Hashable): name: str = ..., position: int = ..., nsfw: bool = ..., - overwrites: Mapping[Union[Role, Member], PermissionOverwrite] = ..., + overwrites: Mapping[OverwriteKeyT, PermissionOverwrite] = ..., reason: Optional[str] = ..., ) -> CategoryChannel: ... @@ -2114,7 +2118,7 @@ class ForumChannel(discord.abc.GuildChannel, Hashable): slowmode_delay: int = ..., default_auto_archive_duration: ThreadArchiveDuration = ..., type: ChannelType = ..., - overwrites: Mapping[Union[Role, Member, Snowflake], PermissionOverwrite] = ..., + overwrites: Mapping[OverwriteKeyT, PermissionOverwrite] = ..., ) -> ForumChannel: ... diff --git a/docs/migrating.rst b/docs/migrating.rst index 128671d59..10afcc17d 100644 --- a/docs/migrating.rst +++ b/docs/migrating.rst @@ -1119,6 +1119,7 @@ The following changes have been made: - :attr:`AuditLogEntry.target` may now be a :class:`PartialMessageable`. - :attr:`PartialMessage.channel` may now be a :class:`PartialMessageable`. - :attr:`Guild.preferred_locale` is now of type :class:`Locale`. +- :attr:`abc.GuildChannel.overwrites` keys can now have :class:`Object` in them. Removals ----------