2.4.2 • Published 11 days ago

@kaname-png/plugin-subcommands-advanced v2.4.2

Weekly downloads
-
License
MIT
Repository
github
Last release
11 days ago

Neko Plugins Logo

@kaname-png/plugin-subcommands-advanced

Plugin for @sapphire/framework to be able to create subcommands based on command classes.

GitHub codecov npm (scoped) npm

Description

This plugin allows you to manage the subcommands of a parent command based on the classes of the commands in a simple way.

Currently the problem with the original subcommand plugin is that you have to put all the methods of the subcommands in the same class of the parent command, which can be a problem if the parent command has many subcommands or subcommand groups.

This plugin allows you to modularize the subcommands of a parent command into several command classes and also allows you to use different preconditions on each subcommand.

Support for message commands coming soon

Features

  • Fully ready for TypeScript!
  • Includes ESM ready entrypoint
  • Easy to use
  • Support for preconditions.
  • Based on command class.
  • Everything included in the original subcommand plugin.

Installation

@kaname-png/plugin-subcommands-advanced depends on the following packages. Be sure to install these along with this package!

You can use the following command to install this package, or replace npm install with your package manager of choice.

npm install @sapphire/framework @sapphire/plugin-subcommands @kaname-png/plugin-subcommands-advanced

Usage

JavaScript

In your main or setup file, register the plugin:

require('@kaname-png/plugin-subcommands-advanced/register');

Once the plugin is registered, we have to configure some options.

async function main() {
	const client = new SapphireClient({
		subcommandsAdvanced: {
			/* All options are optionals */
			nameCommandsAutogenerated: true
			/* more optional options.... */
		}
	});

	await client.login();
}

void main();

TypeScript

In your main or setup file, register the plugin:

import '@kaname-png/plugin-subcommands-advanced/register';

Once the plugin is registered, we have to configure some options.

async function main() {
	const client = new SapphireClient({
		subcommandsAdvanced: {
			/* All options are optionals */
			nameCommandsAutogenerated: true
			/* more optional options.... */
		}
	});

	await client.login();
}

void main();

For a good user experience (UX), it is necessary to follow the following file structure. The directory order is not required, but is recommended.

commands
└── utils
    ├── parent.js // Parent command of the subcommand and subcommand groups.

    ├── ping.js // Subcommand of the parent command.

    └── poll // Subcommand group name.
        └── create.js // Subcommand of the poll subcommand group.

Parent Command

The parent command is important because it is where the subcommands and subcommand group will be registered and is necessary for @sapphire/framework to know what to do with the subcommands.

TypeScript

import { Subcommand } from '@kaname-png/plugin-subcommands-advanced';
import { ApplicationCommandRegistry } from '@sapphire/framework';

export class ParentCommand extends Subcommand {
 	public constructor(context: Submmand.Context, options: Subcommand.Options) {
 		super(context, {
 			...options,
 			name: 'utils',
			preconditions: [] // The preconditions set here affect all subcommands.
 		});
 	}

 	public override registerApplicationCommands(registry: ApplicationCommandRegistry) {
 		registry.registerChatInputCommand(
			(ctx) => {
				// If you want to link commands in groups of subcommands you first need to register them in the builder context of the parent command.
				ctx.addSubcommandGroup((sc) =>
					sc
						.setName('poll')
						.setDescription('Make awesome polls!')
				);

				// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand registry in the subcommand groups of the parent command.
				this.hooks.groups(this, ctx);

				// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand register in the parent command.
				this.hooks.subcommands(this, ctx);

 				// Calling both hooks is only necessary if required, it is not mandatory.
				return ctx
					.setName(this.name)
					.setDescription('Parent command of utils subcommands)
			}
		);
 	}
}

JavaScript

import { Subcommand } from '@kaname-png/plugin-subcommands-advanced';

export class ParentCommand extends Subcommand {
 	constructor(context, options) {
 		super(context, {
 			...options,
 			name: 'utils',
			preconditions: [] // The preconditions set here affect all subcommands.
 		});
 	}

 	registerApplicationCommands(registry) {
 		registry.registerChatInputCommand(
			(ctx) => {
				// If you want to link commands in groups of subcommands you first need to register them in the builder context of the parent command.
				ctx.addSubcommandGroup((sc) =>
					sc
						.setName('poll')
						.setDescription('Make awesome polls!')
				);

				// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand registry in the subcommand groups of the parent command.
				this.hooks.groups(this, ctx);

				// It is necessary to call this hook and pass the builder context to register the subcommands stored in the subcommand register in the parent command.
				this.hooks.subcommands(this, ctx);

 				// Calling both hooks is only necessary if required, it is not mandatory.
				return ctx
					.setName(this.name)
					.setDescription('Parent command of utils subcommands)
			}
		);
 	}
 }

Register the command as a subcommand in the parent command

To register commands as subcommands of the parent command it is necessary to use the registerSubCommand option of the command options.

With Typescript

import { Command } from '@kaname-png/plugin-subcommands-advanced';
import type { Message } from 'discord.js';

export class PingCommand extends Command {
	public constructor(context: Command.Context, options: Command.Options) {
		super(context, {
			...options,
			preconditions: [], // The preconditions set here affect only the subcommand where it was established.
			registerSubCommand: {
				parentCommandName: 'utils', // Name of the parent command (parent.js).
				slashSubcommand: (builder) => builder.setName('ping').setDescription('Hi!') // Builder that will be embedded in the parent command registry to register the slash subcommand.
			}
		});
	}

	// It is only necessary if the `slashSubcommand` option of the `registerSubCommand` command options is used.
	public override chatInputRun(interaction: Command.ChatInputInteraction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	public override messageRun(message: Message) {
		return message.reply('uwu');
	}
}

With JavaScript

import { Command } from '@kaname-png/plugin-subcommands-advanced';

export class PingCommand extends Command {
	constructor(context, options) {
		super(context, {
			...options,
			preconditions: [], // The preconditions set here affect only the subcommand where it was established.
			registerSubCommand: {
				parentCommandName: 'utils', // Name of the parent command (parent.js).
				slashSubcommand: (builder) => builder.setName('ping').setDescription('Hi!') // Builder that will be embedded in the parent command registry to register the slash subcommand.
			}
		});
	}

	// It is only necessary if the `slashSubcommand` option of the `registerSubCommand` command options is used.
	chatInputRun(interaction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	messageRun(message) {
		return message.reply('uwu');
	}
}

Register a command as a subcommand of a group of subcommands of the parent command

To register commands as group subcommands it is important to first register the groups to be used in the main command.

With Typescript

import { Command } from '@kaname-png/plugin-subcommands-advanced';

export class PollCreateCommand extends Command {
	public constructor(context: Command.Context, options: Command.Options) {
		super(context, {
			...options,
			preconditions: [], // The preconditions set here affect only the subcommand where it was established.
			registerSubcommmandInGroup: {
				parentCommandName: 'utils', // Name of the parent command (parent.js).
				groupName: 'poll', // Name of the group that was registered in the builder context of the parent command.
				slashSubcommand: (builder) => builder.setName('create').setDescription('Create a poll!') // Builder that will be embedded in the parent command registry to register the slash subcommand.
			}
		});
	}

	// It is only necessary if the `slashSubcommand` option of the `registerSubcommmandInGroup` command options is used.
	public override chatInputRun(interaction: Command.ChatInputInteraction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	public override messageRun(message: Message) {
		return message.reply('uwu');
	}
}

With JavaScript

import { Command } from '@kaname-png/plugin-subcommands-advanced';

export class PollCreateCommand extends Command {
	constructor(context, options) {
		super(context, {
			...options,
			preconditions: [], // The preconditions set here affect only the subcommand where it was established.
			registerSubcommmandInGroup: {
				parentCommandName: 'utils', // Name of the parent command (parent.js).
				groupName: 'poll', // Name of the group that was registered in the builder context of the parent command.
				slashSubcommand: (builder) => builder.setName('create').setDescription('Create a poll!') // Builder that will be embedded in the parent command registry to register the slash subcommand.
			}
		});
	}

	// It is only necessary if the `slashSubcommand` option of the `registerSubcommmandInGroup` command options is used.
	chatInputRun(interaction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	messageRun(message) {
		return message.reply('uwu');
	}
}

Decorators

The plugin also includes subcommand decorators so that TypeScript users can easily register subcommands.

Subcommands

import { RegisterSubCommand } from '@kaname-png/plugin-subcommands-advanced';
import { Command } from '@kaname-png/plugin-subcommands-advanced';

@RegisterSubCommand('utils', (builder) => builder.setName('ping').setDescription('Hi!'))
export class PingCommand extends Command {
	// It is only necessary if the `slashSubcommand` option of the `registerSubCommand` command options is used.
	public override chatInputRun(interaction: Command.ChatInputInteraction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	public override messageRun(message: Message) {
		return message.reply('uwu');
	}
}

Subcommands group

import { RegisterSubCommandGroup } from '@kaname-png/plugin-subcommands-advanced';
import { Command } from '@kaname-png/plugin-subcommands-advanced';

@RegisterSubCommandGroup('utils', 'poll', (builder) => builder.setName('create').setDescription('Create a poll'))
export class PingCommand extends Command {
	// It is only necessary if the `slashSubcommand` option of the `registerSubcommmandInGroup` command options is used.
	public override chatInputRun(interaction: Command.ChatInputInteraction) {
		return interaction.reply('uwu');
	}

	// Optional if you want the subcommand to work for slash commands and message commands.
	public override messageRun(message: Message) {
		return message.reply('uwu');
	}
}

That's it, the plugin will take care of configuring everything so that when the subcommand of the parent command is called, the linked command is executed.

Note

This plugin is not official from @sapphire/framework, so if you need additional help ping me in discord with my tag @kaname-png on the @sapphire/framework discord server.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

This project follows the all-contributors specification. Contributions of any kind welcome!

2.4.2

3 months ago

2.4.1

3 months ago

2.4.0

7 months ago

2.3.0

8 months ago

2.2.3

11 months ago

2.2.2

11 months ago

2.2.1

1 year ago

2.2.0

1 year ago

2.1.6

1 year ago

2.1.5

1 year ago

2.1.8

1 year ago

2.1.7

1 year ago

2.1.4

2 years ago

2.1.2

2 years ago

2.1.3

2 years ago

2.1.1

2 years ago

2.1.0

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.2.2

2 years ago

1.2.1

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago