mirror of
https://github.com/Rapptz/discord.py.git
synced 2025-07-06 18:11:59 +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`
|
:class:`Permissions`
|
||||||
The resolved permissions.
|
The resolved permissions.
|
||||||
"""
|
"""
|
||||||
|
return Permissions._dm_permissions()
|
||||||
base = Permissions.text()
|
|
||||||
base.read_messages = True
|
|
||||||
base.send_tts_messages = False
|
|
||||||
base.manage_messages = False
|
|
||||||
return base
|
|
||||||
|
|
||||||
def get_partial_message(self, message_id: int, /) -> PartialMessage:
|
def get_partial_message(self, message_id: int, /) -> PartialMessage:
|
||||||
"""Creates a :class:`PartialMessage` from the message ID.
|
"""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.
|
The resolved permissions for the user.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
base = Permissions.text()
|
base = Permissions._dm_permissions()
|
||||||
base.read_messages = True
|
|
||||||
base.send_tts_messages = False
|
|
||||||
base.manage_messages = False
|
|
||||||
base.mention_everyone = True
|
base.mention_everyone = True
|
||||||
|
|
||||||
if obj.id == self.owner_id:
|
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.abc
|
||||||
import discord.utils
|
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 discord.context_managers import Typing
|
||||||
from .view import StringView
|
from .view import StringView
|
||||||
|
|
||||||
@ -456,6 +456,76 @@ class Context(discord.abc.Messageable, Generic[BotT]):
|
|||||||
# bot.user will never be None at this point.
|
# 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
|
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
|
@property
|
||||||
def voice_client(self) -> Optional[VoiceProtocol]:
|
def voice_client(self) -> Optional[VoiceProtocol]:
|
||||||
r"""Optional[:class:`.VoiceProtocol`]: A shortcut to :attr:`.Guild.voice_client`\, if applicable."""
|
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)}")
|
raise TypeError(f"Invalid permission(s): {', '.join(invalid)}")
|
||||||
|
|
||||||
def predicate(ctx: Context[BotT]) -> bool:
|
def predicate(ctx: Context[BotT]) -> bool:
|
||||||
ch = ctx.channel
|
permissions = ctx.permissions
|
||||||
permissions = ch.permissions_for(ctx.author) # type: ignore
|
|
||||||
|
|
||||||
missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value]
|
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)}")
|
raise TypeError(f"Invalid permission(s): {', '.join(invalid)}")
|
||||||
|
|
||||||
def predicate(ctx: Context[BotT]) -> bool:
|
def predicate(ctx: Context[BotT]) -> bool:
|
||||||
guild = ctx.guild
|
permissions = ctx.bot_permissions
|
||||||
me = guild.me if guild is not None else ctx.bot.user
|
|
||||||
permissions = ctx.channel.permissions_for(me) # type: ignore
|
|
||||||
|
|
||||||
missing = [perm for perm, value in perms.items() if getattr(permissions, perm) != value]
|
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
|
p.read_message_history = False
|
||||||
return ~p.value
|
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
|
@classmethod
|
||||||
def all_channel(cls) -> Self:
|
def all_channel(cls) -> Self:
|
||||||
"""A :class:`Permissions` with all channel-specific permissions set to
|
"""A :class:`Permissions` with all channel-specific permissions set to
|
||||||
|
Loading…
x
Reference in New Issue
Block a user