Command processor testing

This commit is contained in:
anthorob committed 2025-10-27 07:08:56 +00:00
1 parent c19287d580
commit 6fc3dc9577
6 files changed
+1142 -27

No files matched your search

@@ -70,8 +70,8 @@ public class NetNeutrality {
throw new RuntimeException("No bot token provided, exiting.");
}
DatabaseMigration.migrate();
SessionManager.getSessionFactory();
DatabaseMigration.migrate();
CommandManager.init();
MusicManager.initPlayerManager();
TaskManager.getInstance().init();
@@ -58,6 +58,7 @@ public class MessageCommandContext extends CommandContext implements MessageCont
@Override
public List<CommandOption> parseOptions(String[] args, List<OptionData> commandOptions) {
List<CommandOption> options = new ArrayList<>();
int required = commandOptions.stream().filter(OptionData::isRequired).toList().size();
Mentions mentions = message.getMentions();
int roleMentionIndex = 0;
int userMentionIndex = 0;
@@ -74,13 +75,59 @@ public class MessageCommandContext extends CommandContext implements MessageCont
try {
switch (type) {
case STRING -> {
String str = args[index];
int currentOptionIndex = commandOptions.indexOf(data);
boolean nextOptionIsString = false;
if (currentOptionIndex + 1 < commandOptions.size()) {
OptionData nextOption = commandOptions.get(currentOptionIndex + 1);
nextOptionIsString = nextOption.getType() == OptionType.STRING;
}
if ((str.contains("<@") || str.contains("<#")) && str.contains(">")) {
invalidateContext(data, "expected a string at position " + (index + 1) + " but a role/user/channel was provided");
StringBuilder strBuilder = new StringBuilder();
if (!nextOptionIsString) {
while (index < args.length) {
String nextArg = args[index];
if ((nextArg.contains("<@") || nextArg.contains("<#") || nextArg.contains("<@&")) && nextArg.contains(">")) {
break;
}
if (nextArg.equalsIgnoreCase("true") || nextArg.equalsIgnoreCase("false")) {
break;
}
try {
Long.parseLong(nextArg);
break;
} catch (NumberFormatException ignored) {}
try {
Double.parseDouble(nextArg);
break;
} catch (NumberFormatException ignored) {}
if (!strBuilder.isEmpty()) {
strBuilder.append(" ");
}
strBuilder.append(nextArg);
index++;
}
// Update index to skip the concatenated strings
index = index - 1;
} else {
// Next option is also a string, so just take the current argument
if (index < args.length) {
strBuilder.append(args[index]);
}
}
if (strBuilder.isEmpty()) {
break;
}
String str = strBuilder.toString();
if (!choices.isEmpty()) {
List<Command.Choice> matched = choices.stream().filter(choice -> choice.getAsString().equalsIgnoreCase(str)).toList();
if (matched.isEmpty()) {
@@ -119,8 +166,6 @@ public class MessageCommandContext extends CommandContext implements MessageCont
} else if (max != null && num > max.longValue()) {
value = max.longValue();
}
value = num;
}
case BOOLEAN -> {
String str = args[index];
@@ -132,7 +177,7 @@ public class MessageCommandContext extends CommandContext implements MessageCont
invalidateContext(data, "expected true or false");
}
case NUMBER -> {
double num = Long.parseLong(args[index]);
double num = Double.parseDouble(args[index]);
if (!choices.isEmpty()) {
List<Command.Choice> matched = choices.stream().filter(choice -> choice.getAsDouble() == num).toList();
if (matched.isEmpty()) {
@@ -209,7 +254,7 @@ public class MessageCommandContext extends CommandContext implements MessageCont
if (mentions.getChannels().size() > channelMentionIndex) {
GuildChannel channel = mentions.getChannels().get(channelMentionIndex++);
if (!requiredChannelTypes.contains(channel.getType())) {
if (!requiredChannelTypes.isEmpty() && !requiredChannelTypes.contains(channel.getType())) {
invalidateContext(data, "not a valid channel type at index " + (index + 1) +
" , valid types are: " + validTypes(requiredChannelTypes));
break;
@@ -225,7 +270,11 @@ public class MessageCommandContext extends CommandContext implements MessageCont
}
}
} catch (IndexOutOfBoundsException e) {
if (data.isRequired()) {
if (options.size() < required) {
invalidateContext(data, "missing required argument at index " + (index + 1));
}
if (data.isRequired() && index < required) {
// This should never happen because required options are validated before calling parseOptions()
throw new IllegalArgumentException("Required option " + data.getName() + " was not found at index " + index);
}
@@ -240,6 +289,13 @@ public class MessageCommandContext extends CommandContext implements MessageCont
index++;
}
// Check if there are leftover arguments that weren't consumed
if (index < args.length) {
if (options.size() >= required) {
invalidateContext(commandOptions.getLast(), "too many arguments");
}
}
return options;
}
@@ -14,7 +14,6 @@ import me.bobert.netneutrality.core.tasks.TaskManager;
import me.bobert.netneutrality.exceptions.CommandExecutionException;
import me.bobert.netneutrality.exceptions.GracefulContextError;
import me.bobert.netneutrality.utils.UserFunction;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandGroupData;
@@ -204,22 +203,6 @@ public class CommandProcessor {
return false;
}
// check if last option is a string, if it is then combine all remaining strings into one
// ["@user", "you", "are", "banned"] becomes ["@user", "you are banned"]
if (!options.isEmpty() && arguments.size() > 1) {
OptionData last = options.get(options.size() - 1);
if (last.getType() == OptionType.STRING) {
List<String> lastArgs = arguments.stream().skip(options.size() - 1).toList();
arguments.removeAll(lastArgs);
arguments.add(String.join(" ", lastArgs));
}
}
if (arguments.size() > required + optional) {
context.reply(invalidUsage("too many arguments"));
return false;
}
context.setCurrentCommandOptions(arguments.toArray(String[]::new), options);
return true;
}
@@ -120,6 +120,10 @@ public class MessageCommandOption implements CommandOption {
@Override
public User getAsUser() {
if (value instanceof Member) {
return ((Member) value).getUser();
}
if (value instanceof User) {
return (User) value;
}
File diff suppressed because it is too large. Load diff