Browse Source

Fix implicit permission resolution for Thread

Fix #9153
pull/10109/head
Rapptz 2 years ago
committed by dolfies
parent
commit
e6f549008f
  1. 28
      discord/abc.py
  2. 3
      discord/channel.py
  3. 29
      discord/threads.py

28
discord/abc.py

@ -755,6 +755,20 @@ class GuildChannel:
category = self.guild.get_channel(self.category_id)
return bool(category and category.overwrites == self.overwrites)
def _apply_implicit_permissions(self, base: Permissions) -> None:
# if you can't send a message in a channel then you can't have certain
# permissions as well
if not base.send_messages:
base.send_tts_messages = False
base.mention_everyone = False
base.embed_links = False
base.attach_files = False
# if you can't read a channel then you have no permissions there
if not base.read_messages:
denied = Permissions.all_channel()
base.value &= ~denied.value
def permissions_for(self, obj: Union[Member, Role], /) -> Permissions:
"""Handles permission resolution for the :class:`~discord.Member`
or :class:`~discord.Role`.
@ -765,6 +779,7 @@ class GuildChannel:
- Guild roles
- Channel overrides
- Member overrides
- Implicit permissions
- Member timeout
If a :class:`~discord.Role` is passed, then it checks the permissions
@ -880,19 +895,6 @@ class GuildChannel:
base.handle_overwrite(allow=overwrite.allow, deny=overwrite.deny)
break
# if you can't send a message in a channel then you can't have certain
# permissions as well
if not base.send_messages:
base.send_tts_messages = False
base.mention_everyone = False
base.embed_links = False
base.attach_files = False
# if you can't read a channel then you have no permissions there
if not base.read_messages:
denied = Permissions.all_channel()
base.value &= ~denied.value
if obj.is_timed_out():
# Timeout leads to every permission except VIEW_CHANNEL and READ_MESSAGE_HISTORY
# being explicitly denied

3
discord/channel.py

@ -226,6 +226,7 @@ class TextChannel(discord.abc.Messageable, discord.abc.GuildChannel, Hashable):
@utils.copy_doc(discord.abc.GuildChannel.permissions_for)
def permissions_for(self, obj: Union[Member, Role], /) -> Permissions:
base = super().permissions_for(obj)
self._apply_implicit_permissions(base)
# text channels do not have voice related permissions
denied = Permissions.voice()
@ -947,6 +948,7 @@ class VocalGuildChannel(discord.abc.Connectable, discord.abc.GuildChannel, Hasha
@utils.copy_doc(discord.abc.GuildChannel.permissions_for)
def permissions_for(self, obj: Union[Member, Role], /) -> Permissions:
base = super().permissions_for(obj)
self._apply_implicit_permissions(base)
# voice channels cannot be edited by people who can't connect to them
# It also implicitly denies all other voice perms
@ -2151,6 +2153,7 @@ class ForumChannel(discord.abc.GuildChannel, Hashable):
@utils.copy_doc(discord.abc.GuildChannel.permissions_for)
def permissions_for(self, obj: Union[Member, Role], /) -> Permissions:
base = super().permissions_for(obj)
self._apply_implicit_permissions(base)
# text channels do not have voice related permissions
denied = Permissions.voice()

29
discord/threads.py

@ -31,10 +31,11 @@ import array
import copy
from .mixins import Hashable
from .abc import Messageable, _purge_helper
from .abc import Messageable, GuildChannel, _purge_helper
from .enums import ChannelType, try_enum
from .errors import ClientException, InvalidData
from .flags import ChannelFlags
from .permissions import Permissions
from .utils import MISSING, parse_time, snowflake_time, _get_as_snowflake, _unique
__all__ = (
@ -58,7 +59,6 @@ if TYPE_CHECKING:
from .message import Message, PartialMessage
from .abc import Snowflake, SnowflakeTime
from .role import Role
from .permissions import Permissions
from .state import ConnectionState
@ -411,10 +411,9 @@ class Thread(Messageable, Hashable):
"""Handles permission resolution for the :class:`~discord.Member`
or :class:`~discord.Role`.
Since threads do not have their own permissions, they inherit them
from the parent channel. This is a convenience method for
calling :meth:`~discord.TextChannel.permissions_for` on the
parent channel.
Since threads do not have their own permissions, they mostly
inherit them from the parent channel with some implicit
permissions changed.
Parameters
----------
@ -437,7 +436,23 @@ class Thread(Messageable, Hashable):
parent = self.parent
if parent is None:
raise ClientException('Parent channel not found')
return parent.permissions_for(obj)
base = GuildChannel.permissions_for(parent, obj)
# if you can't send a message in a channel then you can't have certain
# permissions as well
if not base.send_messages_in_threads:
base.send_tts_messages = False
base.mention_everyone = False
base.embed_links = False
base.attach_files = False
# if you can't read a channel then you have no permissions there
if not base.read_messages:
denied = Permissions.all_channel()
base.value &= ~denied.value
return base
async def delete_messages(self, messages: Iterable[Snowflake], /, *, reason: Optional[str] = None) -> None:
"""|coro|

Loading…
Cancel
Save