| D++ (DPP) C++ Discord API Bot Library

Search
Loading...
Searching...
No Matches
Checking Permissions

Of course most people typically iterate over the roles of a member to check for a permission. But there is a helper method for this: dpp::guild::base_permissions retrieves a member's permissions, taking into account role permissions and the server owner.

For total member permissions including channel overwrites use either the dpp::channel::get_user_permissions or dpp::guild::permission_overwrites method. Both do the same under the hood.

They all return a dpp::permission class, which is a wrapper around a permission bitmask with several helpful methods for easier manipulation and checking of permissions. This bitmask contains flags from the dpp::permissions enum.

Demonstration:

dpp::channel* c = dpp::find_channel(some_channel_id);
if (c && c->get_user_permissions(member).can(dpp::p_send_messages)) {
//...
}
dpp::channel
A definition of a discord channel. There are one of these for every channel type except threads....
Definition channel.h:340
dpp::channel::get_user_permissions
permission get_user_permissions(const class user *user) const
Get the overall permissions for a member in this channel, including channel overwrites,...
dpp::permission::can
constexpr bool can(T... values) const noexcept
Check for certain permissions, taking into account administrator privileges. It uses the Bitwise AND ...
Definition permissions.h:369
dpp::find_channel
DPP_EXPORT class channel * find_channel(snowflake id)
dpp::p_send_messages
@ p_send_messages
Allows for sending messages in a channel.
Definition permissions.h:92

### Role Hierarchy

The recommended and correct way to compare for roles in the hierarchy is using the comparison operators (<, >) on the dpp::role objects themselves. Keep in mind that multiple roles can have the same position number. As a result, comparing roles by position alone can lead to subtle bugs when checking for role hierarchy.

For example let's say you have a ban command, and want to make sure that any issuer of the command can only ban members of lower position than their own highest role:

bot.on_interaction_create([](const dpp::interaction_create_t& event) {
dpp::snowflake target_id = std::get<dpp::snowflake>(event.get_parameter("user"));
dpp::guild_member target = event.command.get_resolved_member(target_id);
for (dpp::snowflake issuer_role_id : event.command.member.get_roles()) {
auto issuer_role = dpp::find_role(issuer_role_id);
if (issuer_role == nullptr) continue;
for (dpp::snowflake target_role_id : target.get_roles()) {
auto target_role = dpp::find_role(target_role_id);
if (target_role == nullptr) continue;
if (target_role > issuer_role) {
event.reply("You can't ban someone whose role is higher than yours!");
return;
}
}
}
});
dpp::guild_member
Represents dpp::user membership upon a dpp::guild. This contains the user's nickname,...
Definition guild.h:407
dpp::guild_member::get_roles
const std::vector< dpp::snowflake > & get_roles() const
Get the roles.
dpp::interaction::member
guild_member member
Optional: guild member data for the invoking user, including permissions. Filled when the interaction...
Definition appcommand.h:1068
dpp::snowflake
A container for a 64 bit unsigned value representing many things on discord. This value is known in d...
Definition snowflake.h:54
dpp::find_role
DPP_EXPORT class role * find_role(snowflake id)
dpp::interaction_create_t
Create interaction.
Definition dispatcher.h:505
dpp::interaction_create_t::command
interaction command
command interaction
Definition dispatcher.h:789
dpp::interaction_create_t::get_parameter
virtual command_value get_parameter(const std::string &name) const
Get a slashcommand parameter.

## Permissions in Interaction Events

### Default Command Permissions

Discord's intended way of managing permissions for commands is through "default member permissions". In a nutshell you tell Discord which permissions a user must have to use the command. Discord completely hides the command for members who don't have the required permissions. You set them using dpp::slashcommand::set_default_permissions when creating or updating a command.

The corresponding code to create a command with default permissions would look something like this:

dpp::slashcommand command("ban", "Ban a member", bot.me.id);
command.set_default_permissions(dpp::p_ban_members); // set permissions that are required by default here
command.add_option(dpp::command_option(dpp::co_user, "user", "The user to ban", true));
command.add_option(dpp::command_option(dpp::co_string, "reason", "The reason for banning", true));
bot.global_command_create(command);
dpp::slashcommand
Represents an application command, created by your bot either globally, or on a guild.
Definition appcommand.h:1436
dpp::p_ban_members
@ p_ban_members
Allows banning members.
Definition permissions.h:46
dpp::co_user
@ co_user
A user snowflake id.
Definition appcommand.h:84
dpp::co_string
@ co_string
A string value.
Definition appcommand.h:69
dpp::command_option
Each command option is a command line parameter. It can have a type (see dpp::command_option_type),...
Definition appcommand.h:208

You can set the default member permissions to "0" to disable the command for everyone except admins by default.

For more customization for server owners, they can override these permissions by their own restrictions in the server settings. This is why they are referred to as "default" permissions.

### Checking Permissions on Your Own

When using default permissions you don't necessarily need to check the issuing user for any permissions in the interaction event as Discord handles all that for you. However, if you don't want server admins to be able to override the command restrictions, you can make those permission checks on your own.

To check if a member has certain permissions during interaction events, the easiest way is to use the dpp::interaction::get_resolved_permission function. The resolved list contains associated structures for the command and does not rely on the cache or require any extra API calls. Additionally, the permissions in the resolved set are pre-calculated by Discord and taking into account channel overwrites, roles and admin privileges. So, there's no need to loop through roles or stuff like that.

Let's imagine the following scenario:

You have a ban command and want to make sure the issuer has the ban permission.

bot.on_interaction_create([](const dpp::interaction_create_t& event) {
dpp::permission perms = event.command.get_resolved_permission(event.command.usr.id);
if (!perms.can(dpp::p_ban_members)) {
event.reply("You don't have the required permissions to ban someone!");
return;
}
});
dpp::interaction::usr
user usr
User object for the invoking user.
Definition appcommand.h:1073
dpp::managed::id
snowflake id
Unique ID of object set by Discord. This value contains a timestamp, worker ID, internal server ID,...
Definition managed.h:39
dpp::permission
Represents a permission bitmask (refer to enum dpp::permissions) which are held in an uint64_t.
Definition permissions.h:313

### From Parameters

The resolved set also contains the permissions of members from command parameters.

For example, let's say you want to prohibit people from banning server admins with your ban command.

Get the user ID from the parameters and pass it to the get_resolved_permission method:

bot.on_interaction_create([](const dpp::interaction_create_t& event) {
dpp::snowflake user_id = std::get<dpp::snowflake>(event.get_parameter("user"));
dpp::permission perms = event.command.get_resolved_permission(user_id);
if (perms.has(dpp::p_administrator)) {
event.reply("You can't ban Admins!");
return;
}
});
dpp::permission::has
constexpr bool has(T... values) const noexcept
Check for permission flags set. It uses the Bitwise AND operator.
Definition permissions.h:407
dpp::p_administrator
@ p_administrator
Allows all permissions and bypasses channel permission overwrites.
Definition permissions.h:51

### The Bot's Permissions

You also might want to check if the bot itself has the ban permission before processing the command further. You can access the bot's permissions in the dpp::interaction::app_permissions field.

bot.on_interaction_create([](const dpp::interaction_create_t& event) {
if (!event.command.app_permissions.can(dpp::p_ban_members)) {
event.reply("The bot doesn't have the required permission to ban anyone!");
return;
}
});
dpp::interaction::app_permissions
permission app_permissions
Permissions of the bot in the channel/guild where this command was issued.
Definition appcommand.h:1058

### Things to Keep in Mind

When replying to interactions using dpp::interaction_create_t::reply, you do not need to manually check whether the bot has permission to send messages. A bot always has permissions to reply to an interaction.

D++ Library version 9.0.13 D++ Library version 9.0.12 D++ Library version 9.0.11 D++ Library version 9.0.10 D++ Library version 9.0.9 D++ Library version 9.0.8 D++ Library version 9.0.7 D++ Library version 9.0.6 D++ Library version 9.0.5 D++ Library version 9.0.4 D++ Library version 9.0.3 D++ Library version 9.0.2 D++ Library version 9.0.1 D++ Library version 9.0.0 D++ Library version 1.0.2 D++ Library version 1.0.1 D++ Library version 1.0.0