Skip to content

freya022/BotCommands

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

3,665 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

BotCommands logo

BotCommands version JDA version

Discord invite Wiki home Documentation

BotCommands

A framework for JDA with everything you need to make a modern bot!

It supports Java 17+ and provides first-class Kotlin support, meaning you get full language support and a few extras!

πŸ§ͺ Features

Everything is built around it, it takes care of passing instances around, no need to instantiate classes, no passing everything everywhere.

It can also be replaced with Spring IoC.

Annotated and declarative application commands, with customizable argument processing, and smart automatic registration.

Example
@Command
class SlashBan {
    @JDASlashCommand(name = "ban", description = "Bans an user")
    suspend fun onSlashBan(
        event: GuildSlashEvent,
        @SlashOption(description = "The user to ban") user: User,
        @SlashOption(description = "Timeframe of messages to delete") timeframe: Long,
        // Use choices that come from the TimeUnit resolver
        @SlashOption(description = "Unit of the timeframe", usePredefinedChoices = true) unit: TimeUnit, // A resolver is used here
        @SlashOption(description = "Why the user gets banned") reason: String = "No reason supplied" // Optional
    ) {
        // ...
        event.reply_("${user.asMention} has been banned for '$reason'", ephemeral = true)
          .deleteDelayed(5.seconds)
          .await()
    }
}

Slash ban example

Annotated and declarative application commands, with customizable argument processing or manual token consumption, supports prefix and mentions.

Example
@Command
class TextBan {
    @JDATextCommandVariation(path = ["ban"], description = "Bans the mentioned user")
    suspend fun onTextBan(
        event: BaseCommandEvent,
        @TextOption user: User,
        @TextOption(example = "2") timeframe: Long,
        @TextOption unit: TimeUnit, // A resolver is used here
        @TextOption(example = "Get banned") reason: String = "No reason supplied" // Optional
    ) {
        // ...
        event.reply("${user.asMention} has been banned")
            .deleteDelayed(5.seconds)
            .await()
    }
}

Can then be used as @Bot ban @freya02 1 days A totally valid reason

Here's how the help content would look with a subcommand and a few more variations:

Help content example

Database-backed components, can be used with callbacks, or bound to a method, optionally with passed data.

Similar API to components, can be used with callbacks, or bound to a method, optionally with passed data.

Custom (annotated) event handlers, with priorities and async.

Use powerful localization for your commands and replies.

Other utilities

Amongst others!

πŸƒβ€β™‚οΈ Getting Started

You are strongly recommended to have some experience with Kotlin (or Java), OOP, JDA and Dependency Injection basics before you start using this library.

Head over to the wiki to get started.

πŸ”¬ Installation

After adding JDA:

BotCommands on maven central

Maven

<dependencies>
  <dependency>
    <groupId>io.github.freya022</groupId>
    <artifactId>BotCommands</artifactId>
    <version>VERSION</version>
  </dependency>
</dependencies>

Gradle

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.github.freya022:BotCommands:VERSION")
}

Snapshots

To use the latest, unreleased changes, see SNAPSHOTS.md.

🧩 Modules

The base BotCommands artifact will include modules often used, while others are optional.

Default modules

Optional modules

πŸ’‘ Sample usage

Here is how you would create a slash command that sends a message in a specified channel.

Kotlin
@Command
@RequiresComponents // (Optional) Disables the command if components are not enabled
class SlashSay(
    private val buttons: Buttons // Factory for buttons
) {

    // The descriptions can also be moved to localization files, reducing noise
    @JDASlashCommand(name = "say", description = "Sends a message in a channel")
    suspend fun onSlashSay(
        event: GuildSlashEvent,
        @SlashOption(description = "Channel to send the message in") channel: TextChannel,
        @SlashOption(description = "What to say") content: String
    ) {
        val deleteButton = buttons.danger(UnicodeEmojis.WASTEBASKET).ephemeral {
            bindTo { buttonEvent ->
                buttonEvent.deferEdit().queue()
                buttonEvent.hook.deleteOriginal().await()
            }
        }

        event.reply_("Done!", ephemeral = true)
            .deleteDelayed(5.seconds)
            .queue()

        channel.sendMessage(content)
            .addActionRow(deleteButton)
            .await()
    }
}
Kotlin (DSL)
@Command
@RequiresComponents // (Optional) Disables the command if components are not enabled
class SlashSay(
    private val buttons: Buttons // Factory for buttons
) : GlobalApplicationCommandProvider {

    suspend fun onSlashSay(event: GuildSlashEvent, channel: TextChannel, content: String) {
        val deleteButton = buttons.danger(UnicodeEmojis.WASTEBASKET).ephemeral {
            bindTo { buttonEvent ->
                buttonEvent.deferEdit().queue()
                buttonEvent.hook.deleteOriginal().await()
            }
        }

        event.reply_("Done!", ephemeral = true)
            .deleteDelayed(5.seconds)
            .queue()

        channel.sendMessage(content)
            .addActionRow(deleteButton)
            .await()
    }

    // This is nice if you need to run your own code to declare commands.
    // For example, a loop to create commands based on an enum
    // If you don't need any dynamic stuff, just stick to annotations
    override fun declareGlobalApplicationCommands(manager: GlobalApplicationCommandManager) {
        manager.slashCommand("say", function = ::onSlashSay) {
            // The descriptions can also be moved to localization files
            description = "Sends a message in a channel"

            option("channel") {
                description = "Channel to send the message in"
            }

            option("content") {
                description = "What to say"
            }
        }
    }
}
Java
@Command
@RequiresComponents // (Optional) Disables the command if components are not enabled
public class SlashSay {

    private final Buttons buttons; // Factory for buttons

    public SlashSay(Buttons buttons) {
        this.buttons = buttons;
    }

    // The descriptions can also be moved to localization files, reducing noise
    @JDASlashCommand(name = "say", description = "Sends a message in a channel")
    public void onSlashSay(
            GuildSlashEvent event,
            @SlashOption(description = "Channel to send the message in") TextChannel channel,
            @SlashOption(description = "What to say") String content
    ) {
        Button deleteButton = buttons.danger(UnicodeEmojis.WASTEBASKET).ephemeral()
                .bindTo(buttonEvent -> {
                    buttonEvent.deferEdit().queue();
                    buttonEvent.getHook().deleteOriginal().queue();
                })
                .build();

        event.reply("Done!")
                .setEphemeral(true)
                .delay(Duration.ofSeconds(5))
                .flatMap(InteractionHook::deleteOriginal)
                .queue();

        channel.sendMessage(content)
                .addActionRow(deleteButton)
                .queue();
    }
}

πŸ’ͺ Live templates

IntelliJ IDEA users can use live templates provided in this zip file, helping you make commands and other handlers with predefined templates, for both Kotlin and Java, keeping a consistent naming scheme and acting as a cheatsheet.

For example, if you type slashCommand in your class, this will generate a slash command and guide you through the declaration.

A list of live template can be found in Settings > Editor > Live Templates, in the BotCommands 3.X - [Language] group.

For an installation guide, you can follow this guide from JetBrains.

πŸ§‘β€πŸ’» Support

Don't hesitate to join the support server if you have any question!

🚨 Breaking changes

Due to the nature of JDA (and the Discord API), and to always improve the developer experience, the library could introduce breaking changes to allow quick adoption of newer features and better practices.

While attempting to reduce breaking changes by using deprecation mechanisms, it is not always possible or practical to use deprecations.

Small breaking/deprecating changes should be noticed via an increase of the minor version (3.0.Z -> 3.1.0), while larger breaking changes should be seing an increase of the major version (3.Y.Z -> 4.0.0).

πŸ› οΈ Contributing

If you want to contribute, make sure to base your branch on 3.X, and create your PR from it.

It would be appreciated to focus on improving the documentation, such as the wiki, the library documentation, or by creating examples.
Maintainers will focus on bug reports and feature requests, which you can create issues for.

Read the contributing guide for more details.