From de3817aef62a3fb3b431044a68b585cbfdb19caa Mon Sep 17 00:00:00 2001 From: mAxYoLo01 Date: Thu, 1 Sep 2022 16:44:50 +0100 Subject: [PATCH 1/4] feat: create `Context.has_permissions()` & `Member.has_permissions()` --- interactions/api/models/channel.py | 8 ++--- interactions/api/models/member.py | 58 ++++++++++++++++++++++++++++-- interactions/client/context.py | 26 ++++++++++++++ 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/interactions/api/models/channel.py b/interactions/api/models/channel.py index ab4bbd7e9..49d5c0480 100644 --- a/interactions/api/models/channel.py +++ b/interactions/api/models/channel.py @@ -1231,13 +1231,9 @@ async def get_permissions_for(self, member: "Member") -> Permissions: if not self.guild_id: return Permissions.DEFAULT - from .guild import Guild + permissions = await member.get_guild_permissions(self.guild_id) - guild = Guild(**await self._client.get_guild(int(self.guild_id)), _client=self._client) - - permissions = await member.get_guild_permissions(guild) - - if permissions & Permissions.ADMINISTRATOR == Permissions.ADMINISTRATOR: + if Permissions.ADMINISTRATOR in permissions: return Permissions.ALL # @everyone role overwrites diff --git a/interactions/api/models/member.py b/interactions/api/models/member.py index 9b63e64d1..8ea0c7f61 100644 --- a/interactions/api/models/member.py +++ b/interactions/api/models/member.py @@ -507,7 +507,7 @@ def get_avatar_url( url += ".gif" if self.avatar.startswith("a_") else ".png" return url - async def get_guild_permissions(self, guild: "Guild") -> Permissions: + async def get_guild_permissions(self, guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING) -> Permissions: """ Returns the permissions of the member for the specified guild. @@ -521,6 +521,22 @@ async def get_guild_permissions(self, guild: "Guild") -> Permissions: :return: Base permissions of the member in the specified guild :rtype: Permissions """ + from .guild import Guild + + if isinstance(guild_id, Guild): + guild = guild_id + + else: + if guild_id is MISSING: + _guild_id = self.guild_id + if isinstance(_guild_id, LibraryException): + raise _guild_id + + else: + _guild_id = int(guild_id) + + guild = Guild(**await self._client.get_guild(int(_guild_id)), _client=self._client) + if int(guild.owner_id) == int(self.id): return Permissions.ALL @@ -531,7 +547,45 @@ async def get_guild_permissions(self, guild: "Guild") -> Permissions: role = await guild.get_role(role_id) permissions |= int(role.permissions) - if permissions & Permissions.ADMINISTRATOR == Permissions.ADMINISTRATOR: + if Permissions.ADMINISTRATOR in Permissions(permissions): return Permissions.ALL return Permissions(permissions) + + async def has_permissions( + self, + *permissions: Union[int, Permissions], + channel: Optional[Channel] = MISSING, + guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING, + operator: str = "and" + ) -> bool: + """ + Returns whether the member has the permissions passed. + + .. note:: + If the channel argument is present, the function will look if the member has the permissions in the specified channel. + If the argument is missing, then it will only consider the member's guild permissions. + + :param *permissions: The list of permissions + :type *permissions: Union[int, Permissions] + :param channel: The channel where to check for permissions + :type channel: Channel + :param guild_id: The id of the guild + :type guild_id: Optional[Union[int, Snowflake, Guild]] + :param operator: The operator to use to calculate permissions. Possible values: `and`, `or`. Defaults to `and`. + :type operator: str + :return: Whether the member has the permissions + :rtype: bool + """ + perms = await self.get_guild_permissions(guild_id) if channel is MISSING else await channel.get_permissions_for(self) + + if operator == "and": + for perm in permissions: + if perm not in perms: + return False + return True + else: + for perm in permissions: + if perm in perms: + return True + return False diff --git a/interactions/client/context.py b/interactions/client/context.py index b3cb4ca98..780307dd3 100644 --- a/interactions/client/context.py +++ b/interactions/client/context.py @@ -310,6 +310,32 @@ async def popup(self, modal: Modal) -> dict: return payload + async def has_permissions( + self, + *permissions: Union[int, Permissions], + operator: str = "and" + ) -> bool: + """ + Returns whether the author of the interaction has the permissions in the given context. + + :param *permissions: The list of permissions + :type *permissions: Union[int, Permissions] + :param operator: The operator to use to calculate permissions. Possible values: `and`, `or`. Defaults to `and`. + :type operator: str + :return: Whether the author has the permissions + :rtype: bool + """ + if operator == "and": + for perm in permissions: + if perm not in self.author.permissions: + return False + return True + else: + for perm in permissions: + if perm in self.author.permissions: + return True + return False + @define() class CommandContext(_Context): From ce74bdaec69856a6857b588912ac444839427bce Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 Sep 2022 15:48:09 +0000 Subject: [PATCH 2/4] ci: correct from checks. --- interactions/api/models/member.py | 12 +++++++++--- interactions/client/context.py | 4 +--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/interactions/api/models/member.py b/interactions/api/models/member.py index 8ea0c7f61..f5f466e44 100644 --- a/interactions/api/models/member.py +++ b/interactions/api/models/member.py @@ -507,7 +507,9 @@ def get_avatar_url( url += ".gif" if self.avatar.startswith("a_") else ".png" return url - async def get_guild_permissions(self, guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING) -> Permissions: + async def get_guild_permissions( + self, guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING + ) -> Permissions: """ Returns the permissions of the member for the specified guild. @@ -557,7 +559,7 @@ async def has_permissions( *permissions: Union[int, Permissions], channel: Optional[Channel] = MISSING, guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING, - operator: str = "and" + operator: str = "and", ) -> bool: """ Returns whether the member has the permissions passed. @@ -577,7 +579,11 @@ async def has_permissions( :return: Whether the member has the permissions :rtype: bool """ - perms = await self.get_guild_permissions(guild_id) if channel is MISSING else await channel.get_permissions_for(self) + perms = ( + await self.get_guild_permissions(guild_id) + if channel is MISSING + else await channel.get_permissions_for(self) + ) if operator == "and": for perm in permissions: diff --git a/interactions/client/context.py b/interactions/client/context.py index 780307dd3..0d0f913ef 100644 --- a/interactions/client/context.py +++ b/interactions/client/context.py @@ -311,9 +311,7 @@ async def popup(self, modal: Modal) -> dict: return payload async def has_permissions( - self, - *permissions: Union[int, Permissions], - operator: str = "and" + self, *permissions: Union[int, Permissions], operator: str = "and" ) -> bool: """ Returns whether the author of the interaction has the permissions in the given context. From 3ebc6bfc9ef0e568849338adbddbd4a274349baf Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 1 Sep 2022 17:53:04 +0200 Subject: [PATCH 3/4] Update interactions/api/models/member.py Co-authored-by: EdVraz <88881326+EdVraz@users.noreply.github.com> --- interactions/api/models/member.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/interactions/api/models/member.py b/interactions/api/models/member.py index f5f466e44..104a8cee9 100644 --- a/interactions/api/models/member.py +++ b/interactions/api/models/member.py @@ -525,17 +525,13 @@ async def get_guild_permissions( """ from .guild import Guild - if isinstance(guild_id, Guild): - guild = guild_id + if guild_id is MISSING: + _guild_id = self.guild_id + if isinstance(_guild_id, LibraryException): + raise _guild_id else: - if guild_id is MISSING: - _guild_id = self.guild_id - if isinstance(_guild_id, LibraryException): - raise _guild_id - - else: - _guild_id = int(guild_id) + _guild_id = int(guild_id) if not isinstance(guild_id, Guild) else int(guild_id.id) guild = Guild(**await self._client.get_guild(int(_guild_id)), _client=self._client) From d75261c3ac68fc9a0900a850c647fd116c26cdb3 Mon Sep 17 00:00:00 2001 From: mAxYoLo01 Date: Thu, 1 Sep 2022 16:54:39 +0100 Subject: [PATCH 4/4] fix: guild could be unbound --- interactions/api/models/member.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interactions/api/models/member.py b/interactions/api/models/member.py index 104a8cee9..925c9cb5b 100644 --- a/interactions/api/models/member.py +++ b/interactions/api/models/member.py @@ -533,7 +533,7 @@ async def get_guild_permissions( else: _guild_id = int(guild_id) if not isinstance(guild_id, Guild) else int(guild_id.id) - guild = Guild(**await self._client.get_guild(int(_guild_id)), _client=self._client) + guild = Guild(**await self._client.get_guild(int(_guild_id)), _client=self._client) if int(guild.owner_id) == int(self.id): return Permissions.ALL