Spraxium logoSpraxium

Execução e Prefixos por Guild

A resolução de prefixos segue uma hierarquia de precedência específica que começa pelas sobrescritas por guild. Aprenda a configurar prefixos globais e por guild, cooldowns e a pipeline de resolução de prefixos.

Precedência na resolução de prefixos

Quando o framework recebe uma mensagem, o PrefixParser verifica se o texto começa com um prefixo reconhecido. A resolução segue uma ordem de precedência estrita: primeiro são verificados os prefixos específicos da guild, depois o prefixo global e, por fim, a menção ao bot, se estiver habilitada. A primeira correspondência vence e as demais opções são ignoradas.

Esse modelo de precedência significa que uma sobrescrita da guild sempre tem prioridade sobre o padrão global. Se uma guild registrou ? como prefixo e a config global usa !, mensagens que começam com ? serão reconhecidas nessa guild, enquanto ! será ignorado. Se não existir sobrescrita por guild, o parser volta para o prefixo global. O prefixo por menção, como em @Bot roll 6, sempre é verificado por último como fallback universal.

A ordem de resolução importa para bots que atendem múltiplas comunidades com convenções diferentes. Uma guild focada em moderação pode preferir . como prefixo porque é discreto e pouco intrusivo, enquanto uma guild gamer pode escolher >> para ganhar visibilidade. O sistema de prefixo por guild permite que cada comunidade defina sua própria convenção sem afetar as demais.

Verificar sobrescritas da guild

O parser chama PrefixGuildManager.getGuildPrefix com o ID da guild vindo da mensagem recebida. Se a guild registrou um ou mais prefixos, o parser testa a mensagem contra cada um deles em ordem. O primeiro prefixo que casa é usado e o parser segue direto para a tokenização. Prefixos de guild podem ser uma única string ou um array de strings.

Verificar prefixo global

Se nenhuma sobrescrita da guild casar, ou se a mensagem vier de DM, o parser testa a mensagem contra o prefixo global definido em PrefixConfig. O prefixo global também aceita arrays, então você pode definir múltiplos prefixos globais como ['!', '?']. Se a mensagem começar com qualquer um dos prefixos globais, a primeira correspondência será usada.

Verificar prefixo por menção

Se mentionPrefix estiver habilitado, que é o padrão, o parser verifica se a mensagem começa com uma menção ao bot como <@BOT_ID>. Isso funciona como um prefixo universal que sempre vale, independentemente da config da guild ou da config global. O prefixo por menção é útil quando as pessoas esquecem o prefixo configurado e precisam de um fallback confiável.

Referência do PrefixConfig

A interface PrefixConfig controla o comportamento global do subsistema de prefixos. Você a passa para definePrefix no arquivo de configuração. Todo campo, exceto prefix, é opcional e possui um valor padrão sensato.

config/prefix.config.ts
import { definePrefix } from '@spraxium/core';
import { loadGuildPrefixes } from './prefix/guild-prefix.provider';

export default definePrefix({
  prefix: '!',
  caseSensitive: false,
  mentionPrefix: true,
  defaultCooldown: 3,
  replyOnNotFound: true,
  guildPrefixProvider: loadGuildPrefixes,
});

Seu arquivo de config deve definir apenas a política global e a hidratação inicial do subsistema de prefixos. Lógica de leitura e escrita de prefixos, auditoria e sincronização deve viver em serviços que injetam PrefixDispatcher. A página API de Prefixos via Serviços mostra essa arquitetura em profundidade para fluxos de produção.

Gerenciando prefixos por guild em runtime

O PrefixGuildManager fica acessível por meio do PrefixDispatcher e oferece uma API completa para ler, gravar e remover sobrescritas de prefixo específicas por guild. As mudanças entram em vigor imediatamente na próxima mensagem recebida, sem necessidade de restart. Isso permite construir comandos administrativos ou integrações com dashboards que atualizam prefixos de forma dinâmica.

Cada entrada de guild armazena o ID da guild, um ou mais prefixos e um registro opcional de metadados. O campo de metadados não é usado pelo framework em si, mas oferece um lugar para guardar contexto, como quem alterou o prefixo e quando isso aconteceu. Isso é útil para logs de auditoria em bots de moderação.

O método loadFromProvider é chamado automaticamente no startup se você definir um guildPrefixProvider na config. Você também pode chamá-lo manualmente para recarregar os prefixos por guild a partir do banco a qualquer momento, por exemplo depois de uma importação em lote ou migração.

Exemplo de mutação de prefixo em runtime

Um padrão comum é construir um comando administrativo que permita a pessoas donas de guild alterar o prefixo por meio de uma message command. O handler injeta PrefixDispatcher para acessar o gerenciador guildPrefixes e persiste a mudança em um banco. A atualização em runtime passa a valer imediatamente nas mensagens seguintes.

import { PrefixArg, PrefixCommand } from '@spraxium/common';

@PrefixCommand({ name: 'set-prefix' })
export class SetPrefixCommand {
  @PrefixArg.String('newPrefix', { minLength: 1, maxLength: 5 })
  build() {}
}

Sistema de cooldown

O PrefixCooldownManager aplica cooldowns por pessoa usuária e por comando. Quando um comando define um valor de cooldown no decorator @PrefixCommand, ou usa o defaultCooldown global da config, o manager rastreia o último timestamp de execução para cada par usuário-comando. Se alguém tentar rodar um comando antes de o cooldown expirar, o framework bloqueia a execução e pode, opcionalmente, responder com o tempo restante.

Cooldowns ficam armazenados em memória e são reiniciados quando o bot dá restart. O método check retorna os segundos restantes, ou zero se o cooldown já tiver expirado, o método set registra uma nova entrada de cooldown e o método clear remove todos os cooldowns rastreados. Na maioria dos bots, o campo cooldown no decorator e a config global defaultCooldown resolvem tudo automaticamente, sem necessidade de chamadas diretas à API.

O campo cooldown definido por comando em @PrefixCommand sobrescreve o defaultCooldown global. Se um comando definir cooldown: 5 e o padrão global for 3, esse comando usará um cooldown de 5 segundos.