mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-03 16:27:53 +00:00
[AB-xxx] adding support for user installable apps to varying commands
This commit is contained in:
@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ReactionService;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -53,7 +54,7 @@ public class ConditionPostExecution implements PostCommandExecution {
|
||||
|
||||
@Override
|
||||
public void executeSlash(SlashCommandInteractionEvent interaction, CommandResult commandResult, Command command) {
|
||||
if(commandResult.getResult().equals(ResultState.CONDITION)
|
||||
if(commandResult.getResult().equals(ResultState.CONDITION) && ContextUtils.isNotUserCommand(interaction)
|
||||
&& commandResult.getConditionResult() != null &&
|
||||
!commandResult.getConditionResult().isResult()
|
||||
&& commandResult.getConditionResult().getConditionDetail() != null
|
||||
|
||||
@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ResultState;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandCoolDownService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -35,7 +36,9 @@ public class CoolDownPostExecution implements PostCommandExecution {
|
||||
public void executeSlash(SlashCommandInteractionEvent interaction, CommandResult commandResult, Command command) {
|
||||
ResultState result = commandResult.getResult();
|
||||
if(result.equals(ResultState.SUCCESSFUL) || result.equals(ResultState.IGNORED)) {
|
||||
commandCoolDownService.updateCoolDowns(command, interaction);
|
||||
if(ContextUtils.isNotUserCommand(interaction)) {
|
||||
commandCoolDownService.updateCoolDowns(command, interaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.command.service.ExceptionService;
|
||||
import dev.sheldan.abstracto.core.command.service.PostCommandExecution;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionExceptionService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
@@ -53,7 +54,7 @@ public class ExceptionPostExecution implements PostCommandExecution {
|
||||
if(result.equals(ResultState.ERROR)) {
|
||||
Throwable throwable = commandResult.getThrowable();
|
||||
if(throwable != null) {
|
||||
if(throwable instanceof CommandNotFoundException){
|
||||
if(throwable instanceof CommandNotFoundException && ContextUtils.isNotUserCommand(interaction)){
|
||||
String configValue = configService.getStringValueOrConfigDefault(CoreFeatureConfig.NO_COMMAND_REPORTING_CONFIG_KEY, interaction.getGuild().getIdLong());
|
||||
if(!BooleanUtils.toBoolean(configValue)) {
|
||||
return;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.core.commands.help;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.CoreSlashCommandNames;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
@@ -52,6 +53,8 @@ public class Documentation extends AbstractConditionableCommand {
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.userInstallable(true)
|
||||
.userCommandConfig(UserCommandConfig.all())
|
||||
.rootCommandName(CoreSlashCommandNames.INFO)
|
||||
.commandName("documentation")
|
||||
.build();
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
@@ -18,6 +19,7 @@ import dev.sheldan.abstracto.core.models.template.display.ChannelDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -64,15 +66,14 @@ public class Echo extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
|
||||
String message = slashCommandParameterService.getCommandOption(INPUT_PARAMETER, event, String.class);
|
||||
GuildMessageChannel messageChannel;
|
||||
MessageChannel messageChannel;
|
||||
boolean redirect = false;
|
||||
if (slashCommandParameterService.hasCommandOption(TARGET_CHANNEL_PARAMETER, event)) {
|
||||
messageChannel = slashCommandParameterService.getCommandOption(TARGET_CHANNEL_PARAMETER, event, GuildMessageChannel.class);
|
||||
redirect = true;
|
||||
} else {
|
||||
messageChannel = event.getGuildChannel();
|
||||
messageChannel = event.getChannel();
|
||||
}
|
||||
|
||||
EchoModel model = EchoModel
|
||||
@@ -110,6 +111,7 @@ public class Echo extends AbstractConditionableCommand {
|
||||
.name(TARGET_CHANNEL_PARAMETER)
|
||||
.type(GuildMessageChannel.class)
|
||||
.slashCommandOnly(true)
|
||||
.supportsUserCommands(false)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.remainder(true)
|
||||
@@ -118,6 +120,8 @@ public class Echo extends AbstractConditionableCommand {
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.userInstallable(true)
|
||||
.userCommandConfig(UserCommandConfig.all())
|
||||
.rootCommandName(ECHO_COMMAND)
|
||||
.build();
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
@@ -60,6 +61,8 @@ public class Ping extends AbstractConditionableCommand {
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.userInstallable(true)
|
||||
.userCommandConfig(UserCommandConfig.all())
|
||||
.rootCommandName(PING_COMMAND)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
@@ -69,6 +70,8 @@ public class Uptime extends AbstractConditionableCommand {
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.userInstallable(true)
|
||||
.userCommandConfig(UserCommandConfig.all())
|
||||
.rootCommandName(UPTIME_COMMAND)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.context.ContextCommandService;
|
||||
import dev.sheldan.abstracto.core.interaction.context.management.ContextCommandInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.context.management.ContextCommandManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.context.message.MessageContextCommandListenerBean;
|
||||
import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageContextCommandListener;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandListenerBean;
|
||||
@@ -20,6 +18,7 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
@@ -28,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -60,12 +60,6 @@ public class CommandLoaderListener implements AsyncStartupListener {
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private ContextCommandManagementService contextCommandManagementService;
|
||||
|
||||
@Autowired
|
||||
private ContextCommandInServerManagementService contextCommandInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private CommandLoaderListener self;
|
||||
|
||||
@@ -92,7 +86,7 @@ public class CommandLoaderListener implements AsyncStartupListener {
|
||||
return;
|
||||
}
|
||||
log.info("Updating slash command {} in guild {}.", command.getConfiguration().getName(), guild.getId());
|
||||
slashCommandService.convertCommandConfigToCommandData(command.getConfiguration(), slashCommandsToUpdate, guild.getIdLong());
|
||||
slashCommandService.convertCommandConfigToCommandData(command.getConfiguration(), slashCommandsToUpdate, guild.getIdLong(), false);
|
||||
});
|
||||
|
||||
log.info("Updating context commands for guild {}.", guild.getIdLong());
|
||||
@@ -126,7 +120,15 @@ public class CommandLoaderListener implements AsyncStartupListener {
|
||||
return null;
|
||||
});
|
||||
});
|
||||
|
||||
List<Pair<List<CommandConfiguration>, SlashCommandData>> userCommandsToUpdate = new ArrayList<>();
|
||||
incomingSlashCommands.forEach(command -> {
|
||||
slashCommandService.convertCommandConfigToCommandData(command.getConfiguration(), userCommandsToUpdate, null, true);
|
||||
});
|
||||
List<CommandData> userCommands = userCommandsToUpdate
|
||||
.stream()
|
||||
.map(Pair::getSecond)
|
||||
.collect(Collectors.toList());
|
||||
jda.updateCommands().addCommands(userCommands).queue();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -7,6 +7,8 @@ import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageCo
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListener;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerModel;
|
||||
import dev.sheldan.abstracto.core.models.listener.interaction.MessageContextInteractionModel;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.callbacks.IReplyCallback;
|
||||
@@ -57,18 +59,32 @@ public class InteractionExceptionServiceBean implements InteractionExceptionServ
|
||||
|
||||
@Override
|
||||
public void reportSlashException(Throwable exception, SlashCommandInteractionEvent event, Command command) {
|
||||
log.info("Reporting exception of {} command {} in channel {} in guild {} from user {}.",
|
||||
exception.getClass().getSimpleName(), command.getConfiguration().getName(),
|
||||
event.getChannel().getIdLong(), event.getGuild().getIdLong(), event.getMember().getIdLong(), exception);
|
||||
if(ContextUtils.hasGuild(event)) {
|
||||
log.info("Reporting exception of {} command {} in channel {} in guild {} from user {}.",
|
||||
exception.getClass().getSimpleName(), command.getConfiguration().getName(),
|
||||
event.getChannel().getIdLong(), event.getGuild().getIdLong(), event.getMember().getIdLong(), exception);
|
||||
} else {
|
||||
log.info("Reporting exception of user command for user {}.", event.getUser().getIdLong());
|
||||
}
|
||||
reportGenericInteractionException(exception, event.getInteraction());
|
||||
}
|
||||
|
||||
private void reportGenericInteractionException(Throwable throwable, IReplyCallback replyCallback) {
|
||||
GenericInteractionExceptionModel exceptionModel = buildInteractionExceptionModel(throwable, replyCallback);
|
||||
if(replyCallback.isAcknowledged()) {
|
||||
interactionService.sendMessageToInteraction(GENERIC_INTERACTION_EXCEPTION, exceptionModel, replyCallback.getHook());
|
||||
FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(GENERIC_INTERACTION_EXCEPTION, exceptionModel, replyCallback.getHook()))
|
||||
.thenAccept(interactionHook -> log.info("Notified about exception."))
|
||||
.exceptionally(throwable1 -> {
|
||||
log.warn("Failed to notify about exception.", throwable1);
|
||||
return null;
|
||||
});;
|
||||
} else {
|
||||
interactionService.replyEmbed(GENERIC_INTERACTION_EXCEPTION, exceptionModel, replyCallback);
|
||||
interactionService.replyEmbed(GENERIC_INTERACTION_EXCEPTION, exceptionModel, replyCallback)
|
||||
.thenAccept(interactionHook -> log.info("Notified about exception."))
|
||||
.exceptionally(throwable1 -> {
|
||||
log.warn("Failed to notify about exception.", throwable1);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
@@ -107,9 +108,11 @@ public class InteractionServiceBean implements InteractionService {
|
||||
if(messageToSend.getEphemeral()) {
|
||||
Interaction interaction = interactionHook.getInteraction();
|
||||
interactionHook.setEphemeral(messageToSend.getEphemeral());
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
interaction.getGuild().getIdLong(), interaction.getChannel().getId(),
|
||||
interaction.getMember().getIdLong());
|
||||
if(ContextUtils.hasGuild(interaction)) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
interaction.getGuild().getIdLong(), interaction.getChannel().getId(),
|
||||
interaction.getUser().getIdLong());
|
||||
}
|
||||
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
|
||||
}
|
||||
|
||||
@@ -134,13 +137,14 @@ public class InteractionServiceBean implements InteractionService {
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendMessageToInteraction(String templateKey, Object model, InteractionHook interactionHook) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model, interactionHook.getInteraction().getGuild().getIdLong());
|
||||
Long serverId = ContextUtils.serverIdOrNull(interactionHook);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model, serverId);
|
||||
return sendMessageToInteraction(messageToSend, interactionHook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<InteractionHook> replyEmbed(String templateKey, Object model, IReplyCallback callback) {
|
||||
Long serverId = callback.getGuild().getIdLong();
|
||||
Long serverId = ContextUtils.serverIdOrNull(callback);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model, serverId);
|
||||
return replyMessageToSend(messageToSend, callback);
|
||||
}
|
||||
@@ -160,20 +164,24 @@ public class InteractionServiceBean implements InteractionService {
|
||||
|
||||
@Override
|
||||
public List<CompletableFuture<Message>> sendEmbed(String templateKey, InteractionHook interactionHook) {
|
||||
Long serverId = interactionHook.getInteraction().getGuild().getIdLong();
|
||||
Long serverId = ContextUtils.serverIdOrNull(interactionHook);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, new Object(), serverId);
|
||||
return sendMessageToInteraction(messageToSend, interactionHook);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> replaceOriginal(MessageToSend messageToSend, InteractionHook interactionHook) {
|
||||
Long serverId = interactionHook.getInteraction().getGuild().getIdLong();
|
||||
Long serverId = ContextUtils.serverIdOrNull(interactionHook);
|
||||
|
||||
if(messageToSend.getEphemeral()) {
|
||||
Interaction interaction = interactionHook.getInteraction();
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
interaction.getGuild().getIdLong(), interaction.getChannel().getId(),
|
||||
interaction.getMember().getIdLong());
|
||||
if(ContextUtils.hasGuild(interaction)) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
interaction.getGuild().getIdLong(), interaction.getChannel().getId(),
|
||||
interaction.getUser().getIdLong());
|
||||
} else {
|
||||
log.info("Sending ephemeral message to interaction for user {}", interactionHook.getInteraction().getUser().getIdLong());
|
||||
}
|
||||
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
|
||||
interactionHook.setEphemeral(true);
|
||||
}
|
||||
@@ -215,7 +223,11 @@ public class InteractionServiceBean implements InteractionService {
|
||||
action = interactionHook.editOriginal(".");
|
||||
}
|
||||
action = action.setComponents(actionRows);
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
AServer server;
|
||||
if(ContextUtils.isGuildKnown(interactionHook.getInteraction())) {
|
||||
server = serverManagementService.loadServer(serverId);
|
||||
} else {
|
||||
server = null; }
|
||||
actionRows.forEach(components -> components.forEach(component -> {
|
||||
if(component instanceof ActionComponent) {
|
||||
String id = ((ActionComponent)component).getId();
|
||||
@@ -242,7 +254,6 @@ public class InteractionServiceBean implements InteractionService {
|
||||
}
|
||||
|
||||
public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) {
|
||||
Long serverId = callback.getGuild().getIdLong();
|
||||
ReplyCallbackAction action = null;
|
||||
if(messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
@@ -279,7 +290,12 @@ public class InteractionServiceBean implements InteractionService {
|
||||
action = callback.reply(".");
|
||||
}
|
||||
action = action.setComponents(actionRows);
|
||||
AServer server = serverManagementService.loadServer(serverId);
|
||||
AServer server;
|
||||
if(ContextUtils.isGuildKnown(callback)) {
|
||||
server = serverManagementService.loadServer(callback.getGuild().getIdLong());
|
||||
} else {
|
||||
server = null;
|
||||
}
|
||||
actionRows.forEach(components -> components.forEach(component -> {
|
||||
if(component instanceof ActionComponent) {
|
||||
String id = ((ActionComponent)component).getId();
|
||||
@@ -292,17 +308,23 @@ public class InteractionServiceBean implements InteractionService {
|
||||
}
|
||||
|
||||
if(messageToSend.getEphemeral()) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
callback.getGuild().getIdLong(), callback.getChannel().getId(),
|
||||
callback.getMember().getIdLong());
|
||||
if(ContextUtils.hasGuild(callback)) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
callback.getGuild().getIdLong(), callback.getChannel().getId(),
|
||||
callback.getUser().getIdLong());
|
||||
} else {
|
||||
log.info("Sending ephemeral message to user {}.", callback.getUser().getIdLong());
|
||||
}
|
||||
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
|
||||
if(action != null) {
|
||||
action = action.setEphemeral(messageToSend.getEphemeral());
|
||||
}
|
||||
}
|
||||
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
|
||||
if(action != null) {
|
||||
action.setAllowedMentions(allowedMentions);
|
||||
if(ContextUtils.isGuildKnown(callback)) {
|
||||
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
|
||||
if (action != null) {
|
||||
action.setAllowedMentions(allowedMentions);
|
||||
}
|
||||
}
|
||||
|
||||
if(action == null) {
|
||||
@@ -313,7 +335,7 @@ public class InteractionServiceBean implements InteractionService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<InteractionHook> replyMessage(String templateKey, Object model, IReplyCallback callback) {
|
||||
Long serverId = callback.getGuild().getIdLong();
|
||||
Long serverId = ContextUtils.serverIdOrNull(callback);
|
||||
MessageToSend messageToSend = templateService.renderTemplateToMessageToSend(templateKey, model, serverId);
|
||||
return replyMessageToSend(messageToSend, callback);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.BeanUtils;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
@@ -124,6 +125,9 @@ public class SyncButtonClickedListenerBean extends ListenerAdapter {
|
||||
if(!model.getEvent().isFromGuild()) {
|
||||
return true;
|
||||
}
|
||||
if(ContextUtils.isUserCommand(model.getEvent())) {
|
||||
return true;
|
||||
}
|
||||
if (!featureFlagService.isFeatureEnabled(feature, model.getServerId())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
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;
|
||||
@@ -126,7 +127,11 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
|
||||
try {
|
||||
if(commands == null || commands.isEmpty()) return;
|
||||
log.debug("Executing slash command in guild {} from user {}.", event.getGuild().getIdLong(), event.getMember().getIdLong());
|
||||
if(ContextUtils.hasGuild(event.getInteraction())) {
|
||||
log.debug("Executing slash command in guild {} from user {}.", event.getGuild().getIdLong(), event.getUser().getIdLong());
|
||||
} else {
|
||||
log.debug("Executing slash command by user {}", event.getUser().getIdLong());
|
||||
}
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), slashCommandExecutor).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async slash command event.", throwable);
|
||||
return null;
|
||||
@@ -136,6 +141,7 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional
|
||||
public void executeListenerLogic(SlashCommandInteractionEvent event) {
|
||||
Optional<Command> potentialCommand = findCommand(event);
|
||||
@@ -179,7 +185,14 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
List<String> fullRepliesList = command.performAutoComplete(event);
|
||||
List<String> replies = fullRepliesList.subList(0, Math.min(fullRepliesList.size(), OptionData.MAX_CHOICES));
|
||||
event.replyChoiceStrings(replies).queue(unused -> {},
|
||||
throwable -> log.error("Failed to response to complete of command {} in guild {}.", command.getConfiguration().getName(), event.getGuild().getIdLong()));
|
||||
throwable -> {
|
||||
if(ContextUtils.hasGuild(event)) {
|
||||
log.error("Failed to respond to complete of command {} in guild {} by user {}.",
|
||||
command.getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong());
|
||||
} else {
|
||||
log.error("Failed to resp ond to complete of command {} for user {}.", command.getConfiguration().getName(), event.getUser().getIdLong());
|
||||
}
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Error while executing autocomplete of command {}.", command.getConfiguration().getName(), exception);
|
||||
}
|
||||
@@ -268,7 +281,11 @@ public class SlashCommandListenerBean extends ListenerAdapter {
|
||||
CompletableFuture<CommandResult> commandOutput;
|
||||
if(conditionResult.isResult()) {
|
||||
commandOutput = command.executeSlash(event).thenApply(commandResult -> {
|
||||
log.info("Command {} in server {} was executed.", commandName, event.getGuild().getIdLong());
|
||||
if(ContextUtils.hasGuild(event)) {
|
||||
log.info("Command {} in server {} was executed by user {}.", command.getConfiguration().getName(), event.getGuild().getIdLong(), event.getUser().getIdLong());
|
||||
} else {
|
||||
log.info("Command {} was executed by user {}.", command.getConfiguration().getName(), event.getUser().getId());
|
||||
}
|
||||
return commandResult;
|
||||
});
|
||||
} else {
|
||||
|
||||
@@ -3,6 +3,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.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.config.UserCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.model.database.ACommand;
|
||||
import dev.sheldan.abstracto.core.command.model.database.ACommandInAServer;
|
||||
import dev.sheldan.abstracto.core.command.service.management.CommandInServerManagementService;
|
||||
@@ -15,19 +16,19 @@ import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.interactions.IntegrationType;
|
||||
import net.dv8tion.jda.api.interactions.InteractionContextType;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.Command;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -58,8 +59,19 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
private final static Map<UserCommandConfig.CommandContext, InteractionContextType> CONTEXT_CONFIG = new HashMap<>();
|
||||
|
||||
static {
|
||||
CONTEXT_CONFIG.put(UserCommandConfig.CommandContext.DM, InteractionContextType.PRIVATE_CHANNEL);
|
||||
CONTEXT_CONFIG.put(UserCommandConfig.CommandContext.BOT_DM, InteractionContextType.BOT_DM);
|
||||
CONTEXT_CONFIG.put(UserCommandConfig.CommandContext.GUILD, InteractionContextType.GUILD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void convertCommandConfigToCommandData(CommandConfiguration commandConfiguration, List<Pair<List<CommandConfiguration>, SlashCommandData>> existingCommands, Long serverId) {
|
||||
public void convertCommandConfigToCommandData(CommandConfiguration commandConfiguration, List<Pair<List<CommandConfiguration>, SlashCommandData>> existingCommands, Long serverId, boolean userCommandsOnly) {
|
||||
if(userCommandsOnly && !commandConfiguration.isUserInstallable()) {
|
||||
return;
|
||||
}
|
||||
boolean isTemplated = commandConfiguration.isTemplated();
|
||||
SlashCommandConfig slashConfig = commandConfiguration.getSlashCommandConfig();
|
||||
String description;
|
||||
@@ -69,15 +81,25 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
} else {
|
||||
description = templateService.renderSimpleTemplate(internalCommandName + "_description", serverId);
|
||||
}
|
||||
String rootName = slashConfig.getSlashCompatibleRootName();
|
||||
String groupName = slashConfig.getSlashCompatibleGroupName();
|
||||
String commandName = slashConfig.getSlashCompatibleCommandName();
|
||||
String rootName = userCommandsOnly ? StringUtils.defaultString(slashConfig.getUserSlashCompatibleRootName(), slashConfig.getSlashCompatibleRootName()) : slashConfig.getSlashCompatibleRootName();
|
||||
String groupName = userCommandsOnly ? StringUtils.defaultString(slashConfig.getUserSlashCompatibleGroupName(), slashConfig.getSlashCompatibleGroupName()) : slashConfig.getSlashCompatibleGroupName();
|
||||
String commandName = userCommandsOnly ? StringUtils.defaultString(slashConfig.getUserSlashCompatibleCommandName(), slashConfig.getSlashCompatibleCommandName()) : slashConfig.getSlashCompatibleCommandName();
|
||||
Optional<SlashCommandData> existingRootCommand = existingCommands
|
||||
.stream()
|
||||
.filter(commandData -> commandData.getSecond().getName().equals(rootName))
|
||||
.map(Pair::getSecond)
|
||||
.findAny();
|
||||
SlashCommandData rootCommand = existingRootCommand.orElseGet(() -> Commands.slash(rootName, description));
|
||||
if(commandConfiguration.isUserInstallable() && userCommandsOnly) {
|
||||
rootCommand.setIntegrationTypes(IntegrationType.USER_INSTALL);
|
||||
if(commandConfiguration.getSlashCommandConfig().getUserCommandConfig() != null) {
|
||||
Set<UserCommandConfig.CommandContext> allowedContexts = commandConfiguration.getSlashCommandConfig().getUserCommandConfig().getContexts();
|
||||
Set<InteractionContextType> interactionContextTypes = mapCommandContexts(allowedContexts);
|
||||
rootCommand.setContexts(interactionContextTypes);
|
||||
} else {
|
||||
rootCommand.setContexts(InteractionContextType.GUILD);
|
||||
}
|
||||
}
|
||||
if(commandName != null) {
|
||||
SubcommandData slashCommand = new SubcommandData(commandName, description);
|
||||
if(groupName == null) {
|
||||
@@ -94,13 +116,13 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
rootCommand.addSubcommandGroups(groupData);
|
||||
}
|
||||
}
|
||||
List<OptionData> requiredParameters = getParameters(commandConfiguration, isTemplated, internalCommandName, serverId);
|
||||
List<OptionData> requiredParameters = getParameters(commandConfiguration, isTemplated, internalCommandName, serverId, userCommandsOnly);
|
||||
slashCommand.addOptions(requiredParameters);
|
||||
} else {
|
||||
List<OptionData> requiredParameters = getParameters(commandConfiguration, isTemplated, internalCommandName, serverId);
|
||||
List<OptionData> requiredParameters = getParameters(commandConfiguration, isTemplated, internalCommandName, serverId, userCommandsOnly);
|
||||
rootCommand.addOptions(requiredParameters);
|
||||
}
|
||||
if(!existingRootCommand.isPresent()) {
|
||||
if(existingRootCommand.isEmpty()) {
|
||||
Optional<Pair<List<CommandConfiguration>, SlashCommandData>> existingCommand = existingCommands
|
||||
.stream()
|
||||
.filter(listSlashCommandDataPair -> listSlashCommandDataPair.getSecond().equals(rootCommand))
|
||||
@@ -113,6 +135,18 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
}
|
||||
}
|
||||
|
||||
private Set<InteractionContextType> mapCommandContexts(Set<UserCommandConfig.CommandContext> contexts) {
|
||||
Set<InteractionContextType> mapped = new HashSet<>();
|
||||
contexts.forEach(commandContext -> {
|
||||
if(commandContext == UserCommandConfig.CommandContext.ALL) {
|
||||
mapped.addAll(InteractionContextType.ALL);
|
||||
} else {
|
||||
mapped.add(CONTEXT_CONFIG.get(commandContext));
|
||||
}
|
||||
});
|
||||
return mapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> completeConfirmableCommand(SlashCommandInteractionEvent event, String template) {
|
||||
return completeConfirmableCommand(event, template, new Object());
|
||||
@@ -131,16 +165,19 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
|
||||
@Override
|
||||
public void convertCommandConfigToCommandData(CommandConfiguration commandConfiguration, List<Pair<List<CommandConfiguration>, SlashCommandData>> existingCommands) {
|
||||
convertCommandConfigToCommandData(commandConfiguration, existingCommands, null);
|
||||
convertCommandConfigToCommandData(commandConfiguration, existingCommands, null, false);
|
||||
}
|
||||
|
||||
private List<OptionData> getParameters(CommandConfiguration commandConfiguration, boolean isTemplated, String internalCommandName, Long serverId) {
|
||||
private List<OptionData> getParameters(CommandConfiguration commandConfiguration, boolean isTemplated, String internalCommandName, Long serverId, boolean userCommandsOnly) {
|
||||
List<OptionData> requiredParameters = new ArrayList<>();
|
||||
List<OptionData> optionalParameters = new ArrayList<>();
|
||||
commandConfiguration.getParameters().forEach(parameter -> {
|
||||
if(!shouldParameterBeCreated(parameter, serverId)) {
|
||||
return;
|
||||
}
|
||||
if(userCommandsOnly && !parameter.getSupportsUserCommands()) {
|
||||
return;
|
||||
}
|
||||
List<OptionType> types = slashCommandParameterService.getTypesFromParameter(parameter);
|
||||
if(types.size() > 1) {
|
||||
if(parameter.isListParam()) {
|
||||
@@ -193,6 +230,9 @@ public class SlashCommandServiceBean implements SlashCommandService {
|
||||
if(parameter.getDependentFeatures().isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
if(serverId == null) {
|
||||
return false;
|
||||
}
|
||||
List<FeatureDefinition> featureDefinitions = parameter
|
||||
.getDependentFeatures()
|
||||
.stream()
|
||||
|
||||
@@ -55,7 +55,7 @@ public class SlashCommandFeatureActivationListener implements FeatureActivationL
|
||||
return;
|
||||
}
|
||||
log.info("Updating slash command {} in guild {}.", command.getConfiguration().getName(), guild.getId());
|
||||
slashCommandService.convertCommandConfigToCommandData(command.getConfiguration(), commandsToUpDate, model.getServerId());
|
||||
slashCommandService.convertCommandConfigToCommandData(command.getConfiguration(), commandsToUpDate, model.getServerId(), false);
|
||||
});
|
||||
slashCommandService.addGuildSlashCommands(guild, commandsToUpDate)
|
||||
.thenAccept(commands1 -> log.info("Updating {} slash commands in guild {}.", commandsToUpDate.size(), guild.getIdLong()));
|
||||
|
||||
@@ -31,6 +31,7 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
List<OptionType> potentialOptionTypes = getTypesFromParameter(parameterType);
|
||||
OptionType actualOptionType = potentialOptionTypes.size() == 1 ? potentialOptionTypes.get(0) : null;
|
||||
boolean useFullName = true;
|
||||
if (potentialOptionTypes.size() > 1) {
|
||||
for (OptionType optionType: potentialOptionTypes) {
|
||||
if(event.getOption(getFullQualifiedParameterName(name, optionType)) != null) {
|
||||
@@ -38,11 +39,17 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(actualOptionType == null) { // if we still didnt find it, lets try without the fully qualified name
|
||||
if(event.getOption(name) != null) {
|
||||
actualOptionType = event.getOption(name).getType();
|
||||
useFullName = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(actualOptionType == null) {
|
||||
throw new IllegalArgumentException(String.format("Could not determine option type for parameter %s", name));
|
||||
}
|
||||
if(potentialOptionTypes.size() > 1) {
|
||||
if(potentialOptionTypes.size() > 1 && useFullName) {
|
||||
name = getFullQualifiedParameterName(name, actualOptionType);
|
||||
}
|
||||
if(actualOptionType == OptionType.BOOLEAN) {
|
||||
@@ -77,6 +84,7 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
|
||||
name = name.toLowerCase(Locale.ROOT);
|
||||
List<OptionType> potentialOptionTypes = getTypesFromParameter(parameterType);
|
||||
OptionType actualOptionType = potentialOptionTypes.size() == 1 ? potentialOptionTypes.get(0) : null;
|
||||
boolean useFullName = true;
|
||||
if (potentialOptionTypes.size() > 1) {
|
||||
for (OptionType optionType: potentialOptionTypes) {
|
||||
if(event.getOption(getFullQualifiedParameterName(name, optionType)) != null) {
|
||||
@@ -84,11 +92,17 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(actualOptionType == null) { // if we still didnt find it, lets try without the fully qualified name
|
||||
if(event.getOption(name) != null) {
|
||||
actualOptionType = event.getOption(name).getType();
|
||||
useFullName = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(actualOptionType == null) {
|
||||
return false;
|
||||
}
|
||||
if(potentialOptionTypes.size() > 1) {
|
||||
if(potentialOptionTypes.size() > 1 && useFullName) {
|
||||
name = getFullQualifiedParameterName(name, actualOptionType);
|
||||
}
|
||||
if(actualOptionType == OptionType.BOOLEAN) {
|
||||
@@ -159,17 +173,38 @@ public class SlashCommandParameterServiceBean implements SlashCommandParameterSe
|
||||
.stream()
|
||||
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(parameter.getType()))
|
||||
.findAny()
|
||||
.map(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping(parameter).getOptionTypes())
|
||||
.map(slashCommandParameterProvider -> {
|
||||
List<OptionType> optionTypes;
|
||||
if(parameter.getUseStrictParameters()) {
|
||||
optionTypes = slashCommandParameterProvider.getOptionMapping(parameter).getStrictTypes();
|
||||
} else {
|
||||
optionTypes = slashCommandParameterProvider.getOptionMapping(parameter).getOptionTypes();
|
||||
}
|
||||
return optionTypes;
|
||||
})
|
||||
.orElseThrow(() -> new IllegalArgumentException(String.format("Unknown type for slash command parameter desired %s", parameter.getType().getName())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionType> getTypesFromParameter(Class clazz) {
|
||||
return getTypesFromParameter(clazz, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OptionType> getTypesFromParameter(Class clazz, boolean strict) {
|
||||
return parameterProviders
|
||||
.stream()
|
||||
.filter(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getType().equals(clazz))
|
||||
.findAny()
|
||||
.map(slashCommandParameterProvider -> slashCommandParameterProvider.getOptionMapping().getOptionTypes())
|
||||
.map(slashCommandParameterProvider -> {
|
||||
List<OptionType> optionTypes;
|
||||
if(strict) {
|
||||
optionTypes = slashCommandParameterProvider.getOptionMapping().getStrictTypes();
|
||||
} else {
|
||||
optionTypes = slashCommandParameterProvider.getOptionMapping().getOptionTypes();
|
||||
}
|
||||
return optionTypes;
|
||||
})
|
||||
.orElseThrow(() -> new IllegalArgumentException(String.format("Unknown type for slash command parameter desired %s", clazz.getName())));
|
||||
}
|
||||
|
||||
|
||||
@@ -55,12 +55,14 @@ public class CombinedSlashCommandParameterProvider implements SlashCommandParame
|
||||
}
|
||||
Set<OptionType> optionTypes = new HashSet<>();
|
||||
possibleTypes.forEach(additionalType -> {
|
||||
optionTypes.addAll(slashCommandParameterService.getTypesFromParameter(additionalType));
|
||||
optionTypes.addAll(slashCommandParameterService.getTypesFromParameter(additionalType, parameter.getUseStrictParameters()));
|
||||
});
|
||||
return SlashCommandOptionTypeMapping
|
||||
.builder()
|
||||
.type(CombinedParameter.class)
|
||||
.optionTypes(new ArrayList<>(optionTypes))
|
||||
// this is needed, because the combined parameter is defined as strict, hence we are using the strictTypes value from the returned object
|
||||
.strictTypes(parameter.getUseStrictParameters() ? new ArrayList<>(optionTypes) : new ArrayList<>())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class UserSlashCommandParameterProvider implements SlashCommandParameterProvider {
|
||||
@@ -16,6 +17,7 @@ public class UserSlashCommandParameterProvider implements SlashCommandParameterP
|
||||
.builder()
|
||||
.type(User.class)
|
||||
.optionTypes(Arrays.asList(OptionType.USER, OptionType.STRING))
|
||||
.strictTypes(List.of(OptionType.USER))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,12 @@ public class ComponentPayloadManagementServiceBean implements ComponentPayloadMa
|
||||
|
||||
@Override
|
||||
public ComponentPayload createButtonPayload(ButtonConfigModel buttonConfigModel, Long serverId) {
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
AServer server;
|
||||
if(serverId != null) {
|
||||
server = serverManagementService.loadOrCreate(serverId);
|
||||
} else {
|
||||
server = null;
|
||||
}
|
||||
return createButtonPayload(buttonConfigModel, server);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.core.service.paginator;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerResult;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListener;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerModel;
|
||||
@@ -31,6 +32,9 @@ public class PaginatorButtonListener implements ButtonClickedListener {
|
||||
@Autowired
|
||||
private TemplateServiceBean templateServiceBean;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
PaginatorButtonPayload payload = (PaginatorButtonPayload) model.getDeserializedPayload();
|
||||
@@ -64,8 +68,12 @@ public class PaginatorButtonListener implements ButtonClickedListener {
|
||||
log.debug("Moving to page {} in paginator {}.", targetPage, payload.getPaginatorId());
|
||||
MessageConfiguration messageConfiguration = payload.getEmbedConfigs().get(targetPage);
|
||||
MessageToSend messageToSend = templateServiceBean.convertEmbedConfigurationToMessageToSend(messageConfiguration);
|
||||
messageService.editMessageInChannel(model.getEvent().getMessageChannel(), messageToSend, originalMessage.getIdLong())
|
||||
.thenAccept(unused -> log.info("Updated paginator {} to switch to page {}.", payload.getPaginatorId(), targetPage));
|
||||
interactionService.replaceOriginal(messageToSend, model.getEvent().getHook())
|
||||
.thenAccept(unused -> log.info("Updated paginator {} to switch to page {}.", payload.getPaginatorId(), targetPage))
|
||||
.exceptionally(throwable -> {
|
||||
log.warn("Failed to update the paginator message.", throwable);
|
||||
return null;
|
||||
});
|
||||
String accessorId = UUID.randomUUID().toString();
|
||||
paginatorServiceBean.updateCurrentPage(payload.getPaginatorId(), targetPage, accessorId);
|
||||
paginatorServiceBean.schedulePaginationDeletion(payload.getPaginatorId(), accessorId);
|
||||
@@ -79,7 +87,7 @@ public class PaginatorButtonListener implements ButtonClickedListener {
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return PaginatorServiceBean.PAGINATOR_BUTTON.equals(model.getOrigin()) && model.getEvent().isFromGuild();
|
||||
return PaginatorServiceBean.PAGINATOR_BUTTON.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -14,6 +14,7 @@ import dev.sheldan.abstracto.core.templating.model.EmbedFooter;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateServiceBean;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
@@ -77,12 +78,12 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createPaginatorFromTemplate(String templateKey, Object model, GuildMessageChannel textChannel, Long userId) {
|
||||
Long serverId = textChannel.getGuild().getIdLong();
|
||||
public CompletableFuture<Void> createPaginatorFromTemplate(String templateKey, Object model, GuildMessageChannel messageChannel, Long userId) {
|
||||
Long serverId = messageChannel.getGuild().getIdLong();
|
||||
PaginatorSetup setup = getPaginatorSetup(templateKey, model, userId, serverId);
|
||||
log.info("Setting up paginator in channel {} in server {} with {} pages.", textChannel.getIdLong(),
|
||||
textChannel.getGuild().getIdLong(), setup.getConfiguration().getEmbedConfigs().size());
|
||||
List<CompletableFuture<Message>> paginatorFutures = channelService.sendMessageToSendToChannel(setup.getMessageToSend(), textChannel);
|
||||
log.info("Setting up paginator in channel {} in server {} with {} pages.", messageChannel.getIdLong(),
|
||||
messageChannel.getGuild().getIdLong(), setup.getConfiguration().getEmbedConfigs().size());
|
||||
List<CompletableFuture<Message>> paginatorFutures = channelService.sendMessageToSendToChannel(setup.getMessageToSend(), messageChannel);
|
||||
return FutureUtils.toSingleFutureGeneric(paginatorFutures)
|
||||
.thenAccept(unused -> self.setupButtonPayloads(paginatorFutures.get(0).join(), setup, serverId));
|
||||
}
|
||||
@@ -106,7 +107,7 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
PaginatorConfiguration configuration = gson.fromJson(embedConfig, PaginatorConfiguration.class);
|
||||
setupFooters(configuration, serverId);
|
||||
|
||||
configuration.setPaginatorId(componentService.generateComponentId());
|
||||
configuration.setPaginatorId(componentService.generateComponentId(serverId));
|
||||
configuration.setSinglePage(configuration.getEmbedConfigs().size() < 2);
|
||||
PaginatorButtonPayload buttonPayload = getButtonPayload(configuration, exitButtonId, startButtonId, previousButtonId, nextButtonId, lastButtonId);
|
||||
if(configuration.getRestrictUser() != null && configuration.getRestrictUser()) {
|
||||
@@ -133,8 +134,8 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createPaginatorFromTemplate(String templateKey, Object model, IReplyCallback callback) {
|
||||
Long serverId = callback.getGuild().getIdLong();
|
||||
PaginatorSetup setup = getPaginatorSetup(templateKey, model, callback.getMember().getIdLong(), serverId);
|
||||
Long serverId = ContextUtils.serverIdOrNull(callback);
|
||||
PaginatorSetup setup = getPaginatorSetup(templateKey, model, callback.getUser().getIdLong(), serverId);
|
||||
return interactionService.replyMessageToSend(setup.getMessageToSend(), callback)
|
||||
.thenCompose(interactionHook -> interactionHook.retrieveOriginal().submit())
|
||||
.thenAccept(message -> self.setupButtonPayloads(message, setup, serverId));
|
||||
@@ -287,9 +288,12 @@ public class PaginatorServiceBean implements PaginatorService {
|
||||
|
||||
@Transactional
|
||||
public void cleanupPaginator(PaginatorInfo paginatorInfo) {
|
||||
// TODO not sure how this is supposed to work, maybe .... not sure
|
||||
log.info("Cleaning up paginator {} in server {} channel {} message {}.", paginatorInfo.getPaginatorId(),
|
||||
paginatorInfo.getServerId(), paginatorInfo.getChannelId(), paginatorInfo.getMessageId());
|
||||
messageService.deleteMessageInChannelInServer(paginatorInfo.getServerId(), paginatorInfo.getChannelId(), paginatorInfo.getMessageId());
|
||||
if(paginatorInfo.getServerId() != null) { // user commands store them with null, and we cannot cleanup those
|
||||
messageService.deleteMessageInChannelInServer(paginatorInfo.getServerId(), paginatorInfo.getChannelId(), paginatorInfo.getMessageId());
|
||||
}
|
||||
componentPayloadManagementService.deletePayloads(paginatorInfo.getPayloadIds());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user