Skip to main content
Permissions are always written by name, like 'BanMembers': your editor completes them and refuses a typo. Nothing here sends a request: everything is computed from what the bot knows.
To require permissions before a command runs, declare them in the file of the command: see Commands. What ChapterJS answers when the bot itself lacks a permission is in Errors.

Where permissions come from

To write permissions, pass names to guild.createRole(), role.edit() (RoleCreateOptions, RoleEditOptions) and channel.setPermissions().

How they are computed

The computation follows the permission rules of Discord, in four steps:
  1. In the server. The owner can do everything. Otherwise a member has what the @everyone role allows, plus what each of their roles allows; a member with Administrator can do everything.
  2. In a channel. The overwrites of the channel change that: first the one for @everyone, then the ones for the roles of the member combined, then the one for the member themselves. Each one removes what it denies, then adds what it allows. An administrator is never affected by overwrites.
  3. What follows. A member who can’t ViewChannel can do nothing in it. A member who can’t SendMessages can’t MentionEveryone, SendTtsMessages, AttachFiles or EmbedLinks either.
  4. Timed out. A timed out member only keeps ViewChannel and ReadMessageHistory, unless they are an administrator.
member.permissions applies steps 1 and 4; member.permissionsIn(channel) and channel.permissionsFor(member) apply all four. A thread uses the permissions of the channel it is in.

Permissions

A set of permissions that never changes: every operation returns a new set. Discord serializes permissions as text because they don’t fit in a regular number.

Properties

bigint
required
The permissions as one number, each bit being a permission.

constructor

Builds a set from a name, a list of names, bits, another set, or the text Discord uses ('2048'). Without an argument, the set is empty. A name that is not a permission throws a TypeError:

has()

Whether every given permission is in the set. An administrator has every permission, unless { checkAdmin: false } is passed.

any()

Whether at least one of the given permissions is in the set.

missing()

The given permissions that are not in the set, by name.

add()

A new set with the given permissions added.

remove()

A new set without the given permissions.

toArray()

The names of the permissions in the set, in the order of the docs.

toString()

The text Discord expects in a request.

toJSON()

The text Discord expects in a request.
has(), any() and missing() answer for an administrator as if they had everything. Pass { checkAdmin: false } to has() or any() to check the exact bit.
Discord documentation

PermissionResolvable

A permission, or several: by name, as bits, or as a set.
Every method of Permissions, and every option that takes permissions, accepts one. Something else than a name, a bigint, a set or a list of those throws a TypeError:

PermissionName

The name of one permission: a key of PermissionFlags, as listed below.
Discord documentation

PermissionFlags

The bit of every permission, by name: PermissionFlags.BanMembers is 4n (1n << 2n). It is what PermissionName is made of, and what bits is read against.
You rarely need it: names do the same, readably. Use it when you work with the raw bits of Discord, for example to combine them with | or to compare with a number from elsewhere. Discord documentation

The hierarchy

Having a permission is not always enough: a member can only kick, ban, rename or give roles to members whose highest role is below their own. member.isHigherThan(other) and role.isHigherThan(other) answer that. The same applies to your bot: its highest role must be above the member it moderates. Discord documentation