@discord-nestjs/core
v5.3.14
Published
Core module
Downloads
5,527
Maintainers
Readme
Core module
🧾 Description
NestJS package for discord.js
- 👨🏻💻 Installation
- 📑 Overview
- ▶️ Usage
- 🛠️ Exported providers
- 🗂 Decorators description
- ℹ️ @InjectDiscordClient
- ℹ️ @Command
- ℹ️ @SubCommand
- ℹ️ @On
- ℹ️ @Once
- ℹ️ @ArgNum
- ℹ️ @ArgRange
- ℹ️ @InteractionEvent/@IA
- ℹ️ @InteractionEvent/@MSG
- ℹ️ @Param
- ℹ️ @Choice
- ℹ️ @Channel
- ℹ️ @InteractionEventCollector
- ℹ️ @MessageEventCollector
- ℹ️ @ReactionEventCollector
- ℹ️ @UseCollectors
- ℹ️ @InjectCollector
- ℹ️ @InjectCauseEvent
- ℹ️ @Filter
- ℹ️ @Field
- ℹ️ @TextInputValue
👨🏻💻 Installation
$ npm install @discord-nestjs/core discord.js
Or via yarn
$ yarn add @discord-nestjs/core discord.js
📑 Overview
⚠️Before you start using, set
useDefineForClassFields
totrue
in yourtsconfig.json
.
The module declaration proceeds in the same way as it is done in NestJS by means
creating a dynamic module through the forRootAsync
functions.
token
* - Your discord bot token. You can get herediscordClientOptions
* - Client options from discord.js libraryregisterCommandOptions
- Specific registration of slash commands(If option is not set, global commands will be registered)forGuild
- For which guild to register a slash commandtrigger
- Used in cases where it is necessary to register commands by eventallowFactory
- Based on what criteria will slash commands be registeredremoveCommandsBefore
- Remove mission commands
prefix
- Global command prefixprefixGlobalOptions
- Global options for prefix commandwebhook
- Connecting with webhookwebhookId
* - Webhook idwebhookToken
* - Webhook token
autoLogin
- Calling login function from discord client on application bootstrapfailOnLogin
- Throw an exception if login failed
⚠️Important! For the bot to work correctly, you need to set up intentions in
discordClientOptions
param. More info
Below is an example of creating a dynamic module using the forRootAsync
function
/* app.module.ts */
import { DiscordModule } from '@discord-nestjs/core';
import { Module } from '@nestjs/common';
import { GatewayIntentBits } from 'discord.js';
@Module({
imports: [
DiscordModule.forRootAsync({
useFactory: () => ({
token: 'your-bot-token',
discordClientOptions: {
intents: [GatewayIntentBits.Guilds],
},
}),
}),
],
})
export class AppModule {}
Alternatively, you can use the useClass
syntax
/* app.module.ts */
import { Module } from '@nestjs/common';
import { DiscordConfigService } from './discord-config-service';
import { DiscordModule } from '@discord-nestjs/core';
@Module({
imports: [
DiscordModule.forRootAsync({
useClass: DiscordConfigService,
}),
],
})
export class AppModule {}
You need to implement the DiscordOptionsFactory
interface
/* discord-config.service.ts */
import { Injectable } from '@nestjs/common';
import {
DiscordModuleOption,
DiscordOptionsFactory,
} from '@discord-nestjs/core';
import { GatewayIntentBits } from 'discord.js';
@Injectable()
export class DiscordConfigService implements DiscordOptionsFactory {
createDiscordOptions(): DiscordModuleOption {
return {
token: 'your-bot-token',
discordClientOptions: {
intents: [GatewayIntentBits.Guilds],
},
};
}
}
If you need to inject exported providers outside the AppModule
, use the Discord.forFeature()
import.
For example, you need to get the Discord Client
in your module.
/* bot.module.ts */
import { Module } from '@nestjs/common';
import { DiscordModule } from '@discord-nestjs/core';
import { BotGateway } from './bot.gateway'
@Module({
imports: [DiscordModule.forFeature()],
providers: [BotGateway]
})
export class BotModule {}
/* bot.gateway.ts */
import { Injectable, Logger } from '@nestjs/common';
import { Once, InjectDiscordClient } from '@discord-nestjs/core';
import { Client } from 'discord.js';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
constructor(
@InjectDiscordClient()
private readonly client: Client,
) {}
@Once('ready')
onReady() {
this.logger.log(`Bot ${this.client.user.tag} was started!`);
}
}
▶️ Usage
ℹ️ Creating slash commands
If you install
@angular-devkit/schematics-cli
and @discord-nestjs/schematics , you can run the follow command to create a slash-command bot template:schematics @discord-nestjs/schematics:application --template slash-command
To add a slash command, you need to create a class with @Command
decorator.
The @Handler
decorator will point to the command processing method.
💡 Example
/* playlist.command.ts */
import { Command, Handler } from '@discord-nestjs/core';
import { CommandInteraction } from 'discord.js';
import { Injectable } from '@nestjs/common';
@Command({
name: 'playlist',
description: 'Get current playlist',
})
@Injectable()
export class PlaylistCommand {
@Handler()
onPlaylist(interaction: CommandInteraction): string {
return 'List with music...';
}
}
If your command accepts parameters, you need to create a class with options.
/* registration.dto.ts */
import { Param, Choice, ParamType } from '@discord-nestjs/core';
enum City {
Moscow,
'New York',
Tokyo,
}
export class RegistrationDto {
@Param({ description: 'User name', required: true })
name: string;
@Param({ description: 'User age', required: true, type: ParamType.INTEGER })
age: number;
@Choice(City)
@Param({ description: 'User city', type: ParamType.INTEGER })
city: City;
}
@Param
decorator defines command parameter.@Choice
decorator marks command parameter as dropdown(Acceptsenum
orMap
).@Channel
decorator marks command parameter as channel select.
By default, if
name
is not passed to the decorator parameters, then the name of the marked property will be taken.
If the command parameter is a
string
or aboolean
, then it is not necessary to pass the type. The type will resolve automatically.
To get object with command option you need add @InteractionEvent()
/@IA()
with SlashCommandPipe
.
InteractionEvent
will extract the data from event args and SlashCommandPipe
will convert the data into an object.
You can import
SlashCommandPipe
from common package
💡 Example
/* registration.command.ts */
import {Command, InteractionEvent, Handler} from '@discord-nestjs/core';
import {SlashCommandPipe} from '@discord-nestjs/common';
import {Injectable} from '@nestjs/common';
import {RegistrationDto} from './registration.dto';
@Command({
name: 'reg',
description: 'User registration',
})
@Injectable()
export class BaseInfoCommand {
@Handler()
onRegistration(@InteractionEvent(SlashCommandPipe) options: RegistrationDto): string {
return `User was registered with name: ${options.name}, age ${options.age} and city ${options.city}`;
}
}
Also, you can validate the options using
ValidationPipe
from common package.
Each command must be added to a NestJS module.
/* bot-slash-commands.module.ts */
import { PlaylistCommand } from './playlist.command';
import { BaseInfoCommand } from './registration.command';
import { Module } from '@nestjs/common';
@Module({
providers: [PlaylistCommand, BaseInfoCommand],
})
export class BotSlashCommandsModule {
}
Or you can use https://github.com/fjodor-rybakov/nestjs-dynamic-providers for search files by glob pattern.
/* bot-slash-commands.module.ts */
import { DiscordModule } from '@discord-nestjs/core';
import { Module } from '@nestjs/common';
import { InjectDynamicProviders } from 'nestjs-dynamic-providers';
@InjectDynamicProviders('**/*.command.js')
@Module({})
export class BotSlashCommandsModule {}
And add your BotSlashCommandsModule
to AppModule
.
/* app.module.ts */
import { DiscordModule } from '@discord-nestjs/core';
import { Module } from '@nestjs/common';
import { GatewayIntentBits } from 'discord.js';
import { BotSlashCommandsModule } from './bot-slash-commands.module';
@Module({
imports: [
DiscordModule.forRootAsync({
useFactory: () => ({
token: 'your-bot-token',
discordClientOptions: {
intents: [Intents.FLAGS.GUILDS],
},
}),
}),
BotSlashCommandsModule,
],
})
export class AppModule {}
If your command is more complex, you can add subgroups of commands or subcommands to it.
To do this, you need to add your subgroups and subcommands to the include
option. The include
parameter accepts
list of class types or UseGroup
function, which in turn accepts group parameters and list of subcommands.
⚠️ Remember that if you define a subgroups of commands or subcommands, this will automatically mark your main command unusable. More details in Discord API
💡 Example
/* registration.command.ts */
import { BaseInfoSubCommand } from './sub-commands/base-info-sub-command';
import { EmailSubCommand } from './sub-commands/email-sub-command';
import { NumberSubCommand } from './sub-commands/number-sub-command';
import { Command, UseGroup } from '@discord-nestjs/core';
@Command({
name: 'reg',
description: 'User registration',
include: [
UseGroup(
{ name: 'type', description: 'Registration type' },
NumberSubCommand,
EmailSubCommand,
),
BaseInfoSubCommand,
],
})
export class RegistrationCommand {}
Subcommands are declared similarly to commands and implement the same interfaces.
To do this, you need to create a class, mark it with the SubCommand
decorator and
specify which interface they implement(DiscordCommand
or DiscordTransformedCommand
)
💡 Example
/* email-sub-command.ts */
import {
Handler,
IA,
SubCommand,
} from '@discord-nestjs/core';
import {SlashCommandPipe} from '@discord-nestjs/common';
import {EmailDto} from '../../dto/email.dto';
@SubCommand({name: 'email', description: 'Register by email'})
export class EmailSubCommand {
@Handler()
onEmail(@IA(SlashCommandPipe) dto: EmailDto): string {
return `Success register user: ${dto.email}, ${dto.name}, ${dto.age}, ${dto.city}`;
}
}
/* number-sub-command.ts */
import {
Handler,
IA,
SubCommand,
} from '@discord-nestjs/core';
import {SlashCommandPipe} from '@discord-nestjs/common';
import {NumberDto} from '../../dto/number.dto';
@SubCommand({name: 'number', description: 'Register by phone number'})
export class NumberSubCommand {
@Handler()
onPhoneNumber(@IA(SlashCommandPipe) dto: NumberDto): string {
return `Success register user: ${dto.phoneNumber}, ${dto.name}, ${dto.age}, ${dto.city}`;
}
}
/* base-info-sub-command.ts */
import {Handler, SubCommand} from '@discord-nestjs/core';
import {
CommandInteraction,
InteractionReplyOptions,
MessageEmbed,
} from 'discord.js';
@SubCommand({name: 'base-info', description: 'Base info'})
export class BaseInfoSubCommand {
@Handler()
onBaseInfo(interaction: CommandInteraction): InteractionReplyOptions {
const {user} = interaction;
const embed = new MessageEmbed()
.setImage(user.avatarURL())
.addField('Name', user.username);
return {
embeds: [embed],
};
}
}
All commands and sub-commands must also be added to module providers.
/* bot-slash-commands.module.ts */
import { RegistrationCommand } from './registration.command';
import { BaseInfoSubCommand } from './sub-commands/base-info-sub-command';
import { EmailSubCommand } from './sub-commands/email-sub-command';
import { NumberSubCommand } from './sub-commands/number-sub-command';
import { Module } from '@nestjs/common';
@Module({
providers: [
RegistrationCommand,
NumberSubCommand,
EmailSubCommand,
BaseInfoSubCommand,
],
})
export class BotSlashCommandsModule {
}
ℹ️ UI based commands(Context menu commands)
In addition to slash commands, you can define commands through the context menu.
To do this, you need to explicitly set the command type. (USER
or MESSAGE
)
/* playlist.command.ts */
import {Command, Handler} from '@discord-nestjs/core';
import {ContextMenuInteraction} from 'discord.js';
import {ApplicationCommandTypes} from 'discord.js/typings/enums';
@Command({
name: 'playlist',
type: ApplicationCommandTypes.USER,
})
export class PlaylistCommand {
@Handler()
onPlaylist(interaction: ContextMenuInteraction): string {
return 'Your playlist...';
}
}
ℹ️ Automatic registration of slash commands
Commands are registered automatically if you define them in code. The registerCommandOptions
property responds to the
command registration setting. It works according to the following principle:
registerCommandOptions
- takes an array of objects.If
registerCommandOptions
option is not specified, global commands will be registered by defaultIf
trigger
used in cases where it is necessary to register commands by eventIf
allowFactory
is specified then commands will be registered by condition fromallowFactory
If
forGuild
is specified, then commands for a specific guild will be registeredIf
removeCommandsBefore
is specified, then registered commands that are not in your code will be removed
The trigger
, allowFactory
, forGuild
and removeCommandsBefore
options are combined with each other.
Global commands, unlike guild commands, are cached and updated once per hour. More info.
💡 Example
import { DiscordModule } from '@discord-nestjs/core';
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { GatewayIntentBits, Message } from 'discord.js';
import { BotSlashCommandsModule } from './bot-slash-commands.module';
@Module({
imports: [
DiscordModule.forRootAsync({
imports: [ConfigModule],
useFactory: (configService: ConfigService) => ({
token: configService.get('TOKEN'),
discordClientOptions: {
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages],
},
registerCommandOptions: [
{
forGuild: configService.get('GUILD_ID_WITH_COMMANDS'),
allowFactory: (message: Message) =>
!message.author.bot && message.content === '!deploy',
},
],
}),
inject: [ConfigService],
}),
BotSlashCommandsModule
],
})
export class BotModule {}
ℹ️ Subscribe to event
Subscription to incoming events (hint)
Use the @On
decorator to subscribe to an event. BotGateway
must be added to module providers.
💡 Example
/* bot.gateway.ts */
import { Injectable, Logger } from '@nestjs/common';
import { On, Once, InjectDiscordClient } from '@discord-nestjs/core';
import { Client, Message } from 'discord.js';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
constructor(
@InjectDiscordClient()
private readonly client: Client,
) {}
@Once('ready')
onReady() {
this.logger.log(`Bot ${this.client.user.tag} was started!`);
}
@On('messageCreate')
async onMessage(message: Message): Promise<void> {
if (!message.author.bot) {
await message.reply("I'm watching you");
}
}
}
You can also subscribe to an event once using the @Once
decorator
💡 Example
/* bot.gateway.ts */
import { Injectable, Logger } from '@nestjs/common';
import { Once } from '@discord-nestjs/core';
import { Message } from 'discord.js';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
@Once('ready')
onReady() {
this.logger.log('Bot was started!');
}
}
ℹ️ Prefix commands
If you install
@angular-devkit/schematics-cli
and @discord-nestjs/schematics , you can run the follow command to create a prefix-command bot template:schematics @discord-nestjs/schematics:application --template prefix-command
To create a command with a prefix from the messageCreate
event use the PrefixCommandInterceptor
.
The following code will create a !start
prefix command.
💡 Example
/* bot.gateway.ts */
import {PrefixCommandInterceptor} from '@discord-nestjs/common';
import {
InjectDiscordClient,
On,
Once,
} from '@discord-nestjs/core';
import { Injectable, Logger, UseInterceptors } from '@nestjs/common';
import { Client } from 'discord.js';
import { StartDto } from './dto/start.dto';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
constructor(
@InjectDiscordClient()
private readonly client: Client,
) {}
@Once('ready')
onReady(): void {
this.logger.log(`Bot ${this.client.user.tag} was started!`);
}
@On('messageCreate')
@UseInterceptors(new PrefixCommandInterceptor('start'))
async onMessage(message: Message): Promise<string> {
return 'Message processed successfully';
}
}
You can set the
prefix
globally via setting in theDiscordModule
.
You can also generate a DTO class based on incoming message content.
Create an DTO class. Think of the input string as if it were separated by spaces.
For slicing parameters, the decorators @ArgNum
and @ArgRange
are used.
@ArgNum
takes value at array index@ArgRange
is the same as theslice
function
💡 Example
/* start.dto.ts */
import { ArgNum, ArgRange } from '@discord-nestjs/core';
export class StartDto {
@ArgNum(() => ({ position: 0 }))
game: string;
@ArgRange((last) => ({ formPosition: last + 1 }))
players: string[];
}
Then just create a command. To get object with command option you need add @MessageEvent()
/@MSG()
with PrefixCommandPipe
.
MessageEvent
will extract the data from event args and PrefixCommandPipe
will convert the data into an object.
You can import
PrefixCommandPipe
from common package
/* bot.gateway.ts */
import {PrefixCommandInterceptor, PrefixCommandPipe} from '@discord-nestjs/common';
import {
InjectDiscordClient,
On,
Once,
MessageEvent
} from '@discord-nestjs/core';
import { Injectable, Logger, UseInterceptors } from '@nestjs/common';
import { Client } from 'discord.js';
import {StartDto} from './dto/start.dto';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
constructor(
@InjectDiscordClient()
private readonly client: Client,
) {
}
@Once('ready')
onReady() {
this.logger.log(`Bot ${this.client.user.tag} was started!`);
}
@On('messageCreate')
@UseInterceptors(new PrefixCommandInterceptor('start'))
async onMessage(@MessageEvent(PrefixCommandPipe) dto: StartDto): Promise<string> {
console.log(dto);
return 'Message processed successfully';
}
}
BotGateway
must be added to module providers.
The message !start warzone misha mark
in the channel should generate
StartDto { game: 'warzone', players: [ 'misha', 'mark' ] }
DTO.
ℹ️ Pipes, Guards, Interceptors and Filters
Pipes, Guards, Interceptors and Filter work the same as Nest.
The only exception is guard. In NestJS Guard
consumer throw Forbidden exception, when access denied.
The discord-nestjs
listeners catch ForbiddenException
by default. To override this behavior set
isTrowForbiddenException: true
in DiscordModule
options.
ℹ️ Collectors
In addition to the standard implementation of collectors
from discord.js
, discord-nestjs
provides their declaration
through decorators. You can create three types of collectors: ReactCollector, MessageCollector and InteractionCollector.
The first thing you need to do is create a collector class and mark it with either @MessageEventCollector
or
@ReactionEventCollector
or @InteractionEventCollector
with a decorator. For example, let's create a ReactionCollector
.
💡 Example
/* appreciated-reaction-collector.ts */
import {
Filter,
InjectCollector,
On,
Once,
ReactionEventCollector,
} from '@discord-nestjs/core';
import { Injectable, Scope } from '@nestjs/common';
import { MessageReaction, ReactionCollector, User } from 'discord.js';
@Injectable({ scope: Scope.REQUEST })
@ReactionEventCollector({ time: 15000 })
export class AppreciatedReactionCollector {
constructor(
@InjectCollector()
private readonly collector: ReactionCollector,
) {}
@Filter()
isLikeFromAuthor(reaction: MessageReaction, user: User): boolean {
return (
reaction.emoji.name === '👍' && user.id === reaction.message.author.id
);
}
@On('collect')
onCollect(): void {
console.log('collect');
}
@Once('end')
onEnd(): void {
console.log('end');
}
}
Let me explain in detail what is going on here.
- We marked the
AppreciatedReactionCollector
class with the@ReactionEventCollector
decorator and passed collector options as decorator argument. Think of it like we createdmessage.createReactionCollector({ time: 15000 });
fromdiscord.js
library. - The
@InjectCollector
injects the value of the collector into the class constructor. If you use this decorator, you need to addscope: Scope.REQUEST
. The default isscope: Scope.DEFAULT
. - The
@Filter
decorator filters the incoming data into the collector. Treat it like thefilter
option increateReactionCollector
. - Decorators
On
andOnce
subscribe to collector events.
Filters, guards, interceptors and pipes can be applied to collector events.
To apply your collector to the message use @UseCollectors
decorator.
💡 Example
/* bot.gateway.ts */
import { On, Once, UseCollectors } from '@discord-nestjs/core';
import { CollectorInterceptor } from '@discord-nestjs/common';
import { Injectable, Logger, UseGuards, UseInterceptors } from '@nestjs/common';
import { Message } from 'discord.js';
import { AppreciatedReactionCollector } from './appreciated-reaction-collector';
import { MessageFromUserGuard } from './guards/message-from-user.guard';
@Injectable()
export class BotGateway {
private readonly logger = new Logger(BotGateway.name);
@Once('ready')
onReady(): void {
this.logger.log('Bot was started!');
}
@On('messageCreate')
@UseGuards(MessageFromUserGuard)
@UseCollectors(AppreciatedReactionCollector)
@UseInterceptors(CollectorInterceptor)
async onMessage(message: Message): Promise<void> {
await message.reply('Start collector');
}
}
In order for the collector to be called in the correct order, you need to hang CollectorInterceptor
interceptor.
You can import
CollectorInterceptor
from common package
If you need to get applied collectors use @AppliedCollectors
param decorator.
Other collectors types are created exactly by analogy. They apply to both event handlers and commands.
For example, below is a sample button creation.
💡 Example
/* post-interaction-collector.ts */
import {
Filter,
InjectCauseEvent,
InteractionEventCollector,
On,
} from '@discord-nestjs/core';
import { Injectable, Scope } from '@nestjs/common';
import { ButtonInteraction, ChatInputCommandInteraction } from 'discord.js';
@Injectable({ scope: Scope.REQUEST })
@InteractionEventCollector({ time: 15000 })
export class PostInteractionCollector {
constructor(
@InjectCauseEvent()
private readonly causeInteraction: ChatInputCommandInteraction,
) {}
@Filter()
filter(interaction: ButtonInteraction): boolean {
return this.causeInteraction.id === interaction.message.interaction.id;
}
@On('collect')
async onCollect(interaction: ButtonInteraction): Promise<void> {
await interaction.update({
content: 'A button was clicked!',
components: [],
});
}
}
- The
@InjectCauseEvent
decorator allow you get event that created the collector
/* play.command.ts */
import { CollectorInterceptor, SlashCommandPipe } from '@discord-nestjs/common';
import {
AppliedCollectors,
Command,
Handler,
IA,
UseCollectors,
} from '@discord-nestjs/core';
import { MessageActionRowComponentBuilder } from '@discordjs/builders';
import { UseInterceptors } from '@nestjs/common';
import {
ActionRowBuilder,
ButtonBuilder,
ButtonInteraction,
ButtonStyle,
InteractionCollector,
InteractionReplyOptions,
} from 'discord.js';
import { PlayDto } from '../dto/play.dto';
import { PostInteractionCollector } from '../post-interaction-collector';
@Command({
name: 'play',
description: 'Plays a song',
})
@UseInterceptors(CollectorInterceptor)
@UseCollectors(PostInteractionCollector)
export class PlayCommand {
@Handler()
async onPlayCommand(
@IA(SlashCommandPipe) dto: PlayDto,
@AppliedCollectors(0) collector: InteractionCollector<ButtonInteraction>,
): Promise<InteractionReplyOptions> {
const row =
new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('primary')
.setLabel(dto.song)
.setStyle(ButtonStyle.Primary),
);
console.log(collector);
return {
content: 'Click on the button to play the song!',
components: [row],
};
}
}
ℹ️ Modals
Full example is shown here
🛠️ Exported providers
DiscordModule
currently exports only three providers.
ℹ️ DiscordClientProvider
Provides the discord client or webhook client.
ℹ️ DiscordCommandProvider
discord-nestjs
package builds slash command object based on all decorators and DiscordCommandProvider provides it.
For example, this is useful when you need to lazily register commands or register commands for a specific guild.
ℹ️ ReflectMetadataProvider
Provides methods for getting metadata for decorators.
ℹ️ CollectorProvider
Allow you to apply collector event
🗂 Decorators description
ℹ️ @InjectDiscordClient
Inject Discord.js client
ℹ️ @Command
Mark class as command
Params
name
* - Command namedescription
* - Command descriptioninclude
- Include subgroups and subcommandsdefaultMemberPermissions
- Set default permissiondmPermission
- Has DM permission
ℹ️ @SubCommand
Mark class as subcommand
Params
name
* - Command namedescription
* - Command description
ℹ️ @On
Handle discord and collector events hint
Params
event
* - Name of the event to listen to
ℹ️ @Once
Handle discord and collector events (only once) hint
ℹ️ @ArgNum
Set value by argument number
Params
- arguments
last
- Last index position
- return
position
* - Position index form input
ℹ️ @ArgRange
Set value by argument number
Params
- arguments
last
- Last index position
- return
formPosition
* - Start index position form inputtoPosition
- Finish index position form input (default last index of input)
Params
event
* - Name of the event to listen to
ℹ️ @InteractionEvent/@IA
Extract interaction event from args
ℹ️ @MessageEvent/@MSG
Extract message event from args
ℹ️ @Param
Sets the command parameter
Params
description
* - Command descriptionname
- Command namerequired
- The parameter is requiredautocomplete
- Send autocomplete interaction(Only forstring
,number
andinteger
)minValue
- Min value fornumber
orinteger
maxValue
- Max value fornumber
orinteger
type
- Specifies the type of the parameter
ℹ️ @Choice
Marks command parameter as dropdown.
Params
(Accepts enum
or Map
)
ℹ️ @Channel
Marks command parameter as channel select.
Params
channelType
- list of channel types
ℹ️ @InteractionEventCollector
Create interaction collector
Params
See here
ℹ️ @MessageEventCollector
Create message collector
Params
See here
ℹ️ @ReactionEventCollector
Create reaction collector
Params
See here
ℹ️ @UseCollectors
Apply collector
Params
- List of collector classes
ℹ️ @InjectCollector
Inject collector in constructor (only in class collector)
ℹ️ @InjectCauseEvent
Inject cause event in constructor (only in class collector)
ℹ️ @Filter
Add filter to collector
ℹ️ @Field
Extract field from modal form
ℹ️ @TextInputValue
Extract text input value from modal form