Skip to content

Permissions ​

BloumeChat utilise un système de bitmask BigInt pour les permissions de rôle, codé dès le départ en BigInt pour ne jamais être limité aux 32 bits d'un entier standard (number en JavaScript perd sa précision au-delà de 2^53, et un système de permissions grandit vite au-delà de 32 flags). Les littéraux BigInt (1n) sont du JavaScript standard (ES2020) — rien de spécifique à TypeScript ici.

Les flags disponibles ​

Chaque flag est une puissance de 2 (1n << Nn), ce qui permet de les combiner sans collision avec l'opérateur | et de tester leur présence avec &.

FlagValeurCatégorieDescription
MANAGE_SERVER1n << 0nServeurModifier les paramètres généraux du serveur.
MANAGE_ROLES1n << 1nServeurCréer, modifier, supprimer des rôles.
MANAGE_CHANNELS1n << 2nServeurCréer, modifier, supprimer des salons et catégories.
VIEW_AUDIT_LOG1n << 3nServeurConsulter le journal d'audit.
MANAGE_INVITES1n << 4nServeurCréer et révoquer des invitations.
VIEW_MEMBERS1n << 5nServeurVoir la liste des membres.
KICK_MEMBERS1n << 6nModérationExpulser un membre.
BAN_MEMBERS1n << 7nModérationBannir/débannir un membre.
MANAGE_MESSAGES1n << 8nModérationSupprimer les messages d'autres membres.
VIEW_CHANNELS1n << 9nCommunicationVoir un salon.
SEND_MESSAGES1n << 10nCommunicationEnvoyer des messages.
UPLOAD_FILES1n << 11nCommunicationEnvoyer des pièces jointes.
MENTION_EVERYONE1n << 12nCommunicationUtiliser @everyone / @here.
CONNECT1n << 13nVocalRejoindre un salon vocal.
SPEAK1n << 14nVocalParler dans un salon vocal.
MUTE_MEMBERS1n << 15nVocalRendre muet un membre en vocal.
DEAFEN_MEMBERS1n << 16nVocalRendre sourd un membre en vocal.
MOVE_MEMBERS1n << 17nVocalDéplacer un membre entre salons vocaux.
PIN_MESSAGE1n << 18nChatÉpingler un message.
ADD_REACTION1n << 19nChatAjouter une réaction.
MANAGE_APPLICATIONS1n << 20nApplicationsGérer les bots/applications installés sur le serveur.
CREATE_INVITE1n << 21nServeurCréer des invitations — c'est aussi la permission que le bot d'une application doit posséder sur le serveur pour que le scope OAuth2 guilds.join puisse y ajouter un utilisateur, voir OAuth2 — Se connecter avec BloumeChat.
ADMINISTRATOR1n << 31nGlobalBypasse toutes les vérifications de permission, y compris les futures.
ts
import { PermissionFlags } from "bloumechat";

PermissionFlags.MANAGE_SERVER;    // 1n << 0n
PermissionFlags.BAN_MEMBERS;      // 1n << 7n
PermissionFlags.SEND_MESSAGES;    // 1n << 10n
PermissionFlags.ADMINISTRATOR;    // 1n << 31n — bypasse toutes les vérifications
js
const { PermissionFlags } = require("bloumechat");

PermissionFlags.MANAGE_SERVER;    // 1n << 0n
PermissionFlags.BAN_MEMBERS;      // 1n << 7n
PermissionFlags.SEND_MESSAGES;    // 1n << 10n
PermissionFlags.ADMINISTRATOR;    // 1n << 31n — bypasse toutes les vérifications

Type PermissionFlag

TypeScript exporte aussi le type union PermissionFlag (typeof PermissionFlags[keyof typeof PermissionFlags]), pratique pour typer un paramètre qui accepte n'importe quel flag individuel :

ts
import type { PermissionFlag } from "bloumechat";

function describe(flag: PermissionFlag) { /* ... */ }

Vérifier une permission ​

Chaque Member et chaque Role expose hasPermission(permission: bigint): boolean :

ts
const member = await client.members.fetch(guild.id, userId);

if (member.hasPermission(PermissionFlags.BAN_MEMBERS)) {
  await member.ban({ reason: "Spam répété" });
} else {
  await message.reply("Vous n'avez pas la permission de bannir des membres.");
}
js
const member = await client.members.fetch(guild.id, userId);

if (member.hasPermission(PermissionFlags.BAN_MEMBERS)) {
  await member.ban({ reason: "Spam répété" });
} else {
  await message.reply("Vous n'avez pas la permission de bannir des membres.");
}

Member.hasPermission() vs Role.hasPermission() ​

Les deux méthodes ont une sémantique légèrement différente à connaître :

  • Member.hasPermission(flag) teste le résultat du getter Member.permissions (union de tous les rôles du membre, voir ci-dessous) — il gère déjà le cas ADMINISTRATOR en amont via permissions.
  • Role.hasPermission(flag) teste uniquement le bitmask propre à ce rôle, mais court-circuite aussi si ce rôle seul possède ADMINISTRATOR.
ts
// Vérifier si un rôle spécifique (pas le membre entier) donne le droit de bannir
const modRole = guild.roles.cache.find((r) => r.name === "Modérateur");
if (modRole?.hasPermission(PermissionFlags.BAN_MEMBERS)) {
  console.log("Le rôle Modérateur permet de bannir.");
}

Member.permissions — calcul détaillé ​

Member.permissions est un getter (bigint) qui recalcule l'union des permissions de tous les rôles du membre à chaque accès, avec deux raccourcis appliqués dans cet ordre :

  1. Si guild.ownerId === member.user.id, le propriétaire du serveur reçoit implicitement ALL_PERMISSIONS — aucun calcul de rôle n'est effectué.
  2. Sinon, les permissions de chaque rôle en cache sur le membre sont combinées avec |. Si le résultat contient ADMINISTRATOR, le getter retourne directement ALL_PERMISSIONS.
  3. Si le serveur (guild) n'est pas trouvé dans client.guilds.cache au moment de l'appel, le getter retourne 0n (aucune permission) — assurez-vous que le serveur est chargé avant de vous fier à ce calcul.
ts
const member = await client.members.fetch(guild.id, userId);
console.log(member.permissions); // bigint — union des rôles, ou ALL_PERMISSIONS si owner/admin

Overrides de salon/catégorie

Le calcul de Member.permissions reflète les permissions de rôle, pas les overrides par salon/catégorie (gérés côté serveur et non exposés directement par le SDK aujourd'hui). Pour une vérification fine par salon, obtenez d'abord les permissions de rôle avec member.permissions/hasPermission(), puis croisez avec les métadonnées du salon concerné si votre bot en a besoin.

Combiner des permissions ​

Les flags sont des BigInt, combinables avec les opérateurs bitwise standards : | (union / OR), & (intersection / AND), ~ (complément / NOT).

ts
const modPerms = PermissionFlags.KICK_MEMBERS | PermissionFlags.BAN_MEMBERS | PermissionFlags.MANAGE_MESSAGES;

await guild.createRole({
  name: "Modérateur",
  color: "#5e72e4",
  permissions: modPerms,
  hoist: true,
});
js
const modPerms = PermissionFlags.KICK_MEMBERS | PermissionFlags.BAN_MEMBERS | PermissionFlags.MANAGE_MESSAGES;

await guild.createRole({
  name: "Modérateur",
  color: "#5e72e4",
  permissions: modPerms,
  hoist: true,
});

Retirer un flag d'un ensemble existant ​

Pour retirer une permission précise d'un bitmask sans toucher aux autres, combinez & avec le complément ~ :

ts
// Retire MANAGE_MESSAGES tout en gardant le reste des permissions du rôle
const updatedPerms = role.permissions & ~PermissionFlags.MANAGE_MESSAGES;
await role.edit({ permissions: updatedPerms });
js
// Retire MANAGE_MESSAGES tout en gardant le reste des permissions du rôle
const updatedPerms = role.permissions & ~PermissionFlags.MANAGE_MESSAGES;
await role.edit({ permissions: updatedPerms });

Tester plusieurs flags à la fois ​

hasPermission() n'accepte qu'un seul bitmask à la fois, mais rien n'empêche de lui passer une combinaison déjà unie avec | — dans ce cas elle exige que tous les flags combinés soient présents (comparaison stricte ===) :

ts
const canModerate = member.hasPermission(PermissionFlags.KICK_MEMBERS | PermissionFlags.BAN_MEMBERS);
// true seulement si le membre a KICK_MEMBERS **et** BAN_MEMBERS

Pour un test « au moins un de ces flags », combinez manuellement :

ts
const hasAnyModPerm =
  member.hasPermission(PermissionFlags.KICK_MEMBERS) ||
  member.hasPermission(PermissionFlags.BAN_MEMBERS);

DEFAULT_PERMISSIONS et ALL_PERMISSIONS ​

Deux constantes prêtes à l'emploi, calculées une fois au chargement du module :

ConstanteValeurUsage typique
DEFAULT_PERMISSIONSVIEW_CHANNELS | SEND_MESSAGES | UPLOAD_FILES | ADD_REACTION | CONNECT | SPEAKPermissions de base à donner à un rôle « membre » standard.
ALL_PERMISSIONSUnion de tous les flags de PermissionFlags (calculée dynamiquement via Object.values(...).reduce(...))Valeur retournée implicitement pour le propriétaire du serveur et pour tout détenteur d'ADMINISTRATOR.
ts
import { DEFAULT_PERMISSIONS, ALL_PERMISSIONS, PermissionFlags } from "bloumechat";

await guild.createRole({
  name: "Membre",
  permissions: DEFAULT_PERMISSIONS,
});

// ALL_PERMISSIONS contient forcément ADMINISTRATOR
console.log((ALL_PERMISSIONS & PermissionFlags.ADMINISTRATOR) === PermissionFlags.ADMINISTRATOR); // true
js
const { DEFAULT_PERMISSIONS, ALL_PERMISSIONS, PermissionFlags } = require("bloumechat");

await guild.createRole({
  name: "Membre",
  permissions: DEFAULT_PERMISSIONS,
});

// ALL_PERMISSIONS contient forcément ADMINISTRATOR
console.log((ALL_PERMISSIONS & PermissionFlags.ADMINISTRATOR) === PermissionFlags.ADMINISTRATOR); // true

Pièges courants ​

BigInt ne se mélange pas avec number

1n + 1 lève une TypeError: Cannot mix BigInt and other types. Restez en BigInt de bout en bout lorsque vous manipulez des permissions (0n, 1n, etc.) — n'utilisez Number(...) que pour l'affichage, jamais pour recombiner des flags.

JSON.stringify ne sérialise pas les BigInt

Si vous devez transmettre un bitmask de permissions dans du JSON (logs, webhook externe…), convertissez-le explicitement en chaîne : role.permissions.toString(). C'est d'ailleurs ce que fait Role.edit() en interne avant d'envoyer la requête à l'API.

Voir aussi ​

  • Role — structure complète avec edit(), delete(), et le détail de hasPermission().
  • Member — kick(), ban(), addRole(), removeRole(), et le getter permissions.
  • RoleManager — créer/lister les rôles d'un serveur.
  • Permissions (bitmask) — Référence API — export brut de PermissionFlags, DEFAULT_PERMISSIONS, ALL_PERMISSIONS.

SDK publié sous licence ISC.