Skip to main content

Privileges

Another common use case when making commands is to be able to restrict access to some commands that should not be used by everyone. The Privilege API provides a way to conveniently implement these kind of restrictions.

info

The permission system proposed by Discord is currently not yet supported by Discord4J. As such, using this Privilege API is the recommended approach until Discord native permissions are fully supported. There is no plan to deprecate this feature for now.

The Privilege interface

Privilege is a functional interface that is in charge of checking if access to the command is granted for a specific context. If granted, the abstract method of the interface returns a Mono that completes empty, which signals that the command can be run normally. If not granted, the returned Mono is expected to emit PrivilegeException (or a subclass of this exception), possibly carrying details on the reason of the failure. In this case, the command execution will be cancelled.

The InteractionListener superinterface, which is extended by ChatInputInteractionListener, UserInteractionListener, MessageInteractionListener and ComponentInteractionListener, provides a privilege() method that can be overriden in your command implementations.

An instance of this interface can be provided via a lambda expression. The example below defines a privilege which only grants users whose username starts with "A":

@Override
public Privilege privilege() {
return ctx -> Mono.justOrEmpty(ctx.event().getMessage().getAuthor())
.filter(author -> author.getUsername().startsWith("A"))
.switchIfEmpty(Mono.error(PrivilegeException::new))
.then();
}
info

Handling PrivilegeException (for example to display a user-friendly message) is documented on the Handling Errors page.

Privilege presets

In most cases, checking if access to a command is granted will simply consist of checking if the user has a particular role or a particular permission in the guild. You can use one of the static methods of the Privileges class instead of implementing that yourself:

@Override
public Privilege privilege() {
return Privileges.checkPermissions(perms -> perms.contains(ADMINISTRATOR));
}

Check out the Javadoc for the Privileges class for more presets like this one.

Composing privileges

You can compose several Privilege instances by using the and() and or() methods:

@Override
public Privilege privilege() {
return Privileges.checkRoles(roles -> !roles.isEmpty())
.or(Privileges.guildOwner());
}

This code means "Grant if the user has at least one role OR if they are the owner of the server".