Pular para o conteúdo principal

Permissões

Permissão no Concord é um inteiro de 23 bits. Cada bit é uma autorização; o valor inteiro é o conjunto. O SDK espelha exatamente os bits de hub::perm do servidor — se um dia divergirem, o servidor está certo.

A tabela​

BitNomeDecimalAutoriza
1 << 0ADMIN1Tudo. Implica todos os outros bits
1 << 1MANAGE_SERVER2Editar nome, descrição, banner, categoria, verificação
1 << 2MANAGE_CHANNELS4Criar, editar e apagar canais
1 << 3MANAGE_ROLES8Criar, editar e apagar cargos; atribuir cargos
1 << 4KICK16Expulsar do servidor (pode voltar com convite)
1 << 5BAN32Banir e desbanir
1 << 6MANAGE_MESSAGES64Apagar e fixar mensagem de outra pessoa
1 << 7CREATE_INVITE128Gerar convite
1 << 8MENTION_EVERYONE256Usar @everyone, @todos, @aqui, @here
1 << 9SEND_MESSAGES512Escrever em canal de texto
1 << 10ATTACH_FILES1024Anexar arquivo
1 << 11CREATE_THREADS2048Abrir tópico
1 << 12ADD_REACTIONS4096Reagir
1 << 13CONNECT8192Entrar em canal de voz
1 << 14SPEAK16384Publicar microfone
1 << 15VIDEO32768Publicar câmera e tela
1 << 16MUTE_MEMBERS65536Silenciar e desconectar da voz
1 << 17VIEW_AUDIT131072Ler o log de auditoria
1 << 18CREATE_ROOMS262144Criar sala temporária de voz
1 << 19VIEW_CHANNEL524288Ver o canal
1 << 20MANAGE_EVENTS1048576Criar e editar eventos
1 << 21MODERATE_MEMBERS2097152Moderar membros
1 << 22MANAGE_APPS4194304Instalar e revogar bots no servidor

Duas constantes derivadas:

ConstanteValorO que é
ALL_PERMISSIONS8388607(1 << 23) - 1, todos os bits
EVERYONE_DEFAULT_PERMISSIONS327552O que o @everyone recebe num servidor novo

O padrão do @everyone é CREATE_INVITE | MENTION_EVERYONE | SEND_MESSAGES | ATTACH_FILES | CREATE_THREADS | ADD_REACTIONS | CONNECT | SPEAK | VIDEO | CREATE_ROOMS — ou seja, participar plenamente, sem moderar nada.

Como o servidor resolve​

A ordem importa, e é exatamente esta — a mesma de hub::perms_of:

  1. É o dono do servidor? Então tudo, e para aqui.
  2. Não é membro? Então zero, e para aqui.
  3. Senão: everyone_perms | VIEW_CHANNEL | (soma das permissões dos cargos).
  4. Deu ADMIN no passo 3? Então tudo.

Dois detalhes que surpreendem:

  • VIEW_CHANNEL é dado a todo membro, independentemente de cargo. Visibilidade de canal no Concord não é negada por bit.
  • Não existe permissão negativa. Cargos somam, nunca subtraem. Se um bit precisa ser tirado de alguém, ele não pode estar no @everyone nem em nenhum cargo da pessoa.

Checando​

A forma curta​

import { PermissionFlags } from 'concord.js';

if (!member.hasPermission(PermissionFlags.BAN)) return;

Vários bits de uma vez — exige todos:

if (!member.hasPermission([PermissionFlags.CONNECT, PermissionFlags.SPEAK])) return;

O nome em texto também resolve, o que deixa a leitura mais limpa:

if (!member.hasPermission(['MANAGE_MESSAGES'])) return;

As minhas, as de alguém, as do canal​

// As minhas, resolvidas pelo próprio servidor (`my_perms` do snapshot).
const minhas = server.myPermissions;

// De qualquer membro, resolvidas localmente com a mesma regra do servidor.
const dele = server.permissionsFor(userId);

// Neste canal. Hoje vêm de `my_perms`: o Concord não tem override por canal.
const aqui = channel.permissions;

A classe Permissions​

import { Permissions, PermissionFlags } from 'concord.js';

const p = new Permissions(PermissionFlags.SEND_MESSAGES | PermissionFlags.ADD_REACTIONS);

p.has(PermissionFlags.SEND_MESSAGES); // true
p.has(PermissionFlags.BAN); // false
p.toArray(); // ['SEND_MESSAGES', 'ADD_REACTIONS']
p.missing([PermissionFlags.BAN, PermissionFlags.KICK]); // ['BAN', 'KICK']
p.add(PermissionFlags.BAN).bits; // novo Permissions, imutável
Number(p); // o inteiro, via valueOf()
checkAdmin

has() considera ADMIN como "tem tudo", porque é assim que o servidor decide. Para perguntar pelo bit literal — ao desenhar uma tela de edição de cargo, por exemplo — passe { checkAdmin: false }.

missing dá a mensagem de erro​

Em vez de dizer "sem permissão", diga qual falta:

const faltando = new Permissions(ctx.member!.permissions.bits)
.missing([PermissionFlags.MANAGE_MESSAGES, PermissionFlags.VIEW_AUDIT]);

if (faltando.length) {
await ctx.reply(`Faltam estas permissões: ${faltando.join(', ')}`);
return;
}

No decorator​

O caminho mais curto é não checar no corpo do método:

@SlashCommand({
name: 'banir',
description: 'Bane alguém do servidor',
options: [{ name: 'quem', description: 'A pessoa', type: 'user', required: true }],
permissions: [PermissionFlags.BAN],
})
async banir(@Ctx() [ctx]: SlashCommandContext, @Opt('quem') quem: User) {
await ctx.server!.ban(quem.id, 'pedido por comando');
}

Os permissions do decorator checam quem chamou. As permissões do bot são outra coisa — e o servidor as checa de todo jeito, devolvendo um frame error que o SDK transforma em GatewayError.

Resolvendo na mão​

Para calcular permissão fora de um Member — num cache próprio, ou para simular:

import { resolveMemberPermissions, Permissions } from 'concord.js';

const bits = resolveMemberPermissions({
ownerId: server.ownerId,
userId: 7,
memberIds: server.members.map((m) => m.id),
everyonePerms: server.everyonePermissions.bits,
roles: server.roles.toArray().map((r) => r.raw),
memberRoleIds: [3, 5],
});

new Permissions(bits).toArray();

A função segue a ordem do servidor, incluindo os casos de dono e de não-membro.

O que o bot precisa​

Um mínimo útil por tipo de bot:

BotBits
Só responde no chatVIEW_CHANNEL, SEND_MESSAGES
Reage e abre tópico+ ADD_REACTIONS, CREATE_THREADS
Manda arquivo+ ATTACH_FILES
Música+ CONNECT, SPEAK
Câmera ou tela+ VIDEO
Moderação+ MANAGE_MESSAGES, KICK, BAN, MODERATE_MEMBERS

Em decimal, o cargo de um bot de música seria VIEW_CHANNEL | SEND_MESSAGES | ADD_REACTIONS | CONNECT | SPEAK = 553472.

Não dê ADMIN ao bot

ADMIN é 1 bit e vale 23. Um bot com ADMIN que seja comprometido — ou que tenha um comando com bug — apaga canais. Dê exatamente os bits da tabela acima.