mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-04-20 16:00:29 +00:00
[commands] Add Context.permissions and Context.bot_permissions
This commit is contained in:
parent
65a270d35a
commit
9fe19dcc69
@ -2498,12 +2498,7 @@ class DMChannel(discord.abc.Messageable, discord.abc.PrivateChannel, Hashable):
|
||||
:class:`Permissions`
|
||||
The resolved permissions.
|
||||
"""
|
||||
|
||||
base = Permissions.text()
|
||||
base.read_messages = True
|
||||
base.send_tts_messages = False
|
||||
base.manage_messages = False
|
||||
return base
|
||||
return Permissions._dm_permissions()
|
||||
|
||||
def get_partial_message(self, message_id: int, /) -> PartialMessage:
|
||||
"""Creates a :class:`PartialMessage` from the message ID.
|
||||
@ -2671,10 +2666,7 @@ class GroupChannel(discord.abc.Messageable, discord.abc.PrivateChannel, Hashable
|
||||
The resolved permissions for the user.
|
||||
"""
|
||||
|
||||
base = Permissions.text()
|
||||
base.read_messages = True
|
||||
base.send_tts_messages = False
|
||||
base.manage_messages = False
|
||||
base = Permissions._dm_permissions()
|
||||
base.mention_everyone = True
|
||||
|
||||
if obj.id == self.owner_id:
|
||||
|
@ -28,7 +28,7 @@ from typing import TYPE_CHECKING, Any, Dict, Generator, Generic, List, Optional,
|
||||
|
||||
import discord.abc
|
||||
import discord.utils
|
||||
from discord import Interaction, Message, Attachment, MessageType, User, PartialMessageable
|
||||
from discord import Interaction, Message, Attachment, MessageType, User, PartialMessageable, Permissions, ChannelType, Thread
|
||||
from discord.context_managers import Typing
|
||||
from .view import StringView
|
||||
|
||||
@ -456,6 +456,76 @@ class Context(discord.abc.Messageable, Generic[BotT]):
|
||||
# bot.user will never be None at this point.
|
||||
return self.guild.me if self.guild is not None else self.bot.user # type: ignore
|
||||
|
||||
@discord.utils.cached_property
|
||||
def permissions(self) -> Permissions:
|
||||
""":class:`.Permissions`: Returns the resolved permissions for the invoking user in this channel.
|
||||
Shorthand for :meth:`.abc.GuildChannel.permissions_for` or :attr:`.Interaction.permissions`.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
if self.channel.type is ChannelType.private:
|
||||
return Permissions._dm_permissions()
|
||||
if not self.interaction:
|
||||
# channel and author will always match relevant types here
|
||||
return self.channel.permissions_for(self.author) # type: ignore
|
||||
base = self.interaction.permissions
|
||||
if self.channel.type in (ChannelType.voice, ChannelType.stage_voice):
|
||||
if not base.connect:
|
||||
# voice channels cannot be edited by people who can't connect to them
|
||||
# It also implicitly denies all other voice perms
|
||||
denied = Permissions.voice()
|
||||
denied.update(manage_channels=True, manage_roles=True)
|
||||
base.value &= ~denied.value
|
||||
else:
|
||||
# text channels do not have voice related permissions
|
||||
denied = Permissions.voice()
|
||||
base.value &= ~denied.value
|
||||
return base
|
||||
|
||||
@discord.utils.cached_property
|
||||
def bot_permissions(self) -> Permissions:
|
||||
""":class:`.Permissions`: Returns the resolved permissions for the bot in this channel.
|
||||
Shorthand for :meth:`.abc.GuildChannel.permissions_for` or :attr:`.Interaction.app_permissions`.
|
||||
|
||||
For interaction-based commands, this will reflect the effective permissions
|
||||
for :class:`Context` calls, which may differ from calls through
|
||||
other :class:`.abc.Messageable` endpoints, like :attr:`channel`.
|
||||
|
||||
Notably, sending messages, embedding links, and attaching files are always
|
||||
permitted, while reading messages might not be.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
channel = self.channel
|
||||
if channel.type == ChannelType.private:
|
||||
return Permissions._dm_permissions()
|
||||
if not self.interaction:
|
||||
# channel and me will always match relevant types here
|
||||
return channel.permissions_for(self.me) # type: ignore
|
||||
guild = channel.guild
|
||||
base = self.interaction.app_permissions
|
||||
if self.channel.type in (ChannelType.voice, ChannelType.stage_voice):
|
||||
if not base.connect:
|
||||
# voice channels cannot be edited by people who can't connect to them
|
||||
# It also implicitly denies all other voice perms
|
||||
denied = Permissions.voice()
|
||||
denied.update(manage_channels=True, manage_roles=True)
|
||||
base.value &= ~denied.value
|
||||
else:
|
||||
# text channels do not have voice related permissions
|
||||
denied = Permissions.voice()
|
||||
base.value &= ~denied.value
|
||||
base.update(
|
||||
embed_links=True,
|
||||
attach_files=True,
|
||||
send_tts_messages=False,
|
||||
)
|
||||
if isinstance(channel, Thread):
|
||||
base.send_messages_in_threads = True
|
||||
else:
|
||||
base.send_messages = True
|
||||
return base
|
||||
|
||||
@property
|
||||
def voice_client(self) -> Optional[VoiceProtocol]:
|
||||
r"""Optional[:class:`.VoiceProtocol`]: A shortcut to :attr:`.Guild.voice_client`\, if applicable."""
|
||||
|
@ -2159,8 +2159,7 @@ def has_permissions(**perms: bool) -> Check[Any]:
|
||||
raise TypeError(f"Invalid permission(s): {', '.join(invalid)}")
|
||||
|
||||
def predicate(ctx: Context[BotT]) -> bool:
|
||||
ch = ctx.channel
|
||||
permissions = ch.permissions_for(ctx.author) # type: ignore
|
||||
permissions = ctx.permissions
|
||||
|
||||
missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value]
|
||||
|
||||
@ -2185,9 +2184,7 @@ def bot_has_permissions(**perms: bool) -> Check[Any]:
|
||||
raise TypeError(f"Invalid permission(s): {', '.join(invalid)}")
|
||||
|
||||
def predicate(ctx: Context[BotT]) -> bool:
|
||||
guild = ctx.guild
|
||||
me = guild.me if guild is not None else ctx.bot.user
|
||||
permissions = ctx.channel.permissions_for(me) # type: ignore
|
||||
permissions = ctx.bot_permissions
|
||||
|
||||
missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value]
|
||||
|
||||
|
@ -186,6 +186,14 @@ class Permissions(BaseFlags):
|
||||
p.read_message_history = False
|
||||
return ~p.value
|
||||
|
||||
@classmethod
|
||||
def _dm_permissions(cls) -> Self:
|
||||
base = cls.text()
|
||||
base.read_messages = True
|
||||
base.send_tts_messages = False
|
||||
base.manage_messages = False
|
||||
return base
|
||||
|
||||
@classmethod
|
||||
def all_channel(cls) -> Self:
|
||||
"""A :class:`Permissions` with all channel-specific permissions set to
|
||||
|
Loading…
x
Reference in New Issue
Block a user