Skip to content

Commit 9e0a078

Browse files
mAxYoLo01pre-commit-ci[bot]EepyElvyra
authored
feat: create Context.has_permissions() & Member.has_permissions() (#1056)
* feat: create `Context.has_permissions()` & `Member.has_permissions()` * ci: correct from checks. * Update interactions/api/models/member.py Co-authored-by: EdVraz <88881326+EdVraz@users.noreply.github.com> * fix: guild could be unbound Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: EdVraz <88881326+EdVraz@users.noreply.github.com>
1 parent 9362d1a commit 9e0a078

File tree

3 files changed

+84
-8
lines changed

3 files changed

+84
-8
lines changed

interactions/api/models/channel.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,13 +1231,9 @@ async def get_permissions_for(self, member: "Member") -> Permissions:
12311231
if not self.guild_id:
12321232
return Permissions.DEFAULT
12331233

1234-
from .guild import Guild
1234+
permissions = await member.get_guild_permissions(self.guild_id)
12351235

1236-
guild = Guild(**await self._client.get_guild(int(self.guild_id)), _client=self._client)
1237-
1238-
permissions = await member.get_guild_permissions(guild)
1239-
1240-
if permissions & Permissions.ADMINISTRATOR == Permissions.ADMINISTRATOR:
1236+
if Permissions.ADMINISTRATOR in permissions:
12411237
return Permissions.ALL
12421238

12431239
# @everyone role overwrites

interactions/api/models/member.py

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,9 @@ def get_avatar_url(
507507
url += ".gif" if self.avatar.startswith("a_") else ".png"
508508
return url
509509

510-
async def get_guild_permissions(self, guild: "Guild") -> Permissions:
510+
async def get_guild_permissions(
511+
self, guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING
512+
) -> Permissions:
511513
"""
512514
Returns the permissions of the member for the specified guild.
513515
@@ -521,6 +523,18 @@ async def get_guild_permissions(self, guild: "Guild") -> Permissions:
521523
:return: Base permissions of the member in the specified guild
522524
:rtype: Permissions
523525
"""
526+
from .guild import Guild
527+
528+
if guild_id is MISSING:
529+
_guild_id = self.guild_id
530+
if isinstance(_guild_id, LibraryException):
531+
raise _guild_id
532+
533+
else:
534+
_guild_id = int(guild_id) if not isinstance(guild_id, Guild) else int(guild_id.id)
535+
536+
guild = Guild(**await self._client.get_guild(int(_guild_id)), _client=self._client)
537+
524538
if int(guild.owner_id) == int(self.id):
525539
return Permissions.ALL
526540

@@ -531,7 +545,49 @@ async def get_guild_permissions(self, guild: "Guild") -> Permissions:
531545
role = await guild.get_role(role_id)
532546
permissions |= int(role.permissions)
533547

534-
if permissions & Permissions.ADMINISTRATOR == Permissions.ADMINISTRATOR:
548+
if Permissions.ADMINISTRATOR in Permissions(permissions):
535549
return Permissions.ALL
536550

537551
return Permissions(permissions)
552+
553+
async def has_permissions(
554+
self,
555+
*permissions: Union[int, Permissions],
556+
channel: Optional[Channel] = MISSING,
557+
guild_id: Optional[Union[int, Snowflake, "Guild"]] = MISSING,
558+
operator: str = "and",
559+
) -> bool:
560+
"""
561+
Returns whether the member has the permissions passed.
562+
563+
.. note::
564+
If the channel argument is present, the function will look if the member has the permissions in the specified channel.
565+
If the argument is missing, then it will only consider the member's guild permissions.
566+
567+
:param *permissions: The list of permissions
568+
:type *permissions: Union[int, Permissions]
569+
:param channel: The channel where to check for permissions
570+
:type channel: Channel
571+
:param guild_id: The id of the guild
572+
:type guild_id: Optional[Union[int, Snowflake, Guild]]
573+
:param operator: The operator to use to calculate permissions. Possible values: `and`, `or`. Defaults to `and`.
574+
:type operator: str
575+
:return: Whether the member has the permissions
576+
:rtype: bool
577+
"""
578+
perms = (
579+
await self.get_guild_permissions(guild_id)
580+
if channel is MISSING
581+
else await channel.get_permissions_for(self)
582+
)
583+
584+
if operator == "and":
585+
for perm in permissions:
586+
if perm not in perms:
587+
return False
588+
return True
589+
else:
590+
for perm in permissions:
591+
if perm in perms:
592+
return True
593+
return False

interactions/client/context.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,30 @@ async def popup(self, modal: Modal) -> dict:
310310

311311
return payload
312312

313+
async def has_permissions(
314+
self, *permissions: Union[int, Permissions], operator: str = "and"
315+
) -> bool:
316+
"""
317+
Returns whether the author of the interaction has the permissions in the given context.
318+
319+
:param *permissions: The list of permissions
320+
:type *permissions: Union[int, Permissions]
321+
:param operator: The operator to use to calculate permissions. Possible values: `and`, `or`. Defaults to `and`.
322+
:type operator: str
323+
:return: Whether the author has the permissions
324+
:rtype: bool
325+
"""
326+
if operator == "and":
327+
for perm in permissions:
328+
if perm not in self.author.permissions:
329+
return False
330+
return True
331+
else:
332+
for perm in permissions:
333+
if perm in self.author.permissions:
334+
return True
335+
return False
336+
313337

314338
@define()
315339
class CommandContext(_Context):

0 commit comments

Comments
 (0)