Intents & Permissions
Automatic intent inference from events and permission aggregation from commands.
The plugin automatically infers which gateway intents your bot needs based on registered events, and aggregates permissions from command configurations.
Intent inference
When your bot starts, the plugin checks which events you've registered and warns about any missing intents. For example, if you have a messageCreate handler but haven't enabled GuildMessages, you'll see a warning.
How it works
Each Discord.js event maps to one or more required intents. The plugin maintains this mapping internally and checks your configured intents against it:
| Event | Required Intent(s) |
|---|---|
messageCreate | GuildMessages, DirectMessages |
guildMemberAdd | GuildMembers (privileged) |
presenceUpdate | GuildPresences (privileged) |
messageReactionAdd | GuildMessageReactions |
voiceStateUpdate | GuildVoiceStates |
guildCreate | Guilds |
channelCreate | Guilds |
threadCreate | Guilds |
typingStart | GuildMessageTyping |
autoModerationRuleCreate | AutoModerationConfiguration |
autoModerationActionExecution | AutoModerationExecution |
guildScheduledEventCreate | GuildScheduledEvents |
This is a representative sample. The full mapping covers 42+ events. See the exported REQUIRED_INTENTS constant for the complete list.
For events that accept multiple intents (like messageCreate), having at least one is sufficient.
Configuring intents
Set intents explicitly via clientOptions.intents:
import { GatewayIntentBits } from 'discord.js'
import type { DiscordConfig } from '@robojs/discordjs'
export default {
clientOptions: {
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent
]
}
} satisfies DiscordConfigimport { GatewayIntentBits } from 'discord.js'
export default {
clientOptions: {
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.MessageContent
]
}
}Prefix command intents
Prefix commands require three specific intents to function: GuildMessages, DirectMessages, and MessageContent. These are automatically inferred at build time when prefix command files are detected in src/prefixCommands/.
At runtime, checkPrefixIntents() validates that all three intents are configured and logs warnings for any that are missing.
MessageContent is a privileged intent that must be enabled in the Discord Developer Portal. Without it, your bot cannot read message content and prefix commands will not work.
Privileged intents
Some intents require explicit approval in the Discord Developer Portal:
| Intent | Portal Toggle | Events |
|---|---|---|
GuildMembers | Server Members Intent | guildMemberAdd, guildMemberUpdate, guildMemberRemove, threadMembersUpdate |
GuildPresences | Presence Intent | presenceUpdate |
MessageContent | Message Content Intent | Access to message content in messageCreate, messageUpdate. Required for prefix commands. |
Privileged intents must be enabled in both your code and the Discord Developer Portal. Bots in 100+ servers also need Discord approval.
Permission aggregation
The plugin aggregates defaultMemberPermissions from all your commands and context menus for use with the robo invite CLI command and permission utilities.
Setting permissions on commands
import type { CommandConfig } from '@robojs/discordjs'
export const config: CommandConfig = {
description: 'Ban a user',
defaultMemberPermissions: 'BanMembers'
}Permission utilities
The plugin exports utilities for working with permissions programmatically:
import {
getPermissionNames,
hasRequiredPermissions,
getMissingPermissions,
combinePermissions,
setGuildPermissionOverride
} from '@robojs/discordjs'getPermissionNames(permissions)
Convert a permission bitfield to an array of permission names:
import { getPermissionNames } from '@robojs/discordjs'
const names = getPermissionNames(268435456n)
// ['ManageRoles']hasRequiredPermissions(userPermissions, requiredPermissions)
Check if a user has all required permissions:
import { hasRequiredPermissions } from '@robojs/discordjs'
const canBan = hasRequiredPermissions(userBits, requiredBits)getMissingPermissions(userPermissions, requiredPermissions)
Get the names of permissions a user is missing:
import { getMissingPermissions } from '@robojs/discordjs'
const missing = getMissingPermissions(userBits, requiredBits)
// ['BanMembers', 'KickMembers']combinePermissions(...permissions)
Combine multiple permission bitfields:
import { combinePermissions, PERMISSION_FLAGS } from '@robojs/discordjs'
const combined = combinePermissions(
PERMISSION_FLAGS.BanMembers,
PERMISSION_FLAGS.KickMembers
)setGuildPermissionOverride(permissions, commandKey, guildId, permissionBits)
Set guild-specific permission overrides for a command:
import { aggregateCommandPermissions, setGuildPermissionOverride, PERMISSION_FLAGS } from '@robojs/discordjs'
const permissions = aggregateCommandPermissions(commands)
setGuildPermissionOverride(permissions, 'ban', '123456789', PERMISSION_FLAGS.Administrator)aggregateContextPermissions(contextMenus)
Works the same way as aggregateCommandPermissions but for context menu commands. Accepts a record of context menu entries and returns aggregated permissions for each:
import { aggregateContextPermissions } from '@robojs/discordjs'
const contextPermissions = aggregateContextPermissions(contextMenus)getEffectivePermissions(permissions, commandKey, guildId?)
Resolve the effective permissions for a command, accounting for guild-specific overrides. Returns the guild override if one exists, otherwise the default permissions:
import { aggregateCommandPermissions, getEffectivePermissions } from '@robojs/discordjs'
const permissions = aggregateCommandPermissions(commands)
// Get default permissions for 'ban'
const defaultPerms = getEffectivePermissions(permissions, 'ban')
// Get guild-specific permissions (falls back to default if no override)
const guildPerms = getEffectivePermissions(permissions, 'ban', '123456789')Intent validation
Validate intents programmatically using the exported utilities:
import { validateIntents, inferIntents, getIntentNames } from '@robojs/discordjs'
// Validate configured intents against event requirements
const result = validateIntents(configuredIntentsBitfield, ['messageCreate', 'guildMemberAdd'])
if (!result.valid) {
console.log('Events missing intents:', result.missing)
console.log('Suggestions:', result.suggestions)
}
// Infer required intents from event names
const required = inferIntents(['messageCreate', 'guildMemberAdd'])
console.log('Required intents:', getIntentNames(required))checkIntents(client, events)
Check a live Discord.js Client against registered event handlers and log warnings for any missing intents. This is called automatically at startup, but you can also invoke it manually:
import { checkIntents } from '@robojs/discordjs'
// client is your Discord.js Client instance
// events is a record mapping event names to their handler arrays
checkIntents(client, events)
// Logs warnings for any events whose required intents are not configuredcheckPrefixIntents(client)
Check that the client has the required intents for prefix commands (GuildMessages, DirectMessages, MessageContent). Called automatically at startup when prefix commands are registered, but can also be invoked manually:
import { checkPrefixIntents } from '@robojs/discordjs'
checkPrefixIntents(client)
// Logs warnings for any missing prefix command intentsREQUIRED_INTENTS
An exported constant that maps Discord event names to their required GatewayIntentBits. Events that accept multiple intents store them as an array:
import { REQUIRED_INTENTS } from '@robojs/discordjs'
// Single intent
REQUIRED_INTENTS.guildCreate // GatewayIntentBits.Guilds
// Multiple possible intents
REQUIRED_INTENTS.messageCreate // [GatewayIntentBits.GuildMessages, GatewayIntentBits.DirectMessages]This is the same mapping used internally by checkIntents, validateIntents, and inferIntents.
robo invite
Generate a bot invite link with the correct permissions:
npx robo inviteThis aggregates defaultMemberPermissions from all your commands and context menus to generate an invite URL with the minimum required permissions.
This is experimental and may not generate the correct permissions. If you have issues, use the Discord Developer Portal to generate an invite URL manually.
