[AB-xxx] fixing combined parameters not providing the appropriate option types for slash commands

This commit is contained in:
Sheldan
2024-04-13 00:20:02 +02:00
parent 250df57bd0
commit dfe9792330
10 changed files with 125 additions and 12 deletions

View File

@@ -2,12 +2,12 @@ package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.CombinedParameterEntry;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.parameter.CombinedParameter;
import dev.sheldan.abstracto.core.command.handler.provided.CombinedParametersHandler;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
@@ -28,9 +28,6 @@ public class CombinedParameterHandlerImpl implements CombinedParametersHandler {
@Lazy
private List<CommandParameterHandler> parameterHandlers;
@Autowired
private MetricService metricService;
@Override
public boolean async() {
return true;
@@ -40,11 +37,16 @@ public class CombinedParameterHandlerImpl implements CombinedParametersHandler {
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
List<CompletableFuture<Object>> futures = new ArrayList<>();
CompletableFuture<Object> returningFuture = new CompletableFuture<>();
List<Object> possibleTypes = (List) param.getAdditionalInfo().get(Parameter.ADDITIONAL_TYPES_KEY);
for (Object concreteParameter: possibleTypes) {
List<CombinedParameterEntry> combinedParameterEntries = (List) param.getAdditionalInfo().get(Parameter.ADDITIONAL_TYPES_KEY);
List<Class> possibleTypes = combinedParameterEntries
.stream()
.filter(CombinedParameterEntry::isUsableInMessageCommands)
.map(CombinedParameterEntry::getType)
.toList();
for (Class concreteParameter: possibleTypes) {
for (CommandParameterHandler handler : parameterHandlers) {
try {
if (handler.handles((Class) concreteParameter, input)) {
if (handler.handles(concreteParameter, input)) {
if (handler.async()) {
futures.add(handler.handleAsync(input, iterators, param, context, command));
} else {

View File

@@ -119,7 +119,7 @@ public class SlashCommandServiceBean implements SlashCommandService {
if(!shouldParameterBeCreated(parameter, serverId)) {
return;
}
List<OptionType> types = slashCommandParameterService.getTypesFromParameter(parameter.getType());
List<OptionType> types = slashCommandParameterService.getTypesFromParameter(parameter);
if(types.size() > 1) {
if(parameter.isListParam()) {
for (int i = 0; i < parameter.getListSize(); i++) {

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.interaction.slash.parameter;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.interaction.slash.parameter.provider.SlashCommandParameterProvider;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.models.database.AEmote;
@@ -151,6 +152,16 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
return Emoji.fromFormatted(input);
}
@Override
public List<OptionType> getTypesFromParameter(Parameter parameter) {
return parameterProviders
.stream()
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(parameter.getType()))
.findAny()
.map(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping(parameter).getOptionTypes())
.orElseThrow(() -> new IllegalArgumentException(String.format("Unknown type for slash command parameter desired %s", parameter.getType().getName())));
}
@Override
public List<OptionType> getTypesFromParameter(Class clazz) {
return parameterProviders

View File

@@ -1,15 +1,25 @@
package dev.sheldan.abstracto.core.interaction.slash.parameter.provider.provided;
import dev.sheldan.abstracto.core.command.config.CombinedParameterEntry;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.handler.parameter.CombinedParameter;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandOptionTypeMapping;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.interaction.slash.parameter.provider.SlashCommandParameterProvider;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.*;
import static dev.sheldan.abstracto.core.command.config.Parameter.ADDITIONAL_TYPES_KEY;
@Component
public class CombinedSlashCommandParameterProvider implements SlashCommandParameterProvider {
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Override
public SlashCommandOptionTypeMapping getOptionMapping() {
return SlashCommandOptionTypeMapping
@@ -18,4 +28,47 @@ public class CombinedSlashCommandParameterProvider implements SlashCommandParame
.optionTypes(Arrays.asList(OptionType.STRING))
.build();
}
/**
* The purpose of this method is just for the sake of a combined parameter, so that the combined parameters are evaluated _again_
* and every part of the parameter gets its own option. We only need this when creating the options. The other time a slash command parameter provider
* is executed, its when actually retrieving the parameter, but in that case the call is not done via the CombinedParameter type, but
* via the concrete type (Member, String, etc) anyway
*/
@Override
public SlashCommandOptionTypeMapping getOptionMapping(Parameter parameter) {
Map<String, Object> additionalInfo = parameter.getAdditionalInfo();
if(!additionalInfo.containsKey(ADDITIONAL_TYPES_KEY)) {
return empty();
}
List<CombinedParameterEntry> combinedParameterEntries = (List<CombinedParameterEntry>) additionalInfo.get(ADDITIONAL_TYPES_KEY);
if(combinedParameterEntries.isEmpty()) {
return empty();
}
List<Class> possibleTypes = combinedParameterEntries
.stream()
.filter(CombinedParameterEntry::isUsableInSlashCommands)
.map(CombinedParameterEntry::getType)
.toList();
if(possibleTypes.isEmpty()) {
return empty();
}
Set<OptionType> optionTypes = new HashSet<>();
possibleTypes.forEach(additionalType -> {
optionTypes.addAll(slashCommandParameterService.getTypesFromParameter(additionalType));
});
return SlashCommandOptionTypeMapping
.builder()
.type(CombinedParameter.class)
.optionTypes(new ArrayList<>(optionTypes))
.build();
}
private static SlashCommandOptionTypeMapping empty() {
return SlashCommandOptionTypeMapping
.builder()
.type(CombinedParameter.class)
.optionTypes(new ArrayList<>())
.build();
}
}

View File

@@ -0,0 +1,37 @@
package dev.sheldan.abstracto.core.command.config;
import lombok.Builder;
import lombok.Getter;
@Getter
@Builder
public class CombinedParameterEntry {
private Class type;
private boolean usableInSlashCommands;
private boolean usableInMessageCommands;
public static CombinedParameterEntry slashParameter(Class type) {
return CombinedParameterEntry
.builder()
.type(type)
.usableInSlashCommands(true)
.build();
}
public static CombinedParameterEntry messageParameter(Class type) {
return CombinedParameterEntry
.builder()
.type(type)
.usableInMessageCommands(true)
.build();
}
public static CombinedParameterEntry parameter(Class type) {
return CombinedParameterEntry
.builder()
.type(type)
.usableInMessageCommands(true)
.usableInSlashCommands(true)
.build();
}
}

View File

@@ -1,6 +1,7 @@
package dev.sheldan.abstracto.core.interaction.slash.parameter;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.models.database.AEmote;
import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.interactions.commands.CommandInteractionPayload;
@@ -17,6 +18,7 @@ public interface SlashCommandParameterService {
Boolean hasCommandOptionWithFullType(String name, CommandInteractionPayload event, OptionType optionType);
AEmote loadAEmoteFromString(String input, CommandInteractionPayload event);
Emoji loadEmoteFromString(String input, CommandInteractionPayload event);
List<OptionType> getTypesFromParameter(Parameter parameter);
List<OptionType> getTypesFromParameter(Class clazz);
String getFullQualifiedParameterName(String name, OptionType type);
}

View File

@@ -1,7 +1,12 @@
package dev.sheldan.abstracto.core.interaction.slash.parameter.provider;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandOptionTypeMapping;
public interface SlashCommandParameterProvider {
SlashCommandOptionTypeMapping getOptionMapping();
default SlashCommandOptionTypeMapping getOptionMapping(Parameter parameter) {
return getOptionMapping();
}
}