2222import me .s3ns3iw00 .jcommands .argument .ArgumentResult ;
2323import me .s3ns3iw00 .jcommands .argument .InputArgument ;
2424import me .s3ns3iw00 .jcommands .argument .SubArgument ;
25+ import me .s3ns3iw00 .jcommands .argument .ability .Autocompletable ;
26+ import me .s3ns3iw00 .jcommands .argument .autocomplete .AutocompleteState ;
2527import me .s3ns3iw00 .jcommands .argument .concatenation .Concatenator ;
2628import me .s3ns3iw00 .jcommands .argument .converter .ArgumentResultConverter ;
2729import me .s3ns3iw00 .jcommands .argument .converter .type .URLConverter ;
30+ import me .s3ns3iw00 .jcommands .argument .type .ComboArgument ;
31+ import me .s3ns3iw00 .jcommands .argument .util .Choice ;
2832import me .s3ns3iw00 .jcommands .builder .CommandBuilder ;
29- import me .s3ns3iw00 .jcommands .event .listener .ArgumentMismatchEventListener ;
30- import me .s3ns3iw00 .jcommands .event .listener .BadCategoryEventListener ;
31- import me .s3ns3iw00 .jcommands .event .listener .BadChannelEventListener ;
3233import me .s3ns3iw00 .jcommands .event .type .ArgumentMismatchEvent ;
3334import me .s3ns3iw00 .jcommands .event .type .BadCategoryEvent ;
3435import me .s3ns3iw00 .jcommands .event .type .BadChannelEvent ;
3839import me .s3ns3iw00 .jcommands .limitation .type .ChannelLimitable ;
3940import me .s3ns3iw00 .jcommands .limitation .type .RoleLimitable ;
4041import me .s3ns3iw00 .jcommands .limitation .type .UserLimitable ;
41- import me .s3ns3iw00 .jcommands .listener .CommandErrorListener ;
4242import org .javacord .api .DiscordApi ;
4343import org .javacord .api .entity .channel .ChannelCategory ;
4444import org .javacord .api .entity .channel .ChannelType ;
@@ -81,6 +81,7 @@ public class CommandHandler {
8181 public static void setApi (DiscordApi api ) {
8282 CommandHandler .api = api ;
8383 api .addSlashCommandCreateListener (event -> handleCommand (event .getSlashCommandInteraction ()));
84+ api .addAutocompleteCreateListener (event -> handleAutocomplete (event .getAutocompleteInteraction ()));
8485 }
8586
8687 /**
@@ -186,6 +187,62 @@ private static void handleCommand(SlashCommandInteraction interaction) {
186187 });
187188 }
188189
190+ /**
191+ * Handles autocomplete requests for arguments
192+ *
193+ * @param interaction the interaction
194+ */
195+ private static void handleAutocomplete (AutocompleteInteraction interaction ) {
196+ Optional <Command > commandOptional = commands .stream ()
197+ .filter (c -> c .getName ().equalsIgnoreCase (interaction .getCommandName ()))
198+ .findFirst ();
199+
200+ commandOptional .ifPresent (command -> {
201+ SlashCommandInteractionOption option = interaction .getFocusedOption ();
202+
203+ User sender = interaction .getUser ();
204+ Optional <TextChannel > channel = interaction .getChannel ();
205+ List <Argument > allArguments = collectArguments (command .getArguments ());
206+ Optional <Argument > argumentOptional = allArguments .stream ()
207+ .filter (arg -> arg .getName ().equalsIgnoreCase (option .getName ()))
208+ .findFirst ();
209+ argumentOptional .ifPresent (argument -> {
210+ if (argument instanceof Autocompletable ) {
211+ Autocompletable autocompletable = (Autocompletable ) argument ;
212+ AutocompleteState autocompleteState = new AutocompleteState (
213+ command ,
214+ channel .orElse (null ),
215+ sender ,
216+ argument ,
217+ getOptionValue (option , argument .getType ()),
218+ interaction .getArguments ().stream ()
219+ .collect (Collectors .toMap (
220+ key -> allArguments .stream ()
221+ .filter (arg -> arg .getName ().equalsIgnoreCase (key .getName ()))
222+ .findFirst ().orElse (null ),
223+ value -> value
224+ ))
225+ .entrySet ().stream ()
226+ .collect (Collectors .toMap (
227+ Map .Entry ::getKey ,
228+ value -> getOptionValue (value .getValue (), value .getKey ().getType ())
229+ )));
230+
231+ /* Collect results from autocompletes and construct the list */
232+ List <Choice > choices = autocompletable .getAutocompletes ().stream ()
233+ .map (autocomplete -> autocomplete .getResult (autocompleteState ))
234+ .filter (Objects ::nonNull )
235+ .flatMap (List ::stream )
236+ .collect (Collectors .toList ());
237+
238+ if (choices .size () > 0 ) {
239+ interaction .respondWithChoices (choices .stream ().map (Choice ::getChoice ).collect (Collectors .toList ()));
240+ }
241+ }
242+ });
243+ });
244+ }
245+
189246 /**
190247 * Processes arguments and every argument of the arguments recursively:
191248 * - Adjusts values to the arguments
@@ -221,6 +278,14 @@ private static Optional<Map<Argument, ArgumentResult>> processArguments(SlashCom
221278 } else {
222279 return Optional .empty ();
223280 }
281+ } else if (argument instanceof ComboArgument ) {
282+ /* Choose the value that the user picked
283+ Checking is unnecessary since the user only can pick a valid value
284+ */
285+ ComboArgument ca = (ComboArgument ) argument ;
286+
287+ ca .choose (value );
288+ results .put (argument , new ArgumentResult (ca ));
224289 } else if (argument instanceof InputArgument ) {
225290 /* Adjusts the value to the argument and checks that the value is null
226291 If it is not then it will be added to the list,
@@ -273,6 +338,9 @@ private static Object getOptionValue(SlashCommandInteractionOption option, Slash
273338 case LONG :
274339 value = option .getLongValue ().orElse (null );
275340 break ;
341+ case DECIMAL :
342+ value = option .getDecimalValue ().orElse (null );
343+ break ;
276344 case BOOLEAN :
277345 value = option .getBooleanValue ().orElse (null );
278346 break ;
@@ -282,6 +350,40 @@ private static Object getOptionValue(SlashCommandInteractionOption option, Slash
282350 return value ;
283351 }
284352
353+ /**
354+ * Returns the {@link Argument} of {@link Command} by {@link SlashCommandInteractionOption}
355+ *
356+ * @param command the command
357+ * @param option the option
358+ * @return an {@link Optional} with the {@link Argument} in it if found,
359+ * otherwise an empty {@link Optional}
360+ */
361+ private static Optional <Argument > getArgumentByOption (Command command , SlashCommandInteractionOption option ) {
362+ return collectArguments (command .getArguments ()).stream ()
363+ .filter (arg -> arg .getName ().equalsIgnoreCase (option .getName ()))
364+ .findFirst ();
365+ }
366+
367+ /**
368+ * Collects all arguments of a list of arguments in one list
369+ * For collecting a command's all arguments {@link Command#getArguments()} need to be passed as parameter
370+ *
371+ * @param arguments a list of argument
372+ * @return the collection
373+ */
374+ private static List <Argument > collectArguments (List <Argument > arguments ) {
375+ List <Argument > allArguments = new ArrayList <>();
376+ for (Argument argument : arguments ) {
377+ if (argument instanceof SubArgument ) {
378+ allArguments .addAll (collectArguments (((SubArgument ) argument ).getArguments ()));
379+ } else {
380+ allArguments .add (argument );
381+ }
382+ }
383+
384+ return allArguments ;
385+ }
386+
285387 /**
286388 * Registers the command for the listener on the specified servers
287389 * and sets up permissions with discord's default permission system
@@ -420,19 +522,6 @@ public static void registerCommand(CommandBuilder<?> builder) {
420522 registerCommand (builder .getCommand ());
421523 }
422524
423- /**
424- * Registers an error listener where the errors will be managed
425- *
426- * @param error the listener interface
427- * @deprecated because of the new event system
428- * use {@link CategoryLimitable#setOnBadCategory(BadCategoryEventListener)},
429- * {@link ChannelLimitable#setOnBadChannel(BadChannelEventListener)} and
430- * {@link Argument#setOnMismatch(ArgumentMismatchEventListener)} instead
431- */
432- @ Deprecated
433- public static void setOnError (CommandErrorListener error ) {
434- }
435-
436525 /**
437526 * @return the list of the commands
438527 */
0 commit comments