npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@discord-nestjs/core

v5.3.14

Published

Core module

Downloads

5,527

Readme

Core module

🧾 Description

NestJS package for discord.js

👨🏻‍💻 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 to true in your tsconfig.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 here
  • discordClientOptions * - Client options from discord.js library
  • registerCommandOptions - Specific registration of slash commands(If option is not set, global commands will be registered)
    • forGuild - For which guild to register a slash command
    • trigger - Used in cases where it is necessary to register commands by event
    • allowFactory - Based on what criteria will slash commands be registered
    • removeCommandsBefore - Remove mission commands
  • prefix - Global command prefix
  • prefixGlobalOptions - Global options for prefix command
  • webhook - Connecting with webhook
    • webhookId * - Webhook id
    • webhookToken * - Webhook token
  • autoLogin - Calling login function from discord client on application bootstrap
  • failOnLogin - 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(Accepts enum or Map).
  • @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 a boolean, 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 default

  • If trigger used in cases where it is necessary to register commands by event

  • If allowFactory is specified then commands will be registered by condition from allowFactory

  • If forGuild is specified, then commands for a specific guild will be registered

  • If 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 the DiscordModule.

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 the slice 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 created message.createReactionCollector({ time: 15000 }); from discord.js library.
  • The @InjectCollector injects the value of the collector into the class constructor. If you use this decorator, you need to add scope: Scope.REQUEST. The default is scope: Scope.DEFAULT.
  • The @Filter decorator filters the incoming data into the collector. Treat it like the filter option in createReactionCollector.
  • Decorators On and Once 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 name
  • description * - Command description
  • include - Include subgroups and subcommands
  • defaultMemberPermissions - Set default permission
  • dmPermission - Has DM permission

ℹ️ @SubCommand

Mark class as subcommand

Params

  • name * - Command name
  • description * - 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 input
    • toPosition - 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 description
  • name - Command name
  • required - The parameter is required
  • autocomplete - Send autocomplete interaction(Only for string, number and integer)
  • minValue - Min value for number or integer
  • maxValue - Max value for number or integer
  • 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