Nubis / Guards and middleware
Beheren
Guards and middleware
Checks that run before a handler, code that wraps it, and the order they run in.
De documentatie van Nubis is in het Engels, net als de API van het framework en zijn meldingen.
A guard decides whether a handler runs. Middleware runs around it. Both can be set on the whole bot, on a folder, and on a single command, component, modal or menu.
Built-in guards
| Guard | Passes when |
|---|---|
guildOnly | Used in a server, not in DMs. |
hasPermission(...perms) | The member has all of these permissions. |
botHasPermission(...perms) | The bot has all of these permissions in the channel. |
hasRole(...ids) | The member has at least one of these roles. Ids, or functions that return one. |
invokerOnly | On a component: the user is whoever ran the command that sent it. |
cooldown({ seconds, per }) | The user hasn't used it within seconds. per is user (default), member, channel, guild or global. |
import { command, cooldown, guildOnly, hasPermission } from "nubis";
import { PermissionFlagsBits } from "discord-api-types/v10";
export default command({
description: "Post an announcement",
guards: [
guildOnly,
hasPermission(PermissionFlagsBits.ManageMessages),
cooldown({ seconds: 60 }),
],
run: ({ reply }) => reply("Posted."),
});Put cooldown last: a check that fails earlier shouldn't use up the user's turn. Cooldowns are kept in memory, per process.
Writing a guard
A guard gets the user, member, server and channel, and api. It returns nothing to pass, or deny(message) to stop; the user sees the message, privately.
import { guard } from "nubis";
export const betaTesters = guard(async ({ user, deny }) => {
if (!(await db.isBetaTester(user.id))) {
return deny("This is only open to beta testers for now.");
}
});Middleware
Middleware wraps a handler. Code before await next() runs first; code after runs once the handler has finished, and a handler's error comes out of next().
import { middleware } from "nubis";
export const timing = middleware(async ({ kind, name }, next) => {
const started = performance.now();
try {
await next();
} finally {
console.log(`${kind} ${name}: ${Math.round(performance.now() - started)}ms`);
}
});The context has kind (command, component or modal), name (/config set, or the component's id), and the user, member, server, channel and api.
Order
From the outside in:
- The bot's, from
nubis.config.ts - Each folder's, outermost folder first
- The command's, component's or menu's own
Guards run in that order and stop at the first denial. Middleware nests in that order, so the bot's middleware is outermost.