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 &.
| Flag | Valeur | Catégorie | Description |
|---|---|---|---|
MANAGE_SERVER | 1n << 0n | Serveur | Modifier les paramètres généraux du serveur. |
MANAGE_ROLES | 1n << 1n | Serveur | Créer, modifier, supprimer des rôles. |
MANAGE_CHANNELS | 1n << 2n | Serveur | Créer, modifier, supprimer des salons et catégories. |
VIEW_AUDIT_LOG | 1n << 3n | Serveur | Consulter le journal d'audit. |
MANAGE_INVITES | 1n << 4n | Serveur | Créer et révoquer des invitations. |
VIEW_MEMBERS | 1n << 5n | Serveur | Voir la liste des membres. |
KICK_MEMBERS | 1n << 6n | Modération | Expulser un membre. |
BAN_MEMBERS | 1n << 7n | Modération | Bannir/débannir un membre. |
MANAGE_MESSAGES | 1n << 8n | Modération | Supprimer les messages d'autres membres. |
VIEW_CHANNELS | 1n << 9n | Communication | Voir un salon. |
SEND_MESSAGES | 1n << 10n | Communication | Envoyer des messages. |
UPLOAD_FILES | 1n << 11n | Communication | Envoyer des pièces jointes. |
MENTION_EVERYONE | 1n << 12n | Communication | Utiliser @everyone / @here. |
CONNECT | 1n << 13n | Vocal | Rejoindre un salon vocal. |
SPEAK | 1n << 14n | Vocal | Parler dans un salon vocal. |
MUTE_MEMBERS | 1n << 15n | Vocal | Rendre muet un membre en vocal. |
DEAFEN_MEMBERS | 1n << 16n | Vocal | Rendre sourd un membre en vocal. |
MOVE_MEMBERS | 1n << 17n | Vocal | Déplacer un membre entre salons vocaux. |
PIN_MESSAGE | 1n << 18n | Chat | Épingler un message. |
ADD_REACTION | 1n << 19n | Chat | Ajouter une réaction. |
MANAGE_APPLICATIONS | 1n << 20n | Applications | Gérer les bots/applications installés sur le serveur. |
CREATE_INVITE | 1n << 21n | Serveur | Cré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. |
ADMINISTRATOR | 1n << 31n | Global | Bypasse toutes les vérifications de permission, y compris les futures. |
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érificationsconst { 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érificationsType 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 :
import type { PermissionFlag } from "bloumechat";
function describe(flag: PermissionFlag) { /* ... */ }Vérifier une permission
Chaque Member et chaque Role expose hasPermission(permission: bigint): boolean :
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.");
}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 getterMember.permissions(union de tous les rôles du membre, voir ci-dessous) — il gère déjà le casADMINISTRATORen amont viapermissions.Role.hasPermission(flag)teste uniquement le bitmask propre à ce rôle, mais court-circuite aussi si ce rôle seul possèdeADMINISTRATOR.
// 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 :
- Si
guild.ownerId === member.user.id, le propriétaire du serveur reçoit implicitementALL_PERMISSIONS— aucun calcul de rôle n'est effectué. - Sinon, les permissions de chaque rôle en cache sur le membre sont combinées avec
|. Si le résultat contientADMINISTRATOR, le getter retourne directementALL_PERMISSIONS. - Si le serveur (
guild) n'est pas trouvé dansclient.guilds.cacheau moment de l'appel, le getter retourne0n(aucune permission) — assurez-vous que le serveur est chargé avant de vous fier à ce calcul.
const member = await client.members.fetch(guild.id, userId);
console.log(member.permissions); // bigint — union des rôles, ou ALL_PERMISSIONS si owner/adminOverrides 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).
const modPerms = PermissionFlags.KICK_MEMBERS | PermissionFlags.BAN_MEMBERS | PermissionFlags.MANAGE_MESSAGES;
await guild.createRole({
name: "Modérateur",
color: "#5e72e4",
permissions: modPerms,
hoist: true,
});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 ~ :
// 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 });// 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 ===) :
const canModerate = member.hasPermission(PermissionFlags.KICK_MEMBERS | PermissionFlags.BAN_MEMBERS);
// true seulement si le membre a KICK_MEMBERS **et** BAN_MEMBERSPour un test « au moins un de ces flags », combinez manuellement :
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 :
| Constante | Valeur | Usage typique |
|---|---|---|
DEFAULT_PERMISSIONS | VIEW_CHANNELS | SEND_MESSAGES | UPLOAD_FILES | ADD_REACTION | CONNECT | SPEAK | Permissions de base à donner à un rôle « membre » standard. |
ALL_PERMISSIONS | Union 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. |
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); // trueconst { 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); // truePiè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 dehasPermission(). - Member —
kick(),ban(),addRole(),removeRole(), et le getterpermissions. - RoleManager — créer/lister les rôles d'un serveur.
- Permissions (bitmask) — Référence API — export brut de
PermissionFlags,DEFAULT_PERMISSIONS,ALL_PERMISSIONS.
