A Python wrapper for the Discord API forked from discord.py
—
Comprehensive permission management, role operations, and access control for Discord servers with fine-grained permission handling.
Discord's bitfield-based permission system with comprehensive access control capabilities.
import nextcord
from typing import Dict, Iterator, Tuple, Union
class Permissions:
"""Wraps up a Discord permission value.
The properties provided are two-way. You can set and retrieve individual permissions.
Attributes
----------
value: int
The raw value of the permissions.
"""
def __init__(self, permissions: int = 0, **kwargs):
"""Initialize permissions.
Parameters
----------
permissions: int
The raw permissions integer.
**kwargs
Individual permission flags to set.
"""
...
@classmethod
def none(cls) -> Permissions:
"""A factory method that creates a Permissions with all permissions set to False."""
...
@classmethod
def all(cls) -> Permissions:
"""A factory method that creates a Permissions with all permissions set to True."""
...
@classmethod
def all_channel(cls) -> Permissions:
"""A factory method that creates a Permissions with all channel permissions set to True."""
...
@classmethod
def general(cls) -> Permissions:
"""A factory method that creates a Permissions with general permissions."""
...
@classmethod
def membership(cls) -> Permissions:
"""A factory method that creates a Permissions with membership permissions."""
...
@classmethod
def text(cls) -> Permissions:
"""A factory method that creates a Permissions with text channel permissions."""
...
@classmethod
def voice(cls) -> Permissions:
"""A factory method that creates a Permissions with voice channel permissions."""
...
@classmethod
def stage(cls) -> Permissions:
"""A factory method that creates a Permissions with stage channel permissions."""
...
@classmethod
def stage_moderator(cls) -> Permissions:
"""A factory method that creates a Permissions with stage moderator permissions."""
...
@classmethod
def advanced(cls) -> Permissions:
"""A factory method that creates a Permissions with advanced permissions."""
...
def update(self, **kwargs) -> None:
"""Bulk update permissions.
Parameters
----------
**kwargs
Permission flags to update.
"""
...
def __iter__(self) -> Iterator[Tuple[str, bool]]:
"""Iterate over all permissions."""
...
# Permission flags (all boolean properties)
class Permissions:
# General Server Permissions
@property
def create_instant_invite(self) -> bool:
"""bool: Returns True if a user can create instant invites."""
...
@property
def kick_members(self) -> bool:
"""bool: Returns True if a user can kick members from the guild."""
...
@property
def ban_members(self) -> bool:
"""bool: Returns True if a user can ban members from the guild."""
...
@property
def administrator(self) -> bool:
"""bool: Returns True if a user is an administrator. This role overrides all other permissions."""
...
@property
def manage_channels(self) -> bool:
"""bool: Returns True if a user can edit, delete, or create channels."""
...
@property
def manage_guild(self) -> bool:
"""bool: Returns True if a user can edit guild properties."""
...
@property
def add_reactions(self) -> bool:
"""bool: Returns True if a user can add reactions to messages."""
...
@property
def view_audit_log(self) -> bool:
"""bool: Returns True if a user can view the guild's audit log."""
...
@property
def priority_speaker(self) -> bool:
"""bool: Returns True if a user can use priority speaker in voice channels."""
...
@property
def stream(self) -> bool:
"""bool: Returns True if a user can stream in voice channels."""
...
@property
def view_channel(self) -> bool:
"""bool: Returns True if a user can view channels."""
...
@property
def send_messages(self) -> bool:
"""bool: Returns True if a user can send messages."""
...
@property
def send_tts_messages(self) -> bool:
"""bool: Returns True if a user can send TTS messages."""
...
@property
def manage_messages(self) -> bool:
"""bool: Returns True if a user can manage messages (delete/pin)."""
...
@property
def embed_links(self) -> bool:
"""bool: Returns True if a user's messages will embed links."""
...
@property
def attach_files(self) -> bool:
"""bool: Returns True if a user can attach files to messages."""
...
@property
def read_message_history(self) -> bool:
"""bool: Returns True if a user can read message history."""
...
@property
def mention_everyone(self) -> bool:
"""bool: Returns True if a user can mention @everyone and @here."""
...
@property
def external_emojis(self) -> bool:
"""bool: Returns True if a user can use external emojis."""
...
@property
def view_guild_insights(self) -> bool:
"""bool: Returns True if a user can view guild insights."""
...
@property
def connect(self) -> bool:
"""bool: Returns True if a user can connect to voice channels."""
...
@property
def speak(self) -> bool:
"""bool: Returns True if a user can speak in voice channels."""
...
@property
def mute_members(self) -> bool:
"""bool: Returns True if a user can mute members in voice channels."""
...
@property
def deafen_members(self) -> bool:
"""bool: Returns True if a user can deafen members in voice channels."""
...
@property
def move_members(self) -> bool:
"""bool: Returns True if a user can move members between voice channels."""
...
@property
def use_voice_activation(self) -> bool:
"""bool: Returns True if a user can use voice activation in voice channels."""
...
@property
def change_nickname(self) -> bool:
"""bool: Returns True if a user can change their nickname."""
...
@property
def manage_nicknames(self) -> bool:
"""bool: Returns True if a user can manage other members' nicknames."""
...
@property
def manage_roles(self) -> bool:
"""bool: Returns True if a user can manage roles."""
...
@property
def manage_webhooks(self) -> bool:
"""bool: Returns True if a user can manage webhooks."""
...
@property
def manage_emojis_and_stickers(self) -> bool:
"""bool: Returns True if a user can manage emojis and stickers."""
...
@property
def use_application_commands(self) -> bool:
"""bool: Returns True if a user can use application commands."""
...
@property
def request_to_speak(self) -> bool:
"""bool: Returns True if a user can request to speak in stage channels."""
...
@property
def manage_events(self) -> bool:
"""bool: Returns True if a user can manage guild events."""
...
@property
def manage_threads(self) -> bool:
"""bool: Returns True if a user can manage threads."""
...
@property
def create_public_threads(self) -> bool:
"""bool: Returns True if a user can create public threads."""
...
@property
def create_private_threads(self) -> bool:
"""bool: Returns True if a user can create private threads."""
...
@property
def external_stickers(self) -> bool:
"""bool: Returns True if a user can use external stickers."""
...
@property
def send_messages_in_threads(self) -> bool:
"""bool: Returns True if a user can send messages in threads."""
...
@property
def use_embedded_activities(self) -> bool:
"""bool: Returns True if a user can use embedded activities in voice channels."""
...
@property
def moderate_members(self) -> bool:
"""bool: Returns True if a user can moderate members (timeout, etc.)."""
...
# Permission usage examples
def create_permissions_examples():
"""Examples of creating and working with permissions."""
# Create permissions with specific flags
perms = nextcord.Permissions(
send_messages=True,
read_message_history=True,
add_reactions=True
)
# Create from raw value
perms_raw = nextcord.Permissions(permissions=268435456)
# Factory methods
admin_perms = nextcord.Permissions.all()
text_perms = nextcord.Permissions.text()
voice_perms = nextcord.Permissions.voice()
# Update permissions
perms.update(manage_messages=True, embed_links=True)
return perms, admin_perms, text_perms, voice_perms
@bot.slash_command(description="Check permissions for a member")
async def checkperms(
interaction: nextcord.Interaction,
member: Optional[nextcord.Member] = nextcord.SlashOption(
description="Member to check permissions for",
default=None
),
channel: Optional[nextcord.TextChannel] = nextcord.SlashOption(
description="Channel to check permissions in",
default=None
)
):
"""Check a member's permissions in a specific channel or guild."""
target = member or interaction.user
check_channel = channel or interaction.channel
# Get permissions
if isinstance(check_channel, nextcord.abc.GuildChannel):
perms = target.permissions_in(check_channel)
context = f"in {check_channel.mention}"
else:
perms = target.guild_permissions
context = "in this server"
embed = nextcord.Embed(
title=f"Permissions for {target.display_name}",
description=f"Permissions {context}",
color=target.color or nextcord.Color.blue()
)
# Key permissions to display
key_perms = {
"Administrator": perms.administrator,
"Manage Server": perms.manage_guild,
"Manage Channels": perms.manage_channels,
"Manage Roles": perms.manage_roles,
"Manage Messages": perms.manage_messages,
"Kick Members": perms.kick_members,
"Ban Members": perms.ban_members,
"Moderate Members": perms.moderate_members,
"Send Messages": perms.send_messages,
"View Channels": perms.view_channel,
"Connect to Voice": perms.connect,
"Speak in Voice": perms.speak,
"Move Members": perms.move_members,
}
# Group permissions by category
dangerous_perms = []
moderation_perms = []
basic_perms = []
for perm_name, has_perm in key_perms.items():
emoji = "✅" if has_perm else "❌"
perm_text = f"{emoji} {perm_name}"
if perm_name in ["Administrator", "Manage Server", "Manage Roles"]:
dangerous_perms.append(perm_text)
elif perm_name in ["Kick Members", "Ban Members", "Moderate Members", "Manage Messages"]:
moderation_perms.append(perm_text)
else:
basic_perms.append(perm_text)
if dangerous_perms:
embed.add_field(name="🔴 Administrative", value="\n".join(dangerous_perms), inline=True)
if moderation_perms:
embed.add_field(name="🟡 Moderation", value="\n".join(moderation_perms), inline=True)
if basic_perms:
embed.add_field(name="🟢 Basic", value="\n".join(basic_perms), inline=True)
# Show raw permission value
embed.add_field(
name="Raw Permission Value",
value=f"`{perms.value}`",
inline=False
)
await interaction.response.send_message(embed=embed)Channel-specific permission overrides for users and roles.
class PermissionOverwrite:
"""A permission overwrite for a channel.
Permission overwrites allow you to set specific permissions for roles or members
in individual channels, overriding their guild-level permissions.
Attributes
----------
allow: Permissions
Permissions that are explicitly allowed.
deny: Permissions
Permissions that are explicitly denied.
"""
def __init__(self, **permissions):
"""Create a permission overwrite.
Parameters
----------
**permissions
Permission flags. Use None for neutral (inherit), True for allow, False for deny.
"""
...
@classmethod
def from_pair(cls, allow: Permissions, deny: Permissions) -> PermissionOverwrite:
"""Create a PermissionOverwrite from an allow/deny pair.
Parameters
----------
allow: Permissions
Permissions to explicitly allow.
deny: Permissions
Permissions to explicitly deny.
Returns
-------
PermissionOverwrite
The created permission overwrite.
"""
...
def update(self, **permissions) -> None:
"""Update the permission overwrite.
Parameters
----------
**permissions
Permission flags to update.
"""
...
def is_empty(self) -> bool:
"""bool: Whether the overwrite is empty (no explicit allows or denies)."""
...
# Permission overwrite examples
@bot.slash_command(description="Set channel permissions for a role")
async def setperms(
interaction: nextcord.Interaction,
channel: nextcord.TextChannel = nextcord.SlashOption(description="Channel to modify"),
role: nextcord.Role = nextcord.SlashOption(description="Role to set permissions for"),
permission: str = nextcord.SlashOption(
description="Permission to modify",
choices=[
"send_messages", "view_channel", "manage_messages",
"add_reactions", "attach_files", "read_message_history"
]
),
value: str = nextcord.SlashOption(
description="Permission value",
choices=["allow", "deny", "neutral"]
)
):
"""Set specific channel permissions for a role."""
if not interaction.user.guild_permissions.manage_roles:
await interaction.response.send_message(
"❌ You don't have permission to manage roles.",
ephemeral=True
)
return
# Get current overwrite or create new one
overwrite = channel.overwrites_for(role)
# Set the permission
perm_value = None if value == "neutral" else (value == "allow")
setattr(overwrite, permission, perm_value)
try:
await channel.set_permissions(
role,
overwrite=overwrite,
reason=f"Permission modified by {interaction.user}"
)
emoji = {"allow": "✅", "deny": "❌", "neutral": "➖"}[value]
await interaction.response.send_message(
f"{emoji} Set `{permission}` to `{value}` for {role.mention} in {channel.mention}.",
ephemeral=True
)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to modify channel permissions.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to set permissions: {e}",
ephemeral=True
)
@bot.slash_command(description="Lock a channel")
async def lockdown(
interaction: nextcord.Interaction,
channel: Optional[nextcord.TextChannel] = nextcord.SlashOption(
description="Channel to lock (defaults to current)",
default=None
),
reason: Optional[str] = nextcord.SlashOption(description="Reason for lockdown", default=None)
):
"""Lock a channel to prevent members from sending messages."""
if not interaction.user.guild_permissions.manage_channels:
await interaction.response.send_message(
"❌ You don't have permission to manage channels.",
ephemeral=True
)
return
target_channel = channel or interaction.channel
# Get @everyone role
everyone_role = interaction.guild.default_role
# Create overwrite that denies sending messages
overwrite = nextcord.PermissionOverwrite(send_messages=False)
try:
await target_channel.set_permissions(
everyone_role,
overwrite=overwrite,
reason=reason or f"Channel locked by {interaction.user}"
)
embed = nextcord.Embed(
title="🔒 Channel Locked",
description=f"{target_channel.mention} has been locked.",
color=nextcord.Color.red()
)
if reason:
embed.add_field(name="Reason", value=reason, inline=False)
embed.set_footer(text=f"Locked by {interaction.user}", icon_url=interaction.user.display_avatar.url)
await interaction.response.send_message(embed=embed)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to modify this channel.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to lock channel: {e}",
ephemeral=True
)
@bot.slash_command(description="Unlock a channel")
async def unlock(
interaction: nextcord.Interaction,
channel: Optional[nextcord.TextChannel] = nextcord.SlashOption(
description="Channel to unlock (defaults to current)",
default=None
),
reason: Optional[str] = nextcord.SlashOption(description="Reason for unlock", default=None)
):
"""Unlock a channel to allow members to send messages again."""
if not interaction.user.guild_permissions.manage_channels:
await interaction.response.send_message(
"❌ You don't have permission to manage channels.",
ephemeral=True
)
return
target_channel = channel or interaction.channel
everyone_role = interaction.guild.default_role
try:
# Remove the send_messages override (set to neutral)
overwrite = target_channel.overwrites_for(everyone_role)
overwrite.send_messages = None
if overwrite.is_empty():
# If overwrite is empty, delete it entirely
await target_channel.set_permissions(
everyone_role,
overwrite=None,
reason=reason or f"Channel unlocked by {interaction.user}"
)
else:
# Keep other overwrites but remove send_messages restriction
await target_channel.set_permissions(
everyone_role,
overwrite=overwrite,
reason=reason or f"Channel unlocked by {interaction.user}"
)
embed = nextcord.Embed(
title="🔓 Channel Unlocked",
description=f"{target_channel.mention} has been unlocked.",
color=nextcord.Color.green()
)
if reason:
embed.add_field(name="Reason", value=reason, inline=False)
embed.set_footer(text=f"Unlocked by {interaction.user}", icon_url=interaction.user.display_avatar.url)
await interaction.response.send_message(embed=embed)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to modify this channel.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to unlock channel: {e}",
ephemeral=True
)Guild roles with hierarchy, permissions, and member management.
class Role(nextcord.abc.Snowflake):
"""Represents a Discord role.
Attributes
----------
id: int
The role ID.
name: str
The role name.
guild: Guild
The guild this role belongs to.
hoist: bool
Whether the role is displayed separately in the member list.
position: int
The role's position in the hierarchy. Higher is more important.
managed: bool
Whether the role is managed by an integration (bot, booster, etc.).
mentionable: bool
Whether the role can be mentioned by members.
permissions: Permissions
The permissions this role grants.
colour: Colour
The role's color.
created_at: datetime.datetime
When the role was created.
mention: str
A string that mentions this role.
members: List[Member]
A list of members who have this role.
"""
@property
def color(self) -> nextcord.Colour:
"""nextcord.Colour: An alias for colour."""
...
def is_default(self) -> bool:
"""bool: Whether this is the @everyone role."""
...
def is_bot_managed(self) -> bool:
"""bool: Whether this role is managed by a bot."""
...
def is_premium_subscriber(self) -> bool:
"""bool: Whether this role is the premium subscriber (booster) role."""
...
def is_integration(self) -> bool:
"""bool: Whether this role is managed by an integration."""
...
async def edit(
self,
*,
name: str = MISSING,
permissions: Permissions = MISSING,
colour: Union[nextcord.Colour, int] = MISSING,
color: Union[nextcord.Colour, int] = MISSING,
hoist: bool = MISSING,
mentionable: bool = MISSING,
position: int = MISSING,
reason: Optional[str] = None,
icon: Optional[bytes] = MISSING,
unicode_emoji: Optional[str] = MISSING,
) -> Role:
"""Edit the role.
Parameters
----------
name: str
The role's new name.
permissions: Permissions
The role's new permissions.
colour: Union[nextcord.Colour, int]
The role's new colour.
color: Union[nextcord.Colour, int]
Alias for colour.
hoist: bool
Whether the role should be hoisted.
mentionable: bool
Whether the role should be mentionable.
position: int
The role's new position.
reason: Optional[str]
The reason for editing this role.
icon: Optional[bytes]
The role's new icon (for premium guilds).
unicode_emoji: Optional[str]
The role's new unicode emoji (for premium guilds).
Returns
-------
Role
The newly edited role.
"""
...
async def delete(self, *, reason: Optional[str] = None) -> None:
"""Delete the role.
Parameters
----------
reason: Optional[str]
The reason for deleting this role.
"""
...
# Role management examples
@bot.slash_command(description="Create a new role")
async def createrole(
interaction: nextcord.Interaction,
name: str = nextcord.SlashOption(description="Role name"),
color: Optional[str] = nextcord.SlashOption(
description="Role color (hex code, e.g., #FF0000)",
default=None
),
hoist: bool = nextcord.SlashOption(description="Display separately in member list", default=False),
mentionable: bool = nextcord.SlashOption(description="Allow anyone to mention", default=False)
):
"""Create a new role with specified properties."""
if not interaction.user.guild_permissions.manage_roles:
await interaction.response.send_message(
"❌ You don't have permission to manage roles.",
ephemeral=True
)
return
# Parse color if provided
role_color = nextcord.Color.default()
if color:
try:
# Remove # if present
color_hex = color.lstrip('#')
role_color = nextcord.Color(int(color_hex, 16))
except ValueError:
await interaction.response.send_message(
"❌ Invalid color format. Use hex format like `#FF0000`.",
ephemeral=True
)
return
try:
role = await interaction.guild.create_role(
name=name,
color=role_color,
hoist=hoist,
mentionable=mentionable,
reason=f"Role created by {interaction.user}"
)
embed = nextcord.Embed(
title="Role Created",
description=f"Successfully created role {role.mention}",
color=role.color
)
embed.add_field(name="Name", value=role.name, inline=True)
embed.add_field(name="ID", value=role.id, inline=True)
embed.add_field(name="Position", value=role.position, inline=True)
embed.add_field(name="Color", value=str(role.color), inline=True)
embed.add_field(name="Hoisted", value="Yes" if role.hoist else "No", inline=True)
embed.add_field(name="Mentionable", value="Yes" if role.mentionable else "No", inline=True)
await interaction.response.send_message(embed=embed)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to create roles.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to create role: {e}",
ephemeral=True
)
@bot.slash_command(description="Delete a role")
async def deleterole(
interaction: nextcord.Interaction,
role: nextcord.Role = nextcord.SlashOption(description="Role to delete"),
reason: Optional[str] = nextcord.SlashOption(description="Reason for deletion", default=None)
):
"""Delete a role from the server."""
if not interaction.user.guild_permissions.manage_roles:
await interaction.response.send_message(
"❌ You don't have permission to manage roles.",
ephemeral=True
)
return
# Check if it's the @everyone role
if role.is_default():
await interaction.response.send_message(
"❌ Cannot delete the @everyone role.",
ephemeral=True
)
return
# Check hierarchy
if role.position >= interaction.user.top_role.position and interaction.user != interaction.guild.owner:
await interaction.response.send_message(
"❌ Cannot delete this role (same or higher position than your top role).",
ephemeral=True
)
return
# Check if role is managed
if role.managed:
await interaction.response.send_message(
"❌ Cannot delete managed roles (bot roles, booster roles, etc.).",
ephemeral=True
)
return
role_name = role.name
member_count = len(role.members)
try:
await role.delete(reason=reason or f"Role deleted by {interaction.user}")
embed = nextcord.Embed(
title="Role Deleted",
description=f"Successfully deleted role **{role_name}**",
color=nextcord.Color.red()
)
embed.add_field(name="Members Affected", value=member_count, inline=True)
if reason:
embed.add_field(name="Reason", value=reason, inline=False)
embed.set_footer(text=f"Deleted by {interaction.user}", icon_url=interaction.user.display_avatar.url)
await interaction.response.send_message(embed=embed)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to delete this role.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to delete role: {e}",
ephemeral=True
)
@bot.slash_command(description="Edit role permissions")
async def editroleperms(
interaction: nextcord.Interaction,
role: nextcord.Role = nextcord.SlashOption(description="Role to edit"),
permission: str = nextcord.SlashOption(
description="Permission to toggle",
choices=[
"manage_channels", "manage_guild", "kick_members", "ban_members",
"manage_messages", "send_messages", "add_reactions", "view_channel",
"connect", "speak", "mute_members", "deafen_members", "move_members",
"manage_nicknames", "manage_roles", "administrator"
]
),
value: bool = nextcord.SlashOption(description="Enable or disable the permission")
):
"""Edit permissions for a role."""
if not interaction.user.guild_permissions.manage_roles:
await interaction.response.send_message(
"❌ You don't have permission to manage roles.",
ephemeral=True
)
return
if role.position >= interaction.user.top_role.position and interaction.user != interaction.guild.owner:
await interaction.response.send_message(
"❌ Cannot edit this role (same or higher position than your top role).",
ephemeral=True
)
return
if role.managed:
await interaction.response.send_message(
"❌ Cannot edit managed roles.",
ephemeral=True
)
return
# Get current permissions and update
new_permissions = role.permissions
setattr(new_permissions, permission, value)
try:
await role.edit(
permissions=new_permissions,
reason=f"Permission {permission} {'enabled' if value else 'disabled'} by {interaction.user}"
)
status = "enabled" if value else "disabled"
emoji = "✅" if value else "❌"
await interaction.response.send_message(
f"{emoji} {permission.replace('_', ' ').title()} {status} for {role.mention}.",
ephemeral=True
)
except nextcord.Forbidden:
await interaction.response.send_message(
"❌ I don't have permission to edit this role.",
ephemeral=True
)
except nextcord.HTTPException as e:
await interaction.response.send_message(
f"❌ Failed to edit role: {e}",
ephemeral=True
)
@bot.slash_command(description="List all roles in the server")
async def listroles(interaction: nextcord.Interaction):
"""List all roles in the server with their information."""
roles = sorted(interaction.guild.roles[1:], key=lambda r: r.position, reverse=True) # Skip @everyone
if not roles:
await interaction.response.send_message("This server has no custom roles.")
return
embed = nextcord.Embed(
title=f"Roles in {interaction.guild.name}",
description=f"Total roles: {len(roles)}",
color=nextcord.Color.blue()
)
role_list = []
for i, role in enumerate(roles[:20]): # Limit to first 20 roles
member_count = len(role.members)
managed_indicator = " 🤖" if role.managed else ""
hoisted_indicator = " 📌" if role.hoist else ""
role_info = (
f"{i+1}. {role.mention} "
f"({member_count} member{'s' if member_count != 1 else ''})"
f"{managed_indicator}{hoisted_indicator}"
)
role_list.append(role_info)
embed.add_field(
name="Roles (by hierarchy)",
value="\n".join(role_list) + (f"\n... and {len(roles) - 20} more" if len(roles) > 20 else ""),
inline=False
)
embed.set_footer(text="🤖 = Managed | 📌 = Hoisted")
await interaction.response.send_message(embed=embed)Utility functions and helpers for working with permissions and roles.
# Permission checking utilities
def has_any_permission(member: nextcord.Member, *permissions: str) -> bool:
"""Check if a member has any of the specified permissions.
Parameters
----------
member: nextcord.Member
The member to check permissions for.
*permissions: str
Permission names to check for.
Returns
-------
bool
True if the member has any of the permissions.
"""
member_perms = member.guild_permissions
return any(getattr(member_perms, perm, False) for perm in permissions)
def has_all_permissions(member: nextcord.Member, *permissions: str) -> bool:
"""Check if a member has all of the specified permissions.
Parameters
----------
member: nextcord.Member
The member to check permissions for.
*permissions: str
Permission names to check for.
Returns
-------
bool
True if the member has all of the permissions.
"""
member_perms = member.guild_permissions
return all(getattr(member_perms, perm, False) for perm in permissions)
def get_dangerous_permissions(permissions: nextcord.Permissions) -> List[str]:
"""Get a list of dangerous permissions that a user has.
Parameters
----------
permissions: nextcord.Permissions
The permissions to check.
Returns
-------
List[str]
List of dangerous permission names the user has.
"""
dangerous = [
'administrator', 'manage_guild', 'manage_roles', 'manage_channels',
'kick_members', 'ban_members', 'manage_webhooks', 'manage_emojis_and_stickers'
]
return [perm for perm in dangerous if getattr(permissions, perm, False)]
# Permission audit command
@bot.slash_command(description="Audit dangerous permissions in the server")
async def auditperms(interaction: nextcord.Interaction):
"""Audit members with dangerous permissions."""
if not interaction.user.guild_permissions.administrator:
await interaction.response.send_message(
"❌ You need Administrator permission to use this command.",
ephemeral=True
)
return
await interaction.response.defer() # This might take a moment
dangerous_members = []
for member in interaction.guild.members:
if member.bot:
continue
dangerous_perms = get_dangerous_permissions(member.guild_permissions)
if dangerous_perms:
dangerous_members.append((member, dangerous_perms))
if not dangerous_members:
await interaction.followup.send("✅ No members found with dangerous permissions.")
return
embed = nextcord.Embed(
title="🔍 Permission Audit Results",
description=f"Found {len(dangerous_members)} members with dangerous permissions",
color=nextcord.Color.orange()
)
# Sort by number of dangerous permissions (most dangerous first)
dangerous_members.sort(key=lambda x: len(x[1]), reverse=True)
member_list = []
for member, perms in dangerous_members[:10]: # Show top 10
perm_text = ", ".join(p.replace('_', ' ').title() for p in perms)
member_list.append(f"**{member.display_name}** ({len(perms)}): {perm_text}")
embed.add_field(
name="Members with Dangerous Permissions",
value="\n".join(member_list) + (f"\n... and {len(dangerous_members) - 10} more" if len(dangerous_members) > 10 else ""),
inline=False
)
embed.set_footer(text="Consider reviewing these permissions for security")
await interaction.followup.send(embed=embed)
# Role hierarchy utilities
@bot.slash_command(description="Show role hierarchy")
async def hierarchy(interaction: nextcord.Interaction):
"""Display the server's role hierarchy."""
roles = sorted(interaction.guild.roles, key=lambda r: r.position, reverse=True)
embed = nextcord.Embed(
title=f"Role Hierarchy in {interaction.guild.name}",
description="Roles listed from highest to lowest position",
color=nextcord.Color.blue()
)
hierarchy_text = []
for i, role in enumerate(roles[:15]): # Show top 15 roles
indent = " " * min(i // 3, 3) # Add visual indentation
member_count = len(role.members)
if role.is_default():
role_name = "@everyone"
else:
role_name = role.name
hierarchy_text.append(
f"{indent}{i+1}. **{role_name}** "
f"({member_count} member{'s' if member_count != 1 else ''})"
)
embed.add_field(
name="Hierarchy",
value="\n".join(hierarchy_text) + (f"\n... and {len(roles) - 15} more" if len(roles) > 15 else ""),
inline=False
)
embed.set_footer(text="Higher positions have priority over lower ones")
await interaction.response.send_message(embed=embed)
# Permission comparison utility
@bot.slash_command(description="Compare permissions between two members")
async def compareperms(
interaction: nextcord.Interaction,
member1: nextcord.Member = nextcord.SlashOption(description="First member"),
member2: nextcord.Member = nextcord.SlashOption(description="Second member")
):
"""Compare permissions between two members."""
perms1 = member1.guild_permissions
perms2 = member2.guild_permissions
embed = nextcord.Embed(
title="Permission Comparison",
description=f"Comparing {member1.display_name} vs {member2.display_name}",
color=nextcord.Color.blue()
)
# Get all permission attributes
all_perms = [attr for attr in dir(perms1) if not attr.startswith('_') and isinstance(getattr(perms1, attr), bool)]
# Categorize differences
member1_only = []
member2_only = []
both_have = []
neither_have = []
for perm in all_perms:
has_perm1 = getattr(perms1, perm, False)
has_perm2 = getattr(perms2, perm, False)
perm_display = perm.replace('_', ' ').title()
if has_perm1 and not has_perm2:
member1_only.append(perm_display)
elif has_perm2 and not has_perm1:
member2_only.append(perm_display)
elif has_perm1 and has_perm2:
both_have.append(perm_display)
else:
neither_have.append(perm_display)
if member1_only:
embed.add_field(
name=f"✅ Only {member1.display_name} has",
value=", ".join(member1_only[:10]) + ("..." if len(member1_only) > 10 else ""),
inline=False
)
if member2_only:
embed.add_field(
name=f"✅ Only {member2.display_name} has",
value=", ".join(member2_only[:10]) + ("..." if len(member2_only) > 10 else ""),
inline=False
)
if both_have:
embed.add_field(
name="🤝 Both have",
value=", ".join(both_have[:10]) + ("..." if len(both_have) > 10 else ""),
inline=False
)
await interaction.response.send_message(embed=embed)This comprehensive documentation covers all aspects of nextcord's permission and role system, providing developers with the tools needed to implement sophisticated access control in their Discord bots.
Install with Tessl CLI
npx tessl i tessl/pypi-nextcord