Skip to content

03) Adding Commands

ly.ton edited this page Mar 27, 2018 · 3 revisions

The preferred way of adding commands is via a supplier and the BreadBotBuilder#addCommand method.

builder = new BreadBotBuilder();
...
builder.addCommand(MyCommand::new);

When a command is added using its class such as builder.addCommand(MyCommand.class) the constructor is accessed through reflection. Thus, it is more efficient to provide direct access to the default constructor via MyCommand::new.

Adding Commands with a Consumer

Commands can be created from a Consumer<CommandEvent>.

builder.addCommand(event -> event.reply("123"), command -> command.setKeys("test"));

Adding Commands with a Class

public class TestCommand {

    @MainCommand
    public String test() {
        return "123";
    }

}
builder.addCommand(TestCommand.class);

Here we register a command using it's class. In order to create a command from a class, It must be public and there should be a public method that is annotated with @MainCommand or @Command. There also needs to be a public no-args constructor that the Client can use to instantiate the class. The class must be a concrete class and cannot be Abstract or an Interface.

Note that each time the command is called by a user, the class is instantiated each time. If you would like to only use 1 instance of the class, you can either register the command with an object-Adding-Commands#adding-commands-with-an-object). or set the persistence field of the commandbuilder to true

builder.createCommand(TestCommand.class).setPersistent(true);
// or
builder.createCommand(new TestCommand());

Adding Commands with a Supplier

Commands can also be registered with a Supplier.

builder.addCommand(TestCommand::new)

The supplier will be invoked once to set the default values of builder and invoked again each time the command is called.

Adding Commands with an Object

Commands can be registered with an Object. The difference here is that the Object is reused each time the command is called.

builder.addCommand(new TestCommand());

Bulk Adding Commands

Each method has a bulk add option that accepts a collection of those objects.
One other way of adding commands is to provide the package in which the command classes are located in via BreadBotBuilder#addCommands(String packageName). This will scan all the classes in that package for a public concrete class that contains any methods annotated with @Command or @MainCommand.

builder.addCommands("com.github.breadmoirai.testbot.commands");

addCommand() vs CreateCommand()

Both methods will inspect the passed object to set default values of the Command. createCommand() returns the CommandHandleBuilder while addCommand() returns the BreadBotClientBuilder for chaining. addCommand() has overloaded methods which allow a Consumer to be passed as the 2nd parameter to configure the builder.

builder.addCommand(event -> event.reply("123"), command -> command.setKeys("test"));
CommandHandleBuilder command = builder.createCommand(event -> event.reply("123"));
command.setKeys("test");

Multiple Commands

One class can contain multiple commands.

public class TestCommands {
   
    @Command
    public String test1() {
        return "1";
    }

    @Command
    public String test2() {
        return "2";
    }

}

When the following is invoked builder.addCommand(TestCommands.class) 2 commands will be created with keys "test1" and "test2" respectively. If the 'addCommand()' method is passed a Consumer to configure the builder, the Consumer will be applied to both commands.

The TestCommands.class cannot be created with createCommand(). It must be passed to createCommands() which returns a List<CommandHandleBuilder> that contains each command in the class.

SubCommands

Sub commands may be created like so:

command = builder.createCommand(event -> event.reply("1")).setKeys("main");
subcommand = command.createCommand(event -> event.reply("2")).setKeys("sub");

Where an input of "!main" would produce "1" and "!main sub", "2". To achieve this behavior in a class, one method must be marked as @MainCommand and other methods marked with @Command as sub-commands.

public class MyCommand {
    
    @MainCommand
    public String main() {
        return "1";
    }

    @Command
    public String sub() {
        return "2";
    }

}

Nested SubCommands

public class MyCommand {
    
    @MainCommand
    public String main() {
        return "1";
    }

    @Command
    public String sub() {
        return "2";
    }

    public static class InnerCommand {
    
        @MainCommand
        public String isub() {
            return "A";
        }

        @Command
        public String isubsub() {
            return "B";
        }

    }
   
}
builder.addCommand(MyCommand::new)

The class above results in the following.

Input Output
!main 1
!main sub 2
!main isub A
!main isub isubsub B

The inner class must be public and may be static or non-static. If the inner class does not require an instance of the enclosing class, static is preferred.