fix: add missing checks for command usage

This commit is contained in:
anthorob committed 2024-12-18 11:44:23 -05:00
1 parent 9861fac769
commit 96e31a19ec
1 file changed
+55 -30
@@ -61,7 +61,7 @@ public class CommandProcessor {
}
try {
logger.info("Context ID: {}", context.getId());
logger.info("{} ID: {}", context.getClass().getSimpleName(), context.getId());
logger.info("Executing command {} on guild {}", command.getCommandName(), context.getGuild() == null ? "PrivateMessage" : context.getGuild().getId());
configureSentry(command);
@@ -110,46 +110,68 @@ public class CommandProcessor {
}
private boolean checkUsage(CommandOptions commandOptions) {
List<SubcommandGroupData> groups = commandOptions.getSubcommandGroups();
List<SubcommandData> subcommands = commandOptions.getSubcommands();
List<OptionData> options = commandOptions.getOptions();
String[] possibleCommands = Arrays.stream(context.getFullCommand().split(" ")).skip(1).toArray(String[]::new);
if (possibleCommands.length == 0) {
if (!commandOptions.getSubcommandGroups().isEmpty()) {
context.reply(String.format("Invalid usage for command: missing subcommand.\n" +
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName()));
if (!groups.isEmpty()) {
// missing subcommand group
context.reply(invalidUsage("missing subcommand group"));
return false;
}
if (!commandOptions.getSubcommands().isEmpty()) {
context.reply(String.format("Invalid usage for command: missing subcommand.\n" +
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName()));
if (!subcommands.isEmpty()) {
// missing subcommand
context.reply(invalidUsage("missing subcommand"));
return false;
}
return checkOptions(possibleCommands, 0, commandOptions.getOptions());
return checkOptions(possibleCommands, 0, options);
}
SubcommandGroupData group = commandOptions.getSubcommandGroups().stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
if (group != null) {
if (possibleCommands.length < 2) {
context.reply(String.format("Invalid usage for command: missing subcommand.\n" +
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName()));
return false; // missing subcommand
SubcommandGroupData group = groups.stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
if (group == null) {
SubcommandData subcommand = subcommands.stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
if (subcommand == null) {
if (!groups.isEmpty()) {
// no group found but one is expected
context.reply(invalidUsage("unknown subcommand group"));
return false;
}
if (!subcommands.isEmpty()) {
// no subcommand found but one is expected
context.reply(invalidUsage("unknown subcommand"));
return false;
}
// no group found, no subcommand found, command with options only
return checkOptions(possibleCommands, 0, options);
}
SubcommandData subcommand = group.getSubcommands().stream().filter(data -> data.getName().equals(possibleCommands[1])).findFirst().orElse(null);
if (subcommand != null) {
context.setSubcommandGroup(group);
context.setSubcommand(subcommand);
return checkOptions(possibleCommands, 2, subcommand.getOptions());
}
}
SubcommandData subcommand = commandOptions.getSubcommands().stream().filter(data -> data.getName().equals(possibleCommands[0])).findFirst().orElse(null);
if (subcommand != null) {
// no group found, subcommand found
context.setSubcommand(subcommand);
return checkOptions(possibleCommands, 1, subcommand.getOptions());
}
return checkOptions(possibleCommands, 0, commandOptions.getOptions());
if (possibleCommands.length < 2) {
// missing subcommand for group
context.reply(invalidUsage("missing subcommand for command group"));
return false;
}
SubcommandData subcommand = group.getSubcommands().stream().filter(data -> data.getName().equals(possibleCommands[1])).findFirst().orElse(null);
if (subcommand == null) {
// group found, no subcommand found
context.reply(invalidUsage("unknown subcommand in command group"));
return false;
}
// group found, subcommand found
context.setSubcommandGroup(group);
context.setSubcommand(subcommand);
return checkOptions(possibleCommands, 2, subcommand.getOptions());
}
private boolean checkOptions(String[] args, int skip, List<OptionData> options) {
@@ -163,8 +185,7 @@ public class CommandProcessor {
int optional = options.stream().filter(not(OptionData::isRequired)).toList().size();
if (arguments.size() < required) {
context.reply(String.format("Invalid usage for command: missing one or more required arguments\n" +
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName()));
context.reply(invalidUsage("missing one or more required arguments"));
return false;
}
@@ -180,8 +201,7 @@ public class CommandProcessor {
}
if (arguments.size() > required + optional) {
context.reply(String.format("Invalid usage for command: too many arguments\n" +
"Use **/help %s** for information on how to use this command", context.getCommand().getCommandName()));
context.reply(invalidUsage("too many arguments"));
return false;
}
@@ -195,7 +215,7 @@ public class CommandProcessor {
}
if (context instanceof SlashCommandContext) {
return true; // no further check since slash perms are handled by guild settings
return true; // no further checks since slash perms are handled by guild settings on discord
}
if (command.canBeExecutedBy(context.getGuildUser())) {
@@ -205,6 +225,11 @@ public class CommandProcessor {
return command.needAdmin() && UserFunction.isAdmin(context.getGuildUser());
}
private String invalidUsage(String message) {
return String.format("Invalid usage for command: %s\n" +
"Use **/help %s** for information on how to use this command", message, context.getCommand().getCommandName());
}
private void configureSentry(Command command) {
Sentry.configureScope(scope -> {
scope.setTag("command", command.getCommandName());