Skip to content

Commit e6ae978

Browse files
authored
Update to v8.0.0 (#23)
* Remove deprecated parts of the code * Fix argument identification in autocompletes * Handle limitations of options * Limit concatenation to InputArguments * Add action listener to SubArgument * Update example
1 parent 11383c8 commit e6ae978

File tree

8 files changed

+156
-134
lines changed

8 files changed

+156
-134
lines changed

src/main/java/me/s3ns3iw00/jcommands/Command.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import me.s3ns3iw00.jcommands.argument.Argument;
2222
import me.s3ns3iw00.jcommands.argument.InputArgument;
23+
import me.s3ns3iw00.jcommands.argument.SubArgument;
2324
import me.s3ns3iw00.jcommands.argument.concatenation.Concatenator;
2425
import me.s3ns3iw00.jcommands.event.listener.ArgumentMismatchEventListener;
2526
import me.s3ns3iw00.jcommands.event.listener.CommandActionEventListener;
@@ -39,15 +40,14 @@ public class Command {
3940
*/
4041
private final String name, description;
4142
private final LinkedList<Argument> arguments = new LinkedList<>();
42-
private final Map<Concatenator, LinkedList<Argument>> concatenators = new LinkedHashMap<>();
43+
private final Map<Concatenator, LinkedList<InputArgument>> concatenators = new LinkedHashMap<>();
4344

4445
private final Set<PermissionType> defaultPermissions = new HashSet<>();
4546

4647
private boolean onlyForAdministrators = false;
4748
private boolean nsfw = false;
4849

4950
private CommandActionEventListener actionListener;
50-
private ArgumentMismatchEventListener argumentMismatchListener;
5151

5252
/**
5353
* Default constructor
@@ -69,7 +69,7 @@ public Command(String name, String description) {
6969
throw new IllegalArgumentException("Command's name is invalid, it should contain only word characters, '-' and '_' character, and its length must between 1 and 32");
7070
}
7171

72-
if (description.length() < 1 || description.length() > 100) {
72+
if (description.isEmpty() || description.length() > 100) {
7373
throw new IllegalArgumentException("Description's length must between 1 and 100");
7474
}
7575
}
@@ -80,11 +80,25 @@ public Command(String name, String description) {
8080
* @param argument the argument
8181
*/
8282
public void addArgument(Argument argument) {
83-
if (arguments.size() > 0 &&
84-
(arguments.getLast() instanceof InputArgument) &&
85-
((InputArgument) arguments.getLast()).isOptional() &&
86-
!((InputArgument) argument).isOptional()) {
87-
throw new IllegalStateException("Cannot add non-optional argument after an optional argument!");
83+
if (!arguments.isEmpty()) {
84+
// Unique name checking
85+
if (arguments.stream().anyMatch(arg -> arg.getName().equals(argument.getName()))) {
86+
throw new IllegalStateException("Arguments must have unique name in the same scope!");
87+
}
88+
89+
// SubArgument and InputArgument mix checking
90+
if ((argument instanceof SubArgument && arguments.stream().anyMatch(arg -> arg instanceof InputArgument)) ||
91+
(argument instanceof InputArgument && arguments.stream().anyMatch(arg -> arg instanceof SubArgument))) {
92+
throw new IllegalStateException("SubArguments and InputArguments cannot be mixed in the same scope!");
93+
}
94+
95+
// Optional and non-optional argument order checking
96+
if (argument instanceof InputArgument &&
97+
!((InputArgument) argument).isOptional() &&
98+
arguments.getLast() instanceof InputArgument &&
99+
((InputArgument) arguments.getLast()).isOptional()) {
100+
throw new IllegalStateException("Cannot add non-optional argument after an optional argument!");
101+
}
88102
}
89103

90104
this.arguments.add(argument);
@@ -106,7 +120,7 @@ public void addArgument(Argument... arguments) {
106120
* @param concatenator the concatenator
107121
* @param arguments the list of arguments
108122
*/
109-
public void addConcatenator(Concatenator concatenator, Argument... arguments) {
123+
public void addConcatenator(Concatenator concatenator, InputArgument... arguments) {
110124
if (!concatenators.containsKey(concatenator)) {
111125
concatenators.put(concatenator, new LinkedList<>());
112126
}
@@ -171,7 +185,7 @@ public List<Argument> getArguments() {
171185
/**
172186
* @return the map of concatenators
173187
*/
174-
public Map<Concatenator, LinkedList<Argument>> getConcatenators() {
188+
public Map<Concatenator, LinkedList<InputArgument>> getConcatenators() {
175189
return concatenators;
176190
}
177191

src/main/java/me/s3ns3iw00/jcommands/CommandHandler.java

Lines changed: 65 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.javacord.api.interaction.*;
4040

4141
import java.util.*;
42+
import java.util.concurrent.atomic.AtomicInteger;
4243
import java.util.function.Predicate;
4344
import java.util.stream.Collectors;
4445

@@ -150,6 +151,15 @@ private static void handleCommand(SlashCommandInteraction interaction) {
150151
}
151152
}
152153

154+
AtomicInteger i = new AtomicInteger(0);
155+
resultOptional.get().keySet().forEach(argument -> {
156+
if (argument instanceof SubArgument) {
157+
List<ArgumentResult> subResults = results.subList(i.incrementAndGet(), results.size());
158+
159+
((SubArgument<?, ?>) argument).getActionListener().ifPresent(listener -> listener.onAction(new CommandActionEvent(command, sender,
160+
new CommandResponder(interaction), channel.orElse(null), subResults.toArray(new ArgumentResult[0]))));
161+
}
162+
});
153163
command.getActionListener().ifPresent(listener -> listener.onAction(new CommandActionEvent(command, sender,
154164
new CommandResponder(interaction), channel.orElse(null), results.toArray(new ArgumentResult[0]))));
155165
}
@@ -171,44 +181,62 @@ private static void handleAutocomplete(AutocompleteInteraction interaction) {
171181

172182
User sender = interaction.getUser();
173183
Optional<TextChannel> channel = interaction.getChannel();
174-
List<Argument> allArguments = collectArguments(command.getArguments());
175-
Optional<Argument> argumentOptional = allArguments.stream()
176-
.filter(arg -> arg.getName().equalsIgnoreCase(option.getName()))
177-
.findFirst();
178-
argumentOptional.ifPresent(argument -> {
179-
if (argument instanceof AutocompletableInputArgument) {
180-
AutocompletableInputArgument<?, ?> autocompletable = (AutocompletableInputArgument) argument;
181-
AutocompleteState autocompleteState = new AutocompleteState(
182-
command,
183-
channel.orElse(null),
184-
sender,
185-
argument,
186-
getOptionValue(option, argument.getType()),
187-
interaction.getArguments().stream()
188-
.collect(Collectors.toMap(
189-
key -> allArguments.stream()
190-
.filter(arg -> arg.getName().equalsIgnoreCase(key.getName()))
191-
.findFirst().orElse(null),
192-
value -> value
193-
))
194-
.entrySet().stream()
195-
.collect(Collectors.toMap(
196-
Map.Entry::getKey,
197-
value -> getOptionValue(value.getValue(), value.getKey().getType())
198-
)));
199-
200-
/* Collect results from autocompletes and construct the list */
201-
List<Choice> choices = autocompletable.getAutocompletes().stream()
202-
.map(autocomplete -> autocomplete.getResult(autocompleteState))
203-
.filter(Objects::nonNull)
204-
.flatMap(List::stream)
205-
.collect(Collectors.toList());
206-
207-
if (choices.size() > 0) {
208-
interaction.respondWithChoices(choices.stream().map(Choice::getChoice).collect(Collectors.toList()));
209-
}
184+
185+
// Going through options and arguments to identify the proper subcommand that contains the argument
186+
List<Argument> arguments = command.getArguments();
187+
List<SlashCommandInteractionOption> options = interaction.getOptions();
188+
Map<Argument, Optional<?>> argumentValues = new HashMap<>();
189+
while (!options.get(0).getOptions().isEmpty()) {
190+
SlashCommandInteractionOption firstOption = options.get(0);
191+
SubArgument subArgument = (SubArgument) arguments.stream()
192+
.filter(argument -> argument.getName().equals(firstOption.getName()))
193+
.findFirst()
194+
.orElse(null);
195+
196+
argumentValues.put(subArgument, Optional.of(subArgument.getName()));
197+
198+
arguments = subArgument.getArguments();
199+
options = options.get(0).getOptions();
200+
}
201+
202+
// Identifying argument and collecting specified values
203+
Argument argument = null;
204+
for (Argument arg : arguments) {
205+
if (arg.getName().equals(option.getName())) {
206+
argument = arg;
210207
}
211-
});
208+
argumentValues.put(
209+
arg,
210+
getOptionValue(
211+
options.stream()
212+
.filter(opt -> opt.getName().equals(arg.getName()))
213+
.findFirst()
214+
.orElse(null),
215+
arg.getType()
216+
)
217+
);
218+
}
219+
220+
AutocompletableInputArgument<?, ?> autocompletable = (AutocompletableInputArgument) argument;
221+
AutocompleteState autocompleteState = new AutocompleteState(
222+
command,
223+
channel.orElse(null),
224+
sender,
225+
argument,
226+
getOptionValue(option, argument.getType()),
227+
argumentValues
228+
);
229+
230+
/* Collect results from autocompletes and construct the list */
231+
List<Choice> choices = autocompletable.getAutocompletes().stream()
232+
.map(autocomplete -> autocomplete.getResult(autocompleteState))
233+
.filter(Objects::nonNull)
234+
.flatMap(List::stream)
235+
.collect(Collectors.toList());
236+
237+
if (choices.size() > 0) {
238+
interaction.respondWithChoices(choices.stream().map(Choice::getChoice).collect(Collectors.toList()));
239+
}
212240
});
213241
}
214242

@@ -317,20 +345,6 @@ private static Optional<?> getOptionValue(SlashCommandInteractionOption option,
317345
}
318346
}
319347

320-
/**
321-
* Returns the {@link Argument} of {@link Command} by {@link SlashCommandInteractionOption}
322-
*
323-
* @param command the command
324-
* @param option the option
325-
* @return an {@link Optional} with the {@link Argument} in it if found,
326-
* otherwise an empty {@link Optional}
327-
*/
328-
private static Optional<Argument> getArgumentByOption(Command command, SlashCommandInteractionOption option) {
329-
return collectArguments(command.getArguments()).stream()
330-
.filter(arg -> arg.getName().equalsIgnoreCase(option.getName()))
331-
.findFirst();
332-
}
333-
334348
/**
335349
* Collects all arguments of a list of arguments in one list
336350
* For collecting a command's all arguments {@link Command#getArguments()} need to be passed as parameter
@@ -521,17 +535,6 @@ public static boolean isCommandExist(Server server, String cmd) {
521535
return false;
522536
}
523537

524-
/**
525-
* Registers a converter for the given type
526-
*
527-
* @param clazz the class of the type
528-
* @param converter the converter
529-
*
530-
* @deprecated use {@link InputArgument#convertResult(ArgumentResultConverter)}
531-
*/
532-
@Deprecated
533-
public static void registerArgumentConverter(Class<?> clazz, ArgumentResultConverter converter) {}
534-
535538
/**
536539
* @return the discord api
537540
*/

src/main/java/me/s3ns3iw00/jcommands/argument/Argument.java

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,9 @@
1818
*/
1919
package me.s3ns3iw00.jcommands.argument;
2020

21-
import me.s3ns3iw00.jcommands.event.listener.ArgumentMismatchEventListener;
2221
import org.javacord.api.interaction.SlashCommandOption;
2322
import org.javacord.api.interaction.SlashCommandOptionType;
2423

25-
import java.util.Optional;
26-
2724
/**
2825
* Represents an argument
2926
*
@@ -54,10 +51,10 @@ public Argument(String name, String description, SlashCommandOptionType type) {
5451
this.type = type;
5552

5653
if (!name.matches("^[-_\\p{L}\\p{N}\\p{sc=Deva}\\p{sc=Thai}]{1,32}$")) {
57-
throw new IllegalArgumentException("Command's name is invalid, it should contain only word characters, '-' and '_' character, and its length must between 1 and 32");
54+
throw new IllegalArgumentException("Argument's name is invalid, it should contain only word characters, '-' and '_' character, and its length must between 1 and 32");
5855
}
5956

60-
if (description.length() < 1 || description.length() > 100) {
57+
if (description.isEmpty() || description.length() > 100) {
6158
throw new IllegalArgumentException("Description's length must between 1 and 100");
6259
}
6360
}
@@ -93,26 +90,4 @@ public SlashCommandOptionType getType() {
9390
*/
9491
public abstract SlashCommandOption getCommandOption();
9592

96-
/**
97-
* Sets the argument mismatch listener
98-
*
99-
* @param listener the listener
100-
*/
101-
@Deprecated
102-
public void setOnMismatch(ArgumentMismatchEventListener listener) {
103-
//this.mismatchListener = listener;
104-
}
105-
106-
/**
107-
* Gets the argument mismatch listener
108-
*
109-
* @return {@link Optional#empty()} when argument mismatch listener is not specified,
110-
* otherwise {@link Optional#of(Object)} with the listener
111-
*/
112-
@Deprecated
113-
public Optional<ArgumentMismatchEventListener> getMismatchListener() {
114-
//return Optional.ofNullable(mismatchListener);
115-
return Optional.empty();
116-
}
117-
11893
}

src/main/java/me/s3ns3iw00/jcommands/argument/SubArgument.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
*/
1919
package me.s3ns3iw00.jcommands.argument;
2020

21+
import me.s3ns3iw00.jcommands.event.listener.CommandActionEventListener;
2122
import org.javacord.api.interaction.SlashCommandOptionType;
2223

2324
import java.util.LinkedList;
25+
import java.util.Optional;
2426

2527
/**
2628
* Represents a sub argument
@@ -32,6 +34,8 @@ public abstract class SubArgument<T extends Argument, R> extends Argument<R> {
3234

3335
private final LinkedList<T> arguments = new LinkedList<>();
3436

37+
private CommandActionEventListener actionListener;
38+
3539
/**
3640
* Constructs the argument with the default requirements
3741
*
@@ -53,4 +57,24 @@ public LinkedList<T> getArguments() {
5357
* @param argument the argument
5458
*/
5559
public abstract void addArgument(T argument);
60+
61+
/**
62+
* Gets the action listener
63+
*
64+
* @return {@link Optional#empty()} when action listener is not specified,
65+
* otherwise {@link Optional#ofNullable(Object)} with the listener
66+
*/
67+
public Optional<CommandActionEventListener> getActionListener() {
68+
return Optional.ofNullable(actionListener);
69+
}
70+
71+
/**
72+
* Sets the action listener
73+
*
74+
* @param listener the listener
75+
*/
76+
public void setOnAction(CommandActionEventListener listener) {
77+
this.actionListener = listener;
78+
}
79+
5680
}

src/main/java/me/s3ns3iw00/jcommands/argument/type/ConstantArgument.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,17 @@ public SlashCommandOption getCommandOption() {
5454
* @param argument the argument
5555
*/
5656
public void addArgument(InputArgument argument) {
57-
if (getArguments().size() > 0 &&
58-
(getArguments().getLast() != null) &&
59-
getArguments().getLast().isOptional() &&
60-
!argument.isOptional()) {
61-
throw new IllegalStateException("Cannot add non-optional argument after an optional argument!");
57+
if (!getArguments().isEmpty()) {
58+
// Unique name checking
59+
if (getArguments().stream().anyMatch(arg -> arg.getName().equals(argument.getName()))) {
60+
throw new IllegalStateException("Arguments must have unique name in the same scope!");
61+
}
62+
63+
// Optional and non-optional argument order checking
64+
if (!argument.isOptional() &&
65+
getArguments().getLast().isOptional()) {
66+
throw new IllegalStateException("Cannot add non-optional argument after an optional argument!");
67+
}
6268
}
6369

6470
getArguments().add(argument);

0 commit comments

Comments
 (0)