LogoRobo.js

Namespace Controllers

Programmatic access to commands, events, context menus, and middleware.

Namespace controllers provide programmatic access to all registered handlers. Use them to list, retrieve, and execute commands and events at runtime -- useful for building admin panels, dynamic help systems, or programmatic event triggering.

Pre-instantiated controllers

Import the controllers directly from the plugin:

import { commands, events, context, middleware, prefixCommands } from '@robojs/discordjs'

These are ready-to-use instances that work with the portal's handler registry.

Commands

The commands controller provides access to all registered slash commands.

commands.list()

Returns an array of all command keys:

import { commands } from '@robojs/discordjs'

const allCommands = commands.list()
// ['ping', 'ban', 'settings view', 'settings update']

commands.get(name)

Retrieves a specific command handler by name:

const handler = await commands.get('ping')
if (handler) {
	// handler is the default export function
}

commands.execute(name, interaction)

Execute a command programmatically:

import type { ChatInputCommandInteraction } from 'discord.js'

await commands.execute('ping', interaction)

Events

The events controller provides access to all registered event handlers.

events.list()

Returns an array of event names that have handlers:

import { events } from '@robojs/discordjs'

const registeredEvents = events.list()
// ['ready', 'messageCreate', 'guildMemberAdd']

events.get(name)

Retrieves all handlers for a specific event:

const handlers = await events.get('messageCreate')
// Array of handler functions

events.emit(name, ...args)

Emit an event programmatically, executing all handlers for that event:

// Trigger all messageCreate handlers
await events.emit('messageCreate', message)

Context menus

The context controller provides access to all registered context menu handlers.

context.list()

Returns an array of all context menu keys:

import { context } from '@robojs/discordjs'

const menus = context.list()
// ['Get Info', 'Pin Message']

context.get(name)

Retrieves a specific context menu handler by name:

const handler = await context.get('Get Info')
if (handler) {
	// handler is the default export function
}

Middleware

The middleware controller provides access to the middleware chain.

middleware.list()

Returns an array of all middleware keys:

import { middleware } from '@robojs/discordjs'

const allMiddleware = middleware.list()
// ['logger', 'rate-limit', 'admin-only']

middleware.chain()

Returns the ordered, enabled middleware chain. Entries are sorted by order (lower first) and filtered to only enabled middleware:

const chain = await middleware.chain()
for (const entry of chain) {
	console.log(`${entry.key} (order: ${entry.order}, enabled: ${entry.enabled})`)
}

Each entry in the chain contains:

Prop

Type

Prefix commands

The prefixCommands controller provides access to all registered prefix command handlers.

prefixCommands.list()

Returns an array of all prefix command keys:

import { prefixCommands } from '@robojs/discordjs'

const allPrefixCommands = prefixCommands.list()
// ['ping', 'ban', 'admin ban', 'admin kick']

prefixCommands.get(name)

Retrieves a specific prefix command handler by name:

const handler = await prefixCommands.get('ping')
if (handler) {
	// handler is the default export function
}

prefixCommands.execute(name, message, args?)

Execute a prefix command programmatically:

import type { Message } from 'discord.js'

await prefixCommands.execute('ping', message)

// With arguments
await prefixCommands.execute('ban', message, ['@user', 'spam'])

Namespace vs per-handler controllers

There are two levels of control:

  • Namespace controllers (e.g., commands, events) operate on all handlers of a given type. Use them to list, retrieve, or execute any registered handler.
  • Per-handler controllers (e.g., portal.discordjs.command('ping')) operate on a single specific handler. Use them to enable/disable, restrict to servers, or adjust metadata for one handler at a time.

Accessing per-handler controllers

Use the portal to get a controller for a specific handler by name:

import { portal } from 'robo.js'

// Get a controller for a specific command
const pingController = portal.discordjs.command('ping')

// Get a controller for a specific event
const messageHandler = portal.discordjs.event('messageCreate')

// Get a controller for a specific context menu
const infoMenuController = portal.discordjs.contextMenu('Get Info')

// Get a controller for a specific middleware
const rateLimitController = portal.discordjs.middlewareItem('rate-limit')

// Get a controller for a specific prefix command
const pingPrefixController = portal.discordjs.prefixCommand('ping')

Each returns the corresponding controller interface documented below.

Per-handler controller interfaces

For individual handler control, the plugin provides controller interfaces accessible through the portal:

CommandController

interface CommandController {
	isEnabled(): boolean
	setEnabled(value: boolean): void
	setServerOnly(serverIds: string | string[]): void
	isEnabledForServer(serverId: string): boolean
	getMetadata(): Record<string, unknown>
}

EventController

interface EventController {
	isEnabled(): boolean
	setEnabled(value: boolean): void
	setServerOnly(serverIds: string | string[]): void
	isEnabledForServer(serverId: string): boolean
}

ContextController

interface ContextController {
	isEnabled(): boolean
	setEnabled(value: boolean): void
	setServerOnly(serverIds: string | string[]): void
	isEnabledForServer(serverId: string): boolean
	getMetadata(): Record<string, unknown>
}

MiddlewareController

interface MiddlewareController {
	isEnabled(): boolean
	setEnabled(value: boolean): void
	getOrder(): number
	setOrder(order: number): void
}

PrefixCommandController

interface PrefixCommandController {
	isEnabled(): boolean
	setEnabled(value: boolean): void
	setServerOnly(serverIds: string | string[]): void
	isEnabledForServer(serverId: string): boolean
	getMetadata(): Record<string, unknown>
}

Use cases

Dynamic command toggling

Disable a specific command at runtime using its per-handler controller:

import { portal } from 'robo.js'

// Disable a specific command handler
const pingController = portal.discordjs.command('ping')
pingController.setEnabled(false)

// Re-enable it later
pingController.setEnabled(true)

Here is a full example of an admin command that toggles any command by name:

src/commands/admin/toggle.ts
import { portal } from 'robo.js'

export const config = {
	description: 'Toggle a command on or off',
	options: [
		{ name: 'command', type: 'string', required: true },
		{ name: 'enabled', type: 'boolean', required: true }
	]
}

export default async (interaction, options) => {
	const controller = portal.discordjs.command(options.command)
	if (!controller) {
		return `Command "${options.command}" not found`
	}

	controller.setEnabled(options.enabled)
	return `Command "/${options.command}" is now ${options.enabled ? 'enabled' : 'disabled'}`
}

Custom help command

Build a dynamic help system using the namespace controller:

src/commands/help.ts
import { commands } from '@robojs/discordjs'

export default () => {
	const allCommands = commands.list()
	return `Available commands:\n${allCommands.map((cmd) => `\`/${cmd}\``).join('\n')}`
}

Programmatic event emission

Trigger event handlers from other parts of your code:

import { events } from '@robojs/discordjs'

// Trigger all handlers for a custom scenario
await events.emit('messageCreate', syntheticMessage)

Next steps

On this page