Search in sources :

Example 1 with Description

use of com.freya02.botcommands.api.prefixed.annotations.Description in project BotCommands by freya022.

the class Utils method generateCommandHelp.

public static EmbedBuilder generateCommandHelp(TextCommandCandidates candidates, BaseCommandEvent event) {
    final EmbedBuilder builder = event.getDefaultEmbed();
    final TextCommandInfo commandInfo = candidates.last();
    final String name = commandInfo.getPath().getFullPath().replace('/', ' ');
    final String description = Utils.getDescription(commandInfo);
    final String prefix = event.getContext().getPrefix();
    final MessageEmbed.AuthorInfo author = builder.isEmpty() ? null : event.getDefaultEmbed().build().getAuthor();
    if (author != null) {
        builder.setAuthor(author.getName() + " – '" + name + "' command", author.getUrl(), author.getIconUrl());
    } else {
        builder.setAuthor('\'' + name + "' command");
    }
    if (description != null) {
        builder.addField("Description", description, false);
    }
    final ArrayList<TextCommandInfo> reversedCandidates = new ArrayList<>(candidates);
    Collections.reverse(reversedCandidates);
    int i = 1;
    for (TextCommandInfo candidate : reversedCandidates) {
        final List<? extends TextCommandParameter> commandParameters = candidate.getOptionParameters();
        final StringBuilder syntax = new StringBuilder("**Syntax**: " + prefix + name + ' ');
        final StringBuilder example = new StringBuilder("**Example**: " + prefix + name + ' ');
        if (candidate.isRegexCommand()) {
            final boolean needsQuote = hasMultipleQuotable(commandParameters);
            for (TextCommandParameter commandParameter : commandParameters) {
                final Class<?> boxedType = commandParameter.getBoxedType();
                final String argName = getArgName(needsQuote, commandParameter, boxedType);
                final String argExample = getArgExample(needsQuote, commandParameter, boxedType);
                final boolean isOptional = commandParameter.isOptional();
                syntax.append(isOptional ? '[' : '`').append(argName).append(isOptional ? ']' : '`').append(' ');
                example.append(argExample).append(' ');
            }
        }
        final String effectiveCandidateDescription = !candidate.hasDescription() ? "" : ("**Description**: " + candidate.getDescription() + "\n");
        if (candidates.size() == 1) {
            builder.addField("Usage", effectiveCandidateDescription + syntax + "\n" + example, false);
        } else {
            builder.addField("Overload #" + i, effectiveCandidateDescription + syntax + "\n" + example, false);
        }
        i++;
    }
    final List<TextCommandCandidates> textSubcommands = event.getContext().findTextSubcommands(commandInfo.getPath());
    if (textSubcommands != null) {
        final String subcommandHelp = textSubcommands.stream().map(TreeSet::first).map(info -> "**" + info.getPath().getNameAt(info.getPath().getNameCount() - commandInfo.getPath().getNameCount()) + "** : " + Utils.getNonBlankDescription(info)).collect(Collectors.joining("\n - "));
        if (!subcommandHelp.isBlank()) {
            builder.addField("Subcommands", subcommandHelp, false);
        }
    }
    final Consumer<EmbedBuilder> descConsumer = commandInfo.getInstance().getDetailedDescription();
    if (descConsumer != null) {
        descConsumer.accept(builder);
    }
    return builder;
}
Also used : BaseCommandEvent(com.freya02.botcommands.api.prefixed.BaseCommandEvent) net.dv8tion.jda.api.entities(net.dv8tion.jda.api.entities) java.util(java.util) Logger(org.slf4j.Logger) Category(com.freya02.botcommands.api.prefixed.annotations.Category) Emoji(com.freya02.botcommands.api.entities.Emoji) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) Logging(com.freya02.botcommands.api.Logging) Supplier(java.util.function.Supplier) Collectors(java.util.stream.Collectors) QuotableRegexParameterResolver(com.freya02.botcommands.api.parameters.QuotableRegexParameterResolver) Consumer(java.util.function.Consumer) Nullable(org.jetbrains.annotations.Nullable) Parameter(java.lang.reflect.Parameter) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) NotNull(org.jetbrains.annotations.NotNull) EmojiOrEmote(com.freya02.botcommands.api.entities.EmojiOrEmote) Description(com.freya02.botcommands.api.prefixed.annotations.Description) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder)

Example 2 with Description

use of com.freya02.botcommands.api.prefixed.annotations.Description in project BotCommands by freya022.

the class ApplicationCommandsUpdater method computeSlashCommands.

private void computeSlashCommands(List<ApplicationCommandInfo> guildApplicationCommands) {
    guildApplicationCommands.stream().filter(a -> a instanceof SlashCommandInfo).map(a -> (SlashCommandInfo) a).distinct().forEachOrdered(info -> {
        final CommandPath notLocalizedPath = info.getPath();
        try {
            final LocalizedCommandData localizedCommandData = LocalizedCommandData.of(context, guild, info);
            // Put localized option names in order to resolve them when called
            final List<OptionData> localizedMethodOptions = getLocalizedMethodOptions(info, localizedCommandData);
            if (guild != null) {
                info.putLocalizedOptions(guild.getIdLong(), localizedMethodOptions.stream().map(OptionData::getName).collect(Collectors.toList()));
            }
            localizedBaseNameToBaseName.put(localizedCommandData.getLocalizedPath().getName(), notLocalizedPath.getName());
            final CommandPath localizedPath = localizedCommandData.getLocalizedPath();
            final String description = localizedCommandData.getLocalizedDescription();
            Checks.check(localizedPath.getNameCount() == notLocalizedPath.getNameCount(), "Localized path does not have the same name count as the not-localized path");
            final boolean isDefaultEnabled = isDefaultEnabled(info);
            if (localizedPath.getNameCount() == 1) {
                // Standard command
                final SlashCommandData rightCommand = Commands.slash(localizedPath.getName(), description);
                map.put(Command.Type.SLASH, localizedPath, rightCommand);
                rightCommand.addOptions(localizedMethodOptions);
                rightCommand.setDefaultEnabled(isDefaultEnabled);
            } else if (localizedPath.getNameCount() == 2) {
                Checks.notNull(localizedPath.getSubname(), "Subcommand name");
                final SlashCommandData commandData = (SlashCommandData) map.computeIfAbsent(Command.Type.SLASH, localizedPath, x -> {
                    final SlashCommandData tmpData = Commands.slash(localizedPath.getName(), "No description (base name)");
                    tmpData.setDefaultEnabled(isDefaultEnabled);
                    return tmpData;
                });
                // Subcommand of a command
                final SubcommandData subcommandData = new SubcommandData(localizedPath.getSubname(), description);
                subcommandData.addOptions(localizedMethodOptions);
                commandData.addSubcommands(subcommandData);
            } else if (localizedPath.getNameCount() == 3) {
                Checks.notNull(localizedPath.getGroup(), "Command group name");
                Checks.notNull(localizedPath.getSubname(), "Subcommand name");
                final SubcommandGroupData groupData = getSubcommandGroup(Command.Type.SLASH, localizedPath, x -> {
                    final SlashCommandData commandData = Commands.slash(localizedPath.getName(), "No description (base name)");
                    commandData.setDefaultEnabled(isDefaultEnabled);
                    return commandData;
                });
                final SubcommandData subcommandData = new SubcommandData(localizedPath.getSubname(), description);
                subcommandData.addOptions(localizedMethodOptions);
                groupData.addSubcommands(subcommandData);
            } else {
                throw new IllegalStateException("A slash command with more than 4 path components got registered");
            }
            context.addApplicationCommandAlternative(localizedPath, Command.Type.SLASH, info);
            if (!info.isOwnerRequired()) {
                if (ownerOnlyCommands.contains(notLocalizedPath.getName())) {
                    LOGGER.warn("Non owner-only command '{}' is registered as a owner-only command because of another command with the same base name '{}'", notLocalizedPath, notLocalizedPath.getName());
                }
            }
            if (info.isOwnerRequired()) {
                if (info.isGuildOnly()) {
                    ownerOnlyCommands.add(notLocalizedPath.getName());
                } else {
                    LOGGER.warn("Owner-only command '{}' cannot be owner-only as it is a global command", notLocalizedPath);
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("An exception occurred while processing command '" + notLocalizedPath + "' at " + Utils.formatMethodShort(info.getMethod()), e);
        }
    });
}
Also used : java.util(java.util) Logging(com.freya02.botcommands.api.Logging) UserCommandInfo(com.freya02.botcommands.internal.application.context.user.UserCommandInfo) Command(net.dv8tion.jda.api.interactions.commands.Command) Function(java.util.function.Function) DebugBuilder(com.freya02.botcommands.api.builder.DebugBuilder) Guild(net.dv8tion.jda.api.entities.Guild) CommandPath(com.freya02.botcommands.api.application.CommandPath) CommandPrivilege(net.dv8tion.jda.api.interactions.commands.privileges.CommandPrivilege) Blocking(org.jetbrains.annotations.Blocking) Path(java.nio.file.Path) SettingsProvider(com.freya02.botcommands.api.SettingsProvider) SlashUtils.getLocalizedMethodOptions(com.freya02.botcommands.internal.application.slash.SlashUtils.getLocalizedMethodOptions) Checks(net.dv8tion.jda.internal.utils.Checks) Logger(org.slf4j.Logger) BContextImpl(com.freya02.botcommands.internal.BContextImpl) Utils(com.freya02.botcommands.internal.utils.Utils) MessageCommandInfo(com.freya02.botcommands.internal.application.context.message.MessageCommandInfo) Files(java.nio.file.Files) StandardOpenOption(java.nio.file.StandardOpenOption) IOException(java.io.IOException) Collectors(java.util.stream.Collectors) net.dv8tion.jda.api.interactions.commands.build(net.dv8tion.jda.api.interactions.commands.build) Nullable(org.jetbrains.annotations.Nullable) SlashUtils.appendCommands(com.freya02.botcommands.internal.application.slash.SlashUtils.appendCommands) SlashCommandInfo(com.freya02.botcommands.internal.application.slash.SlashCommandInfo) CommandListUpdateAction(net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction) NotNull(org.jetbrains.annotations.NotNull) SlashCommandInfo(com.freya02.botcommands.internal.application.slash.SlashCommandInfo) IOException(java.io.IOException) CommandPath(com.freya02.botcommands.api.application.CommandPath)

Example 3 with Description

use of com.freya02.botcommands.api.prefixed.annotations.Description in project BotCommands by freya022.

the class LocalizationData method getData.

public static LocalizationData getData(BContext context, @Nullable Guild guild, @NotNull ApplicationCommandInfo info) {
    final CommandPath localizedPath;
    final String localizedDescription;
    final List<LocalizedOption> localizedOptions;
    final List<List<Command.Choice>> localizedChoices;
    final Locale locale = context.getEffectiveLocale(guild);
    final BResourceBundle bundle = BResourceBundle.getBundle("BotCommands", locale);
    if (bundle == null) {
        return null;
    }
    final String prefix;
    if (info instanceof SlashCommandInfo) {
        prefix = "slash";
    } else if (info instanceof UserCommandInfo) {
        prefix = "user";
    } else if (info instanceof MessageCommandInfo) {
        prefix = "message";
    } else {
        throw new IllegalArgumentException("Unknown localization prefix for class: " + info.getClass().getSimpleName());
    }
    final String qualifier = info.getMethod().getName();
    final StringJoiner pathJoiner = new StringJoiner("/");
    pathJoiner.add(tryLocalize(bundle, info.getPath().getName(), prefix, qualifier, "name"));
    if (info instanceof SlashCommandInfo) {
        final String notLocalizedGroup = info.getPath().getGroup();
        final String notLocalizedSubname = info.getPath().getSubname();
        if (notLocalizedGroup != null)
            pathJoiner.add(tryLocalize(bundle, notLocalizedGroup, prefix, qualifier, "group"));
        if (notLocalizedSubname != null)
            pathJoiner.add(tryLocalize(bundle, notLocalizedSubname, prefix, qualifier, "subname"));
    }
    localizedPath = CommandPath.of(pathJoiner.toString());
    if (info instanceof SlashCommandInfo) {
        localizedDescription = tryLocalize(bundle, ((SlashCommandInfo) info).getDescription(), prefix, qualifier, "description");
    } else
        localizedDescription = null;
    if (info instanceof SlashCommandInfo) {
        localizedOptions = new ArrayList<>();
        localizedChoices = new ArrayList<>();
        final List<List<Command.Choice>> notLocalizedChoices = SlashUtils.getNotLocalizedChoices(context, guild, info);
        final List<? extends ApplicationCommandParameter<?>> parameters = info.getOptionParameters();
        for (int optionIndex = 0, parametersSize = parameters.size(); optionIndex < parametersSize; optionIndex++) {
            ApplicationCommandParameter<?> parameter = parameters.get(optionIndex);
            final ApplicationOptionData optionData = parameter.getApplicationOptionData();
            final String optionName = tryLocalize(bundle, optionData.getEffectiveName(), prefix, qualifier, "options", optionIndex, "name");
            final String optionDescription = tryLocalize(bundle, optionData.getEffectiveDescription(), prefix, qualifier, "options", optionIndex, "description");
            localizedOptions.add(new LocalizedOption(optionName, optionDescription));
            final List<Command.Choice> choices = getLocalizedChoices(bundle, prefix, qualifier, notLocalizedChoices, optionIndex, parameter);
            localizedChoices.add(choices);
        }
    } else {
        localizedOptions = null;
        localizedChoices = null;
    }
    return new LocalizationData(localizedPath, localizedDescription, localizedOptions, localizedChoices);
}
Also used : Locale(java.util.Locale) SlashCommandInfo(com.freya02.botcommands.internal.application.slash.SlashCommandInfo) LocalizedOption(com.freya02.botcommands.internal.application.LocalizedCommandData.LocalizedOption) ApplicationOptionData(com.freya02.botcommands.internal.ApplicationOptionData) BResourceBundle(com.freya02.botcommands.internal.utils.BResourceBundle) MessageCommandInfo(com.freya02.botcommands.internal.application.context.message.MessageCommandInfo) Command(net.dv8tion.jda.api.interactions.commands.Command) ArrayList(java.util.ArrayList) List(java.util.List) UserCommandInfo(com.freya02.botcommands.internal.application.context.user.UserCommandInfo) CommandPath(com.freya02.botcommands.api.application.CommandPath) StringJoiner(java.util.StringJoiner)

Example 4 with Description

use of com.freya02.botcommands.api.prefixed.annotations.Description in project BotCommands by freya022.

the class ApplicationCommandsUpdater method getSubcommandGroup.

// I am aware that the type is always Command.Type#SLASH, still use a parameter to mimic how ApplicationCommandMap functions and for future proof uses
@SuppressWarnings("SameParameterValue")
@NotNull
private SubcommandGroupData getSubcommandGroup(Command.Type type, CommandPath path, Function<String, CommandData> baseCommandSupplier) {
    if (path.getGroup() == null)
        throw new IllegalArgumentException("Group component of command path is null at '" + path + "'");
    final SlashCommandData data = (SlashCommandData) map.computeIfAbsent(type, path, baseCommandSupplier);
    final CommandPath parent = path.getParent();
    if (parent == null)
        throw new IllegalStateException("A command path with less than 3 components was passed to #getSubcommandGroup");
    return subcommandGroupDataMap.computeIfAbsent(parent.getFullPath(), s -> {
        final SubcommandGroupData groupData = new SubcommandGroupData(path.getGroup(), "No description (group)");
        data.addSubcommandGroups(groupData);
        return groupData;
    });
}
Also used : CommandPath(com.freya02.botcommands.api.application.CommandPath) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with Description

use of com.freya02.botcommands.api.prefixed.annotations.Description in project BotCommands by freya022.

the class LocalizedCommandData method of.

public static LocalizedCommandData of(@NotNull BContext context, @Nullable Guild guild, @NotNull ApplicationCommandInfo info) {
    final LocalizationData data = LocalizationData.getData(context, guild, info);
    final CommandPath localizedPath;
    if (data != null) {
        localizedPath = data.getLocalizedPath();
    } else {
        localizedPath = info.getPath();
    }
    if (!(info instanceof SlashCommandInfo))
        return new LocalizedCommandData(localizedPath, "No description", Collections.emptyList(), Collections.emptyList());
    final String localizedDescription;
    final List<LocalizedOption> localizedOptions;
    final List<List<Command.Choice>> localizedChoices;
    if (data != null && data.getLocalizedDescription() != null) {
        localizedDescription = data.getLocalizedDescription();
    } else {
        localizedDescription = ((SlashCommandInfo) info).getDescription();
    }
    if (data != null && data.getLocalizedOptions() != null) {
        localizedOptions = data.getLocalizedOptions();
    } else {
        localizedOptions = info.getOptionParameters().stream().filter(CommandParameter::isOption).map(ApplicationCommandParameter::getApplicationOptionData).map(a -> new LocalizedOption(a.getEffectiveName(), a.getEffectiveDescription())).collect(Collectors.toList());
    }
    if (data != null && data.getLocalizedChoices() != null) {
        localizedChoices = data.getLocalizedChoices();
    } else {
        localizedChoices = SlashUtils.getNotLocalizedChoices(context, guild, info);
    }
    return new LocalizedCommandData(localizedPath, localizedDescription, localizedOptions, localizedChoices);
}
Also used : SlashCommandInfo(com.freya02.botcommands.internal.application.slash.SlashCommandInfo) Command(net.dv8tion.jda.api.interactions.commands.Command) List(java.util.List) CommandPath(com.freya02.botcommands.api.application.CommandPath)

Aggregations

CommandPath (com.freya02.botcommands.api.application.CommandPath)4 SlashCommandInfo (com.freya02.botcommands.internal.application.slash.SlashCommandInfo)3 Command (net.dv8tion.jda.api.interactions.commands.Command)3 NotNull (org.jetbrains.annotations.NotNull)3 Logging (com.freya02.botcommands.api.Logging)2 MessageCommandInfo (com.freya02.botcommands.internal.application.context.message.MessageCommandInfo)2 UserCommandInfo (com.freya02.botcommands.internal.application.context.user.UserCommandInfo)2 java.util (java.util)2 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 Nullable (org.jetbrains.annotations.Nullable)2 Logger (org.slf4j.Logger)2 BasicSettingsProvider (com.freya02.bot.wiki.slash.BasicSettingsProvider)1 SettingsProvider (com.freya02.botcommands.api.SettingsProvider)1 DebugBuilder (com.freya02.botcommands.api.builder.DebugBuilder)1 Emoji (com.freya02.botcommands.api.entities.Emoji)1 EmojiOrEmote (com.freya02.botcommands.api.entities.EmojiOrEmote)1 QuotableRegexParameterResolver (com.freya02.botcommands.api.parameters.QuotableRegexParameterResolver)1 BaseCommandEvent (com.freya02.botcommands.api.prefixed.BaseCommandEvent)1 Category (com.freya02.botcommands.api.prefixed.annotations.Category)1