Skip to content

Filtering guild application command registrations

This only applies to annotated guild application commands

We'll be using a slash command as the example, but this works the same for context menu commands.

Creating the filter

Create a service implementing CommandDeclarationFilter, and make the method return true if the command can be declared. All filters must return true for the command to be declared.

Example

@BService
class BotOwnerIsGuildOwnerDeclarationFilter(
    private val botOwners: BotOwners, // Provided by the framework
) : CommandDeclarationFilter {

    override fun filter(guild: Guild, path: CommandPath, commandId: String?): Boolean {
        // Only allow this command to be in guilds owned by the bot owner
        return guild.ownerIdLong in botOwners.ownerIds
    }
}
@BService
@NullMarked // Everything is non-null unless @Nullable
public class BotOwnerIsGuildOwnerDeclarationFilter implements CommandDeclarationFilter {
    private final BotOwners botOwners; // Provided by the framework

    public BotOwnerIsGuildOwnerDeclarationFilter(BotOwners botOwners) {
        this.botOwners = botOwners;
    }

    @Override
    public boolean filter(Guild guild, CommandPath commandPath, @Nullable String s) {
        // Only allow this command to be in guilds owned by the bot owner
        return botOwners.getOwnerIds().contains(guild.getOwnerIdLong());
    }
}

Using the filter

Add a @DeclarationFilter on your command and reference your filter inside it.

Example

@Command
class SlashBotOwnerIsGuildOwner {

    // All filters must return 'true' for the command to be declared
    @DeclarationFilter(BotOwnerIsGuildOwnerDeclarationFilter::class)
    // The command needs to be registered on guilds for it to be filtered
    @TopLevelSlashCommandData(scope = CommandScope.GUILD)
    @JDASlashCommand(name = "bot_owner_is_guild_owner")
    suspend fun onSlashBotOwnerIsGuildOwner(event: GuildSlashEvent) {
        event.reply_("This command is registered on in guilds owned by the bot owner ${Emojis.TADA}", ephemeral = true).await()
    }
}
@Command
public class SlashBotOwnerIsGuildOwner {

    // All filters must return 'true' for the command to be declared
    @DeclarationFilter(BotOwnerIsGuildOwnerDeclarationFilter.class)
    // The command needs to be registered on guilds for it to be filtered
    @TopLevelSlashCommandData(scope = CommandScope.GUILD)
    @JDASlashCommand(name = "bot_owner_is_guild_owner")
    public void onSlashBotOwnerIsGuildOwner(GuildSlashEvent event) {
        event.reply("This command is registered on in guilds owned by the bot owner " + Emojis.TADA)
                .setEphemeral(true)
                .queue();
    }
}

Tip

The scope on context commands can be set directly, there is no separate top-level annotation.