Decorators
Decorators can be used to easily add functionality to your modules. By default decorators are created with the typescript template of create-reciple
. To use decorators, you need to install the @reciple/decorators
package in your project and set experimentalDecorators
to true
in your tsconfig.json
.
If you don’t have the @reciple/decorators
package installed, you can install it with npm i @reciple/decorators
.
npm i @reciple/decorators
tsconfig.json
{
"compilerOptions": {
// ...Other compiler options...
"experimentalDecorators": true
}
}
Writing Modules with Decorators
To use decorators, you need to import the @reciple/decorators
package in your module. Then add the @setRecipleModule()
decorator to your module class. This decorator will set your module’s metadata to the prototype using the recipleModuleMetadataSymbol
symbol property.
import { setRecipleModule } from '@reciple/decorators';
@setRecipleModule()
export class PingCommand implements RecipleModuleData {
public async onStart(): Promise<boolean> {
return true;
}
}
export default new PingCommand();
@setRecipleModule()
takes an optional versions
parameter. This parameter will set the versions
property of your module.
import { setRecipleModule } from '@reciple/decorators';
@setRecipleModule('^9.0.0') // or @setRecipleModule(['^9.0.0'])
export class PingCommand implements RecipleModuleData {
public async onStart(): Promise<boolean> {
return true;
}
}
export default new PingCommand();
similar to
export class PingCommand implements RecipleModuleData {
public versions = '^9.0.0';
public async onStart(): Promise<boolean> {
return true;
}
}
export default new PingCommand();
You can also pass an object to @setRecipleModule()
to set the module’s Id and name.
import { setRecipleModule } from '@reciple/decorators';
@setRecipleModule({ id: 'ping', name: 'Ping', versions: '^9.0.0' })
export class PingCommand implements RecipleModuleData {
public async onStart(): Promise<boolean> {
return true;
}
}
export default new PingCommand();
Adding Commands With Decorators
To add commands with decorators, adding @setRecipleModuleStart()
decorator is required to set the created commands from the class’ prototype metadata to the module’s .commands
property.
Context Menu Commands
@setContextMenuCommand()
decorator is used to add context menu commands to your module. First parameter of the decorator takes a command object or builder.
import { setContextMenuCommand, setRecipleModule, setRecipleModuleStart } from '@reciple/decorators';
import { ContextMenuCommandExecuteData, RecipleModuleData } from 'reciple';
import { ApplicationCommandType } from 'discord.js';
@setRecipleModule()
export class PingCommand implements RecipleModuleData {
@setRecipleModuleStart()
public async onStart(): Promise<boolean> {
return true;
}
@setContextMenuCommand({ name: 'Ping', type: ApplicationCommandType.Message })
public async handlePingCommand({ interaction }: ContextMenuCommandExecuteData): Promise<void> {
await interaction.reply('Pong!');
}
}
export default new PingCommand();
Message Commands
@setMessageCommand()
decorator is used to add message commands to your module. First parameter of the decorator takes a command object or builder.
import { setMessageCommand, setRecipleModule, setRecipleModuleStart } from '@reciple/decorators';
import { MessageCommandExecuteData, RecipleModuleData } from 'reciple';
import { ApplicationCommandType } from 'discord.js';
@setRecipleModule()
export class PingCommand implements RecipleModuleData {
@setRecipleModuleStart()
public async onStart(): Promise<boolean> {
return true;
}
@setMessageCommand({ name: 'ping', description: 'Ping command' })
public async handlePingCommand({ message }: MessageCommandExecuteData): Promise<void> {
await message.reply('Pong!');
}
}
export default new PingCommand();
Slash Commands
@setSlashCommand()
decorator is used to add slash commands to your module. First parameter of the decorator takes a command object or builder.
import { setSlashCommand, setRecipleModule, setRecipleModuleStart } from '@reciple/decorators';
import { SlashCommandExecuteData, RecipleModuleData } from 'reciple';
import { ApplicationCommandType } from 'discord.js';
@setRecipleModule()
export class PingCommand implements RecipleModuleData {
@setRecipleModuleStart()
public async onStart(): Promise<boolean> {
return true;
}
@setSlashCommand({ name: 'ping', description: 'Ping command' })
public async handlePingCommand({ interaction }: SlashCommandExecuteData): Promise<void> {
await interaction.reply('Pong!');
}
}
export default new PingCommand();
Stacking Command Decorators
import { setContextMenuCommand, setMessageCommand, setRecipleModule, setRecipleModuleLoad, setRecipleModuleStart, setRecipleModuleUnload, setSlashCommand } from '@reciple/decorators';
import { AnyCommandExecuteData, CommandType, RecipleModuleData } from "reciple";
import { ApplicationCommandType, type Message } from 'discord.js';
@setRecipleModule()
export class PingCommand implements RecipleModuleData {
@setRecipleModuleStart()
public async onStart(): Promise<boolean> {
return true;
}
@setContextMenuCommand({ name: 'Ping', type: ApplicationCommandType.Message })
@setMessageCommand({ name: 'ping', description: 'Ping command' })
@setSlashCommand({ name: 'ping', description: 'Ping command' })
async handleCommandExecute(data: AnyCommandExecuteData): Promise<void> {
switch (data.type) {
case CommandType.ContextMenuCommand:
case CommandType.SlashCommand:
await data.interaction.reply('Pong!');
return;
case CommandType.MessageCommand:
await data.message.reply('Pong!');
return;
}
}
}
export default new PingCommand();
Adding Event Listeners With Decorators
@reciple/decorators
provides:
@setClientEvent()
- Adds event listeners to theRecipleClient
@setWebsocketEvent()
- Adds event listeners to theWebsocketManager
@setRESTEvent()
- Adds event listeners to theREST
@setModuleManagerEvent()
- Adds event listeners to theModuleManager
@setProcessEvent()
- Adds event listeners to theProcess
These decorators are used to set a class method into an event listener. These decorators takes the event name as the first argument. You can set the event as once by setting the second argument to true
.
Event Register
These event listeners are registered to its event emitter after the module is loaded (the bot is logged in), it means that it’s required to use @setRecipleModuleLoad()
decorator to register the event listeners.
You can make the
@setRecipleModuleStart()
’s first parameter astrue
to register the event listeners even before the module is loaded.
@setRecipleModuleUnload()
decorator on your onUnload()
method to unregister the event listeners when the module is unloaded.import { setClientEvent, setRecipleModule, setRecipleModuleStart } from '@reciple/decorators';
import { RecipleModuleData } from 'reciple';
import { ApplicationCommandType } from 'discord.js';
@setRecipleModule()
export class MentionEvent implements RecipleModuleData {
@setRecipleModuleStart()
public async onStart(): Promise<boolean> {
return true;
}
@setRecipleModuleLoad()
public async onLoad(): Promise<void> {}
@setRecipleModuleUnload()
public async onUnload(): Promise<void> {}
@setClientEvent('messageCreate') // or @setClientEvent('messageCreate', true) for once event
public async onMessageCreate(message: Message): Promise<void> {
const bot = message.client.user?.id;
if (!bot || !message.content.include(bot)) return;
await message.reply('You mentioned me!');
}
}
export default new MentionEvent();
Interaction Listeners
If you have reciple-interaction-events
installed, you can use its provided decorators to register an event listener to an interaction.
@setRegisterInteractionEvents()
method decorator to your onStart
or onLoad
method to register the event listeners.import { InteractionListenerType, setRegisterInteractionEvents, setInteractionEvent } from 'reciple-interaction-events';
import { setRecipleModule, setRecipleModuleStart, setMessageCommand } from '@reciple/decorators';
import { ButtonBuilder, ButtonStyle, ComponentType, ButtonInteraction } from 'discord.js';
import type { MessageCommandExecuteData, RecipleModuleData } from 'reciple';
@setRecipleModule()
export class MyModule implements RecipleModuleData {
@setRecipleModuleStart()
@setRegisterInteractionEvents()
async onStart(): Promise<boolean> {
return true;
}
@setMessageCommand({ name: 'test', description: 'Go test' })
async handleMessageCommand({ message }: MessageCommandExecuteData): Promise<void> {
await message.reply({
content: `Hello, world ${message.author}!`,
components: [
{
type: ComponentType.ActionRow,
components: [
new ButtonBuilder()
.setLabel('Delete Message')
.setCustomId('delete-message')
.setStyle(ButtonStyle.Secondary)
]
}
]
});
}
@setInteractionEvent({ type: InteractionListenerType.Button, customId: 'delete-message' })
async onInteraction(interaction: ButtonInteraction): Promise<void> {
await interaction.deferUpdate();
await interaction.message.delete();
}
}
export default new MyModule();