[AB-xxx] migrating assignable role commands to slash commands

removing separate command for editing assignable role place text, and adding it to the change command
fixing 2 bugs related with deleting assignable roles with users, and deleting assignable role places
refactoring how enums are handled with slash command parameters
adding cleanup for slash command confirmation payloads once they are clicked
This commit is contained in:
Sheldan
2025-02-16 22:30:27 +01:00
parent a8c2dfe15a
commit 8544c0c2b1
48 changed files with 1055 additions and 426 deletions

View File

@@ -106,7 +106,10 @@ public class Echo extends AbstractConditionableCommand {
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.rootCommandName(ECHO_COMMAND)
.build();
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
return CommandConfiguration.builder()
.name(ECHO_COMMAND)
.slashCommandOnly(true)

View File

@@ -253,6 +253,11 @@ public class InteractionServiceBean implements InteractionService {
return replaceOriginal(messageToSend, interactionHook);
}
@Override
public CompletableFuture<Void> deleteMessage(InteractionHook interactionHook) {
return interactionHook.deleteOriginal().submit();
}
public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) {
ReplyCallbackAction action = null;
if(messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) {

View File

@@ -85,7 +85,12 @@ public class ConfirmationButtonClickedListener implements ButtonClickedListener
} catch (Exception e) {
commandReceivedHandler.reportException(context.getContext(), context.getCommand(), e, "Confirmation execution of command failed.");
} finally {
cleanup(model, payload);
cleanup(model, payload).thenAccept(unused -> {
log.info("Cleanup successful.");
}).exceptionally(throwable -> {
log.error("Failed to cleanup confirmation button.", throwable);
return null;
});
}
}

View File

@@ -33,7 +33,6 @@ import java.util.concurrent.ConcurrentHashMap;
import dev.sheldan.abstracto.core.utils.ContextUtils;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
@@ -200,7 +199,7 @@ public class SlashCommandListenerBean extends ListenerAdapter {
}
@Transactional
public void continueSlashCommand(Long interactionId, ButtonInteractionEvent buttonInteractionEvent) {
public void continueSlashCommand(Long interactionId, ButtonInteractionEvent buttonInteractionEvent, SlashCommandConfirmationPayload slashCommandConfirmationPayload) {
if(COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) {
DriedSlashCommand driedSlashCommand = COMMANDS_WAITING_FOR_CONFIRMATION.get(interactionId);
Command commandInstance = driedSlashCommand.getCommand();
@@ -212,11 +211,13 @@ public class SlashCommandListenerBean extends ListenerAdapter {
}).thenAccept(commandResult -> {
self.executePostCommandListener(commandInstance, driedSlashCommand.getEvent(), commandResult);
COMMANDS_WAITING_FOR_CONFIRMATION.remove(interactionId);
self.cleanupSlashCommandConfirmation(slashCommandConfirmationPayload, buttonInteractionEvent);
}).exceptionally(throwable -> {
log.error("Error while handling post execution of command with confirmation {}", commandName, throwable);
CommandResult commandResult = CommandResult.fromError(throwable.getMessage(), throwable);
self.executePostCommandListener(commandInstance, driedSlashCommand.getEvent(), commandResult);
COMMANDS_WAITING_FOR_CONFIRMATION.remove(interactionId);
self.cleanupSlashCommandConfirmation(slashCommandConfirmationPayload, buttonInteractionEvent);
return null;
});
} else {
@@ -224,6 +225,12 @@ public class SlashCommandListenerBean extends ListenerAdapter {
}
}
@Transactional
public void cleanupSlashCommandConfirmation(SlashCommandConfirmationPayload slashCommandConfirmationPayload, ButtonInteractionEvent buttonInteractionEvent) {
log.debug("Cleaning up component {} and {}.", slashCommandConfirmationPayload.getConfirmationPayloadId(), slashCommandConfirmationPayload.getAbortPayloadId());
componentPayloadManagementService.deletePayloads(Arrays.asList(slashCommandConfirmationPayload.getAbortPayloadId(), slashCommandConfirmationPayload.getConfirmationPayloadId()));
}
@Transactional
public void removeSlashCommandConfirmationInteraction(Long interactionId, String confirmationPayload, String abortPayload) {
if(COMMANDS_WAITING_FOR_CONFIRMATION.containsKey(interactionId)) {
@@ -253,6 +260,8 @@ public class SlashCommandListenerBean extends ListenerAdapter {
.builder()
.action(SlashCommandConfirmationPayload.CommandConfirmationAction.CONFIRM)
.interactionId(event.getIdLong())
.abortPayloadId(abortId)
.confirmationPayloadId(confirmationId)
.build();
Long serverId = event.getGuild().getIdLong();
AServer server = serverManagementService.loadServer(event.getGuild());
@@ -261,6 +270,8 @@ public class SlashCommandListenerBean extends ListenerAdapter {
.builder()
.action(SlashCommandConfirmationPayload.CommandConfirmationAction.ABORT)
.interactionId(event.getIdLong())
.abortPayloadId(abortId)
.confirmationPayloadId(confirmationId)
.build();
componentPayloadService.createButtonPayload(abortId, denialPayload, SLASH_COMMAND_CONFIRMATION_ORIGIN, server);
CommandConfirmationModel model = CommandConfirmationModel

View File

@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.core.interaction.slash;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
import dev.sheldan.abstracto.core.command.model.database.ACommand;
@@ -235,6 +236,9 @@ public class SlashCommandServiceBean implements SlashCommandService {
}
private void addChoices(OptionData optionData, Parameter parameter, String commandName, boolean isTemplated, Long serverId) {
if(CommandParameterKey.class.isAssignableFrom(parameter.getType())) {
parameter.setChoices(CommandParameterKey.getKeys(parameter.getType()));
}
parameter.getChoices().forEach(choiceKey -> {
String value = isTemplated ? templateService.renderSimpleTemplate(commandName + "_parameter_" + parameter.getName() + "_choice_" + choiceKey, serverId) : choiceKey;
optionData.addChoice(value, choiceKey);

View File

@@ -26,7 +26,7 @@ public class SlashCommandConfirmationGivenButtonListener implements ButtonClicke
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
SlashCommandConfirmationPayload payload = (SlashCommandConfirmationPayload) model.getDeserializedPayload();
if(payload.getAction().equals(SlashCommandConfirmationPayload.CommandConfirmationAction.CONFIRM)) {
slashCommandListenerBean.continueSlashCommand(payload.getInteractionId(), model.getEvent());
slashCommandListenerBean.continueSlashCommand(payload.getInteractionId(), model.getEvent(), payload);
return ButtonClickedListenerResult.ACKNOWLEDGED;
} else {
return ButtonClickedListenerResult.IGNORED;

View File

@@ -171,7 +171,8 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
public List<OptionType> getTypesFromParameter(Parameter parameter) {
return parameterProviders
.stream()
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(parameter.getType()))
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(parameter.getType())
|| slashCommandParameterProvider.getOptionMapping().getType().isAssignableFrom(parameter.getType()))
.findAny()
.map(slashCommandParameterProvider -> {
List<OptionType> optionTypes;
@@ -194,7 +195,8 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
public List<OptionType> getTypesFromParameter(Class clazz, boolean strict) {
return parameterProviders
.stream()
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(clazz))
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(clazz)
|| slashCommandParameterProvider.getOptionMapping().getType().isAssignableFrom(clazz))
.findAny()
.map(slashCommandParameterProvider -> {
List<OptionType> optionTypes;

View File

@@ -0,0 +1,20 @@
package dev.sheldan.abstracto.core.interaction.slash.parameter.provider.provided;
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandOptionTypeMapping;
import dev.sheldan.abstracto.core.interaction.slash.parameter.provider.SlashCommandParameterProvider;
import java.util.Arrays;
import net.dv8tion.jda.api.interactions.commands.OptionType;
import org.springframework.stereotype.Component;
@Component
public class CommandParameterKeySlashCommandParameterProvider implements SlashCommandParameterProvider {
@Override
public SlashCommandOptionTypeMapping getOptionMapping() {
return SlashCommandOptionTypeMapping
.builder()
.type(CommandParameterKey.class)
.optionTypes(Arrays.asList(OptionType.STRING))
.build();
}
}

View File

@@ -10,6 +10,8 @@ public class SlashCommandConfirmationPayload implements ButtonPayload {
private CommandConfirmationAction action;
private Long interactionId;
private String confirmationPayloadId;
private String abortPayloadId;
public enum CommandConfirmationAction {
CONFIRM, ABORT