Source code for toolbox.members

from __future__ import annotations

import typing as t

import hikari

from .errors import CacheFailureError
from .roles import sort_roles

__all__: t.Sequence[str] = ("get_member_color", "is_above", "get_possessive", "calculate_permissions", "can_moderate")


[docs]def get_member_color(member: hikari.Member) -> hikari.Color: """Retrieves the color of a member based on the top colored role. Parameters ---------- member : hikari.Member The member to get the color of. Returns ------- hikari.Color The retrieved color object. If no color is found, it will return RGB(0, 0, 0). """ roles = sort_roles(member.get_roles()) if not roles: return hikari.Color(0) for role in roles: if role.color != hikari.Color.from_rgb(0, 0, 0): return role.color return hikari.Color(0)
[docs]def is_above(member1: hikari.Member, member2: hikari.Member) -> bool: """ Returns True if member1's top role's position is higher than member2's. Parameters ---------- member1 : hikari.Member The first member to compare. member2 : hikari.Member The second member to compare. Returns ------- bool Whether member1's top role's position is higher than member2's. """ member1_top_role = member1.get_top_role() member2_top_role = member2.get_top_role() if not member1_top_role or not member2_top_role: raise CacheFailureError("Some objects could not be resolved from cache.") return member1_top_role.position > member2_top_role.position
[docs]def get_possessive(user: hikari.User) -> str: """Returns the possessive noun of a user or a member. If a `Member` is passed, the display name is used to form the possessive noun when possible. In all other situations, the username is used instead. Parameters ---------- user : User The user or member to get the possessive noun of. Returns ------- str The possessive noun of the user or member. """ name = getattr(user, "display_name", user.username) return f"{name}'{'s' if not name.endswith('s') else ''}"
[docs]def calculate_permissions( member: hikari.Member, channel: t.Optional[hikari.PermissibleGuildChannel] = None ) -> hikari.Permissions: """Calculate the permissions of a member. If a channel is provided, channel overwrites will be taken into account. Parameters ---------- member : hikari.Member The member to calculate the permissions of. channel : hikari.GuildChannel, optional The channel for permission overwrite calculations, by default None. Returns ------- hikari.Permissions The calculated permissions. Raises ------ CacheFailureError Some objects could not be resolved from cache to perform the operation. """ guild = member.get_guild() if not guild: raise CacheFailureError("Guild could not be resolved from cache.") if guild.owner_id == member.id: return hikari.Permissions.all_permissions() guild_roles = guild.get_roles() member_roles = list(filter(lambda r: r.id in member.role_ids, guild_roles.values())) permissions: hikari.Permissions = guild_roles[guild.id].permissions # Start with @everyone perms for role in member_roles: permissions |= role.permissions if permissions & hikari.Permissions.ADMINISTRATOR: return hikari.Permissions.all_permissions() if not channel: # End of role-based permissions return permissions if overwrite_everyone := channel.permission_overwrites.get(channel.guild_id): permissions &= ~overwrite_everyone.deny permissions |= overwrite_everyone.allow overwrites = hikari.PermissionOverwrite( # Collect role overwrites here id=hikari.Snowflake(69), type=hikari.PermissionOverwriteType.ROLE, allow=hikari.Permissions.NONE, deny=hikari.Permissions.NONE, ) for role in member_roles: if overwrite := channel.permission_overwrites.get(role.id): overwrites.deny |= overwrite.deny overwrites.allow |= overwrite.allow permissions &= ~overwrites.deny permissions |= overwrites.allow if overwrite_member := channel.permission_overwrites.get(member.id): permissions &= ~overwrite_member.deny permissions |= overwrite_member.allow return permissions
[docs]def can_moderate( moderator: hikari.Member, member: hikari.Member, permissions: hikari.Permissions = hikari.Permissions.NONE ) -> bool: """ Returns True if "moderator" can execute moderation actions on "member", also checks if "moderator" has "permissions". Parameters ---------- moderator : hikari.Member The moderator to check. member : hikari.Member The member to check. permissions : hikari.Permissions The permissions `moderator` should have. Returns ------- bool Whether "moderator" can execute moderation actions on "member". Raises ------ CacheFailureError Some objects could not be resolved from cache to perform the operation. """ if not is_above(moderator, member): return False guild = member.get_guild() if not guild: raise CacheFailureError("Guild could not be resolved from cache.") if guild.owner_id == member.id: return False if permissions is hikari.Permissions.NONE: return True mod_perms = calculate_permissions(moderator) if mod_perms & hikari.Permissions.ADMINISTRATOR: return True return bool(mod_perms & permissions)
# MIT License # # Copyright (c) 2022-present HyperGH # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE.