Pandora empowers you to create hybrid commands that seamlessly function as both slash commands and prefixed commands within your Discord bot, leveraging the power of discord.js.
npm install pandora.ts
- Arguments: Extracting Information
- Utils: Context-Aware Utilities
- Hybrid Command: Bridging the Gap
- Normalizing Slash Commands
- Examples: Creating Hybrid Commands
Pandora's args
functionality allows you to retrieve data from options in slash commands or by parsing message content for prefixed commands. The '*'
wildcard indicates that any value of the specified type is accepted.
_.getUser({
expects: UserExpectType[] | '*', // Expected format (ID, mention, username)
position: number | '*', // Position in message content
option: string, // Option name (for slash commands)
validate?: (user: User) => boolean // Optional validation function
}): User | null
- UserExpectType:
UserExpectType.Id
UserExpectType.Mention
UserExpectType.Username
_.getMember({
expects: MemberExpectType[] | '*',
position: number | '*',
option: string,
validate?: (member: GuildMember) => boolean
}): GuildMember | null
- MemberExpectType:
MemberExpectType.Id
MemberExpectType.Mention
MemberExpectType.Username
_.getChannel({
expects: ChannelExpectType[] | '*',
position: number | '*',
option: string,
validate?: (channel: Channel) => boolean
}): Channel | null
- ChannelExpectType:
ChannelExpectType.Id
ChannelExpectType.Mention
ChannelExpectType.Name
_.getRole({
expects: RoleExpectType[] | '*',
position: number | '*',
option: string,
validate?: (role: Role) => boolean
}): Role | null
- RoleExpectType:
RoleExpectType.Id
RoleExpectType.Mention
RoleExpectType.Name
_.getString({
position: number | '*',
option: string,
validate?: (value: string) => boolean
}): string | null
_.getNumber({
position: number | '*',
option: string,
validate?: (value: number) => boolean
}): number | null
_.getBoolean({
position: number | '*',
option: string,
validate?: (value: boolean) => boolean
}): boolean | null
Pandora provides utility functions that adapt to both slash and prefixed command contexts.
_.isInteractionContext(__context__): __context__ is InteractionContext;
- Example:
if (_.isInteractionContext(context)) {
// Slash command specific code
}
_.isPrefixedContext(__context__): __context__ is PrefixedContext;
- Example:
if (_.isPrefixedContext(context)) {
// Prefixed command specific code
}
_.author: User
- Example:
const { username } = _.author // The command author username
The HybridCommand
class is the core of building hybrid commands.
- Slash Commands:
<Client>.on('interactionCreate', (interaction) => {
if (!interaction.isChatInputCommand()) return;
// ... Interaction logic
<HybridCommand>.executeSlashCommand(interaction, <Client>);
});
- Prefixed Commands:
<Client>.on('messageCreate', (message) => {
if (!message.inGuild()) return;
// ... Message logic
<HybridCommand>.executePrefixCommand(message, <prefix>, <Client>);
});
Pandora's hybrid commands use a structure that requires normalization for Discord's API.
<HybridCommand>.toJSON() // Returns a Discord-compatible slash command object
- Simple example:
import { HybridCommand } from 'pandora';
export default new HybridCommand({
name: 'ping',
aliases: ['pong'],
description: 'Ping command!',
options: [],
runner: ({ utils }) => utils.reply('Pong!')
});
- Example with options:
import { HybridCommand, EntityType, UserExpectType } from 'pandora';
export default new HybridCommand({
name: 'avatar',
aliases: ['av'],
description: 'Avatar command!',
options: <const> [
{ name: 'user', type: EntityType.User }
],
runner: ({ args, utils }) => {
const user = args.getUser({
expects: [
UserExpectType.Id,
UserExpectType.Mention
],
option: 'user',
position: 0
}) || utils.author;
const avatar = user.displayAvatarURL();
return utils.reply(avatar);
}
});
- Example with command context exceptions:
import { HybridCommand } from 'pandora';
export default new HybridCommand({
name: 'ping',
aliases: ['pong'],
description: 'Ping command!',
options: [],
runner: async ({ ctx, utils }) => {
await utils.reply('Pong!');
if (utils.isInteractionContext(ctx))
ctx.interaction.followUp('Runned with slash');
if (utils.isPrefixedContext(ctx))
ctx.message.channel.send('Runned with prefix');
}
});