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;
}
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);
}
});
}
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);
}
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;
});
}
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);
}
Aggregations