added setup command which includes an interactive process in order to setup features

the current supported features are post targets and system config
the wizard includes a summary step where the user can confirm the changes
removed some unnecessary validators, which were basically just validating the system config from some features
fixed post target name
This commit is contained in:
Sheldan
2020-05-22 17:25:44 +02:00
parent e2f71ef7a3
commit 992357b2cb
81 changed files with 1074 additions and 92 deletions
@@ -9,7 +9,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.models.FullRole;
import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.RoleService;
import dev.sheldan.abstracto.experience.config.features.ExperienceFeature;
@@ -46,7 +45,7 @@ public class ListDisabledExperienceRoles extends AbstractConditionableCommand {
.build();
disabledExperienceRolesModel.getRoles().add(role);
});
channelService.sendTemplateInChannel("list_disabled_experience_roles", disabledExperienceRolesModel, commandContext.getChannel());
channelService.sendEmbedTemplateInChannel("list_disabled_experience_roles", disabledExperienceRolesModel, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@@ -1,22 +0,0 @@
package dev.sheldan.abstracto.experience.validator;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.FeatureValidatorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class ExperienceFeatureValidatorBean implements ExperienceFeatureValidator {
@Autowired
private FeatureValidatorService featureValidatorService;
@Override
public void featureIsSetup(FeatureConfig featureConfig, AServer server, FeatureValidationResult validationResult) {
featureValidatorService.checkSystemConfig("expMultiplier", server, validationResult);
featureValidatorService.checkSystemConfig("minExp", server, validationResult);
featureValidatorService.checkSystemConfig("maxExp", server, validationResult);
}
}
@@ -2,9 +2,6 @@ package dev.sheldan.abstracto.experience.config.features;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.service.FeatureValidator;
import dev.sheldan.abstracto.experience.validator.ExperienceFeatureValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@@ -13,16 +10,13 @@ import java.util.List;
@Component
public class ExperienceFeatureConfig implements FeatureConfig {
@Autowired
private ExperienceFeatureValidator experienceFeatureValidator;
@Override
public FeatureEnum getFeature() {
return ExperienceFeature.EXPERIENCE;
}
@Override
public List<FeatureValidator> getAdditionalFeatureValidators() {
return Arrays.asList(experienceFeatureValidator);
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList("expMultiplier", "minExp", "maxExp");
}
}
@@ -1,6 +0,0 @@
package dev.sheldan.abstracto.experience.validator;
import dev.sheldan.abstracto.core.service.FeatureValidator;
public interface ExperienceFeatureValidator extends FeatureValidator {
}
@@ -44,7 +44,7 @@ public class MyWarnings extends AbstractConditionableCommand {
model.setCurrentWarnCount(currentWarnCount);
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(commandContext.getUserInitiatedContext().getAUserInAServer());
model.setTotalWarnCount(totalWarnCount);
channelService.sendTemplateInChannel("myWarnings_response", model, commandContext.getChannel());
channelService.sendEmbedTemplateInChannel("myWarnings_response", model, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@@ -63,7 +63,7 @@ public class UserNotes extends AbstractConditionableCommand {
userNotes = userNoteManagementService.loadNotesForServer(commandContext.getUserInitiatedContext().getServer());
}
model.setUserNotes(userNotesConverter.fromNotes(userNotes));
channelService.sendTemplateInChannel("user_notes_response", model, commandContext.getChannel());
channelService.sendEmbedTemplateInChannel("user_notes_response", model, commandContext.getChannel());
return CommandResult.fromSuccess();
}
@@ -1,20 +0,0 @@
package dev.sheldan.abstracto.moderation.validator;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.FeatureValidatorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class WarnDecayFeatureValidatorBean implements WarnDecayFeatureValidator {
@Autowired
private FeatureValidatorService featureValidatorService;
@Override
public void featureIsSetup(FeatureConfig featureConfig, AServer server, FeatureValidationResult validationResult) {
featureValidatorService.checkSystemConfig("decayDays", server, validationResult);
}
}
@@ -3,9 +3,7 @@ package dev.sheldan.abstracto.moderation.config.features;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.config.PostTargetEnum;
import dev.sheldan.abstracto.core.service.FeatureValidator;
import dev.sheldan.abstracto.moderation.config.posttargets.WarnDecayPostTarget;
import dev.sheldan.abstracto.moderation.validator.WarnDecayFeatureValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -18,14 +16,17 @@ public class WarningDecayFeature implements FeatureConfig {
@Autowired
private WarningFeature warningFeature;
@Autowired
private WarnDecayFeatureValidator warnDecayFeatureValidator;
@Override
public FeatureEnum getFeature() {
return ModerationFeatures.AUTOMATIC_WARN_DECAY;
}
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList("decayDays");
}
@Override
public List<FeatureConfig> getRequiredFeatures() {
return Arrays.asList(warningFeature);
@@ -36,8 +37,4 @@ public class WarningDecayFeature implements FeatureConfig {
return Arrays.asList(WarnDecayPostTarget.DECAY_LOG);
}
@Override
public List<FeatureValidator> getAdditionalFeatureValidators() {
return Arrays.asList(warnDecayFeatureValidator);
}
}
@@ -5,7 +5,7 @@ import lombok.Getter;
@Getter
public enum LoggingPostTarget implements PostTargetEnum {
LEAVE_LOG("muteLog"), JOIN_LOG("joinLog"), DELETE_LOG("deleteLog"), EDIT_LOG("editLog");
LEAVE_LOG("leaveLog"), JOIN_LOG("joinLog"), DELETE_LOG("deleteLog"), EDIT_LOG("editLog");
private String key;
@@ -1,6 +0,0 @@
package dev.sheldan.abstracto.moderation.validator;
import dev.sheldan.abstracto.core.service.FeatureValidator;
public interface WarnDecayFeatureValidator extends FeatureValidator {
}
@@ -227,7 +227,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.build();
menu.display(initialMessage.getChannel());
} else {
channelService.sendTemplateInChannel("modmail_no_server_available", new Object(), initialMessage.getChannel());
channelService.sendEmbedTemplateInChannel("modmail_no_server_available", new Object(), initialMessage.getChannel());
}
}
@@ -243,7 +243,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.latestModMailThread(latestThread)
.pastModMailThreadCount((long)oldThreads.size())
.build();
List<CompletableFuture<Message>> messages = channelService.sendTemplateInChannel("modmail_thread_header", header, channel);
List<CompletableFuture<Message>> messages = channelService.sendEmbedTemplateInChannel("modmail_thread_header", header, channel);
CompletableFuture.allOf(messages.toArray(new CompletableFuture[0])).whenComplete((aVoid, throwable)-> {
if(throwable != null) {
log.error("Failed to send mod mail header for for user {}.", aUserInAServer.getAUserInAServer().getUserReference().getId(), throwable);
@@ -351,7 +351,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.user(fullUser)
.throwable(throwable)
.build();
channelService.sendTemplateInChannel(template, modMailExceptionModel, channel);
channelService.sendEmbedTemplateInChannel(template, modMailExceptionModel, channel);
} catch (Exception e) {
log.error("Failed to notify about mod mail exception.", e);
}
@@ -443,7 +443,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
HashMap<String, String> closingMessage = new HashMap<>();
String defaultValue = templateService.renderSimpleTemplate("modmail_closing_user_message_description");
closingMessage.put("closingMessage", configService.getStringValue(MODMAIL_CLOSING_MESSAGE_TEXT, modMailThread.getServer().getId(), defaultValue));
messageFutures.addAll(channelService.sendTemplateInChannel("modmail_closing_user_message", closingMessage , privateChannel));
messageFutures.addAll(channelService.sendEmbedTemplateInChannel("modmail_closing_user_message", closingMessage , privateChannel));
} else {
log.trace("*Not* notifying user {}", user.getIdLong());
messageFutures.add(CompletableFuture.completedFuture(null));
@@ -25,7 +25,7 @@ public class ModMailFeature implements FeatureConfig {
@Override
public List<PostTargetEnum> getRequiredPostTargets() {
return Arrays.asList(ModMailPostTargets.MOD_MAIL_PING);
return Arrays.asList(ModMailPostTargets.MOD_MAIL_PING, ModMailPostTargets.MOD_MAIL_LOG);
}
@Override
@@ -42,4 +42,9 @@ public class ModMailFeature implements FeatureConfig {
public List<FeatureMode> getAvailableModes() {
return Arrays.asList(ModMailMode.LOGGING, ModMailMode.NO_LOG);
}
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList("modMailClosingText");
}
}
@@ -0,0 +1,72 @@
package dev.sheldan.abstracto.core.commands.config;
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.features.CoreFeatures;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.interactive.InteractiveService;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.service.FeatureConfigService;
import dev.sheldan.abstracto.core.service.SetupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class Setup extends AbstractConditionableCommand {
@Autowired
private InteractiveService interactiveService;
@Autowired
private FeatureManagementService featureManagementService;
@Autowired
private FeatureConfigService featureConfigService;
@Autowired
private SetupService setupService;
@Override
public CommandResult execute(CommandContext commandContext) {
String name = (String) commandContext.getParameters().getParameters().get(0);
if(featureManagementService.featureExists(name)) {
FeatureConfig feature = featureConfigService.getFeatureDisplayForFeature(name);
AServerChannelUserId initiatingUser = AServerChannelUserId
.builder()
.guildId(commandContext.getGuild().getIdLong())
.channelId(commandContext.getChannel().getIdLong())
.userId(commandContext.getAuthor().getIdLong())
.build();
setupService.performSetup(feature, initiatingUser, commandContext.getMessage().getIdLong());
}
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
Parameter newPrefixParameter = Parameter.builder().name("feature").type(String.class).build();
List<Parameter> parameters = Arrays.asList(newPrefixParameter);
HelpInfo helpInfo = HelpInfo.builder().build();
return CommandConfiguration.builder()
.name("setup")
.module(ConfigModuleInterface.CONFIG)
.parameters(parameters)
.help(helpInfo)
.causesReaction(true)
.build();
}
@Override
public FeatureEnum getFeature() {
return CoreFeatures.CORE_FEATURE;
}
}
@@ -0,0 +1,38 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.exception.SetupStepException;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Getter
@Setter
public abstract class AbstractConfigSetupStep implements SetupStep {
@Autowired
private InteractiveService interactiveService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
protected SetupExecution nextStep;
@Autowired
private InteractiveUtils interactiveUtils;
protected Runnable getTimeoutRunnable(Long serverId, Long channelId) {
return () -> {
interactiveUtils.sendTimeoutMessage(serverId, channelId);
};
}
}
@@ -0,0 +1,117 @@
package dev.sheldan.abstracto.core.interactive;
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.ButtonMenu;
import dev.sheldan.abstracto.core.models.FullUser;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Emote;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@Component
@Slf4j
public class InteractiveServiceBean implements InteractiveService {
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private EventWaiter eventWaiter;
@Autowired
private MessageService messageService;
@Autowired
private EmoteService emoteService;
@Autowired
private BotService botService;
@Override
public void createMessageWithResponse(String templateKey, AUserInAServer responder, AChannel channel, Long messageId, Consumer<MessageReceivedEvent> action, Runnable finalAction) {
String message = templateService.renderSimpleTemplate(templateKey);
channelService.sendTextToAChannel(message, channel);
eventWaiter.waitForEvent(MessageReceivedEvent.class, event -> {
if(event != null) {
return event.getAuthor().getIdLong() == responder.getUserReference().getId() && event.getMessage().getIdLong() != messageId;
}
return false;
}, action, 1, TimeUnit.MINUTES, finalAction);
}
@Override
public void createMessageWithResponse(MessageToSend messageToSend, AUserInAServer responder, AChannel channel, Long messageId, Consumer<MessageReceivedEvent> action, Runnable finalAction) {
channelService.sendMessageToSendToAChannel(messageToSend, channel);
Long userId = responder.getUserReference().getId();
eventWaiter.waitForEvent(MessageReceivedEvent.class, event -> {
if(event != null) {
return event.getAuthor().getIdLong() == userId && event.getMessage().getIdLong() != messageId;
}
return false;
}, action, 1, TimeUnit.MINUTES, finalAction);
}
@Override
public void createMessageWithConfirmation(String text, AUserInAServer responder, AChannel channel, Long messageId, Consumer<Void> confirmation, Consumer<Void> denial, Runnable finalAction) {
Long serverId = responder.getServerReference().getId();
ButtonMenu.Builder builder = new ButtonMenu.Builder();
HashMap<String, Consumer<Void>> actions = new HashMap<>();
addEmoteToBuilder("confirmation", confirmation, serverId, builder, actions);
addEmoteToBuilder("denial", denial, serverId, builder, actions);
ButtonMenu menu = builder
.setEventWaiter(eventWaiter)
.setDescription(text)
.setAction(reactionEmote -> {
if(reactionEmote.isEmoji()) {
actions.get(reactionEmote.getEmoji()).accept(null);
} else {
actions.get(reactionEmote.getEmote().getId()).accept(null);
}
})
.build();
Optional<TextChannel> textChannelInGuild = channelService.getTextChannelInGuild(serverId, channel.getId());
textChannelInGuild.ifPresent(menu::display);
}
private void addEmoteToBuilder(String key, Consumer<Void> consumer, Long serverId, ButtonMenu.Builder builder, HashMap<String, Consumer<Void>> actions) {
AEmote emoteOrFakeEmote = emoteService.getEmoteOrFakeEmote(key, serverId);
if(emoteOrFakeEmote.getCustom()){
Optional<Emote> emote = botService.getEmote(serverId, emoteOrFakeEmote);
emote.ifPresent(emote1 -> {
builder.addChoice(emote1);
actions.put(emote1.getId(), consumer);
});
} else {
builder.addChoice(emoteOrFakeEmote.getEmoteKey());
actions.put(emoteOrFakeEmote.getEmoteKey(), consumer);
}
}
}
@@ -0,0 +1,29 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.templating.service.TemplateService;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Optional;
@Component
public class InteractiveUtils {
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Transactional
public void sendTimeoutMessage(Long serverId, Long channelId) {
String s = templateService.renderSimpleTemplate("setup_configuration_timeout");
Optional<TextChannel> channelOptional = channelService.getTextChannelInGuild(serverId, channelId);
channelOptional.ifPresent(channel -> {
channelService.sendTextToChannelNoFuture(s, channel);
});
}
}
@@ -0,0 +1,23 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PostTargetDelayedAction implements DelayedAction {
@Autowired
private PostTargetManagement postTargetManagement;
@Override
public void execute(DelayedActionConfig delayedActionConfig) {
PostTargetDelayedActionConfig concrete = (PostTargetDelayedActionConfig) delayedActionConfig;
postTargetManagement.createOrUpdate(concrete.getPostTargetKey(), concrete.getServerId(), concrete.getChannelId());
}
@Override
public boolean handles(DelayedActionConfig delayedActionConfig) {
return delayedActionConfig instanceof PostTargetDelayedActionConfig;
}
}
@@ -0,0 +1,33 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.models.template.commands.PostTargetActionModel;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.TextChannel;
@Getter
@Setter
@Builder
public class PostTargetDelayedActionConfig implements DelayedActionConfig {
private String postTargetKey;
private Long serverId;
private Long channelId;
private TextChannel textChannel;
@Override
public String getTemplateName() {
return "setup_post_target_action";
}
@Override
public Object getTemplateModel() {
return PostTargetActionModel
.builder()
.channelId(channelId)
.channel(textChannel)
.postTargetKey(postTargetKey)
.build();
}
}
@@ -0,0 +1,77 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@Component
@Slf4j
public class PostTargetSetupStep extends AbstractConfigSetupStep {
@Autowired
private ConfigService configService;
@Autowired
private InteractiveService interactiveService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private PostTargetSetupStep self;
@Override
public CompletableFuture<List<DelayedActionConfig>> execute(AServerChannelUserId user, SetupStepParameter parameter) {
PostTargetStepParameter systemConfigStepParameter = (PostTargetStepParameter) parameter;
String messageTemplateKey = "setup_posttarget_" + systemConfigStepParameter.getPostTargetKey();
Optional<AChannel> channel = channelManagementService.loadChannel(user.getChannelId());
CompletableFuture<List<DelayedActionConfig>> future = new CompletableFuture<>();
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
if(channel.isPresent()) {
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
try {
if(event.getMessage().getMentionedChannels().size() == 0) {
future.completeExceptionally(new RuntimeException());
}
TextChannel textChannel = event.getMessage().getMentionedChannels().get(0);
PostTargetDelayedActionConfig build = PostTargetDelayedActionConfig
.builder()
.postTargetKey(systemConfigStepParameter.getPostTargetKey())
.serverId(user.getGuildId())
.textChannel(textChannel)
.channelId(textChannel.getIdLong())
.build();
List<DelayedActionConfig> delayedSteps = Arrays.asList(build);
future.complete(delayedSteps);
} catch (Exception e) {
log.error("Failed to handle post target step.", e);
future.completeExceptionally(e);
}
};
interactiveService.createMessageWithResponse(messageTemplateKey, aUserInAServer, channel.get(), parameter.getPreviousMessageId(), configAction, finalAction);
} else {
future.completeExceptionally(new ChannelNotFoundException(user.getGuildId(), user.getChannelId()));
}
return future;
}
}
@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.interactive;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class PostTargetStepParameter implements SetupStepParameter {
private Long previousMessageId;
private String postTargetKey;
}
@@ -0,0 +1,83 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.commands.SetupSummaryModel;
import dev.sheldan.abstracto.core.service.DelayedActionService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@Component
@Slf4j
public class SetupSummaryStep extends AbstractConfigSetupStep {
@Autowired
private InteractiveService interactiveService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private DelayedActionService delayedActionService;
@Autowired
private SetupSummaryStep self;
@Override
public CompletableFuture<List<DelayedActionConfig>> execute(AServerChannelUserId user, SetupStepParameter generalParameter) {
SetupSummaryStepParameter parameter = (SetupSummaryStepParameter) generalParameter;
SetupSummaryModel model = SetupSummaryModel
.builder()
.actionConfigs(parameter.getDelayedActionList())
.build();
String messageToSend = templateService.renderTemplate("setup_confirmation", model);
Optional<AChannel> channel = channelManagementService.loadChannel(user.getChannelId());
CompletableFuture<List<DelayedActionConfig>> future = new CompletableFuture<>();
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
if(channel.isPresent()) {
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<Void> confirmation = (Void none) -> {
try {
self.executeDelayedSteps(parameter);
future.complete(null);
} catch (Exception e) {
future.completeExceptionally(e);
}
};
Consumer<Void> denial = (Void none) -> {
log.info("Stopped wizard.");
};
interactiveService.createMessageWithConfirmation(messageToSend, aUserInAServer, channel.get(), parameter.getPreviousMessageId(), confirmation, denial, finalAction);
} else {
future.completeExceptionally(new ChannelNotFoundException(user.getGuildId(), user.getChannelId()));
}
return future;
}
@Transactional
public void executeDelayedSteps(SetupSummaryStepParameter parameter) {
delayedActionService.executeDelayedActions(parameter.getDelayedActionList());
}
}
@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.interactive;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class SetupSummaryStepParameter implements SetupStepParameter {
private Long previousMessageId;
private List<DelayedActionConfig> delayedActionList;
}
@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SystemConfigDelayedAction implements DelayedAction {
@Autowired
private ConfigService configService;
@Override
public void execute(DelayedActionConfig delayedActionConfig) {
SystemConfigDelayedActionConfig concrete = (SystemConfigDelayedActionConfig) delayedActionConfig;
configService.setConfigValue(concrete.getConfigKey(), concrete.getServerId(), concrete.getValue());
}
@Override
public boolean handles(DelayedActionConfig delayedActionConfig) {
return delayedActionConfig instanceof SystemConfigDelayedActionConfig;
}
}
@@ -0,0 +1,29 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.models.template.commands.SystemConfigActionModel;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SystemConfigDelayedActionConfig implements DelayedActionConfig {
private String configKey;
private Long serverId;
private String value;
@Override
public String getTemplateName() {
return "setup_system_config_action";
}
@Override
public Object getTemplateModel() {
return SystemConfigActionModel
.builder()
.configKey(this.configKey)
.newValue(this.value)
.build();
}
}
@@ -0,0 +1,78 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.exception.ChannelNotFoundException;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
@Component
@Slf4j
public class SystemConfigSetupStep extends AbstractConfigSetupStep {
@Autowired
private ConfigService configService;
@Autowired
private InteractiveService interactiveService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private SystemConfigSetupStep self;
@Override
public CompletableFuture<List<DelayedActionConfig>> execute(AServerChannelUserId user, SetupStepParameter parameter) {
SystemConfigStepParameter systemConfigStepParameter = (SystemConfigStepParameter) parameter;
String messageTemplateKey = "setup_config_" + systemConfigStepParameter.getConfigKey();
Optional<AChannel> channel = channelManagementService.loadChannel(user.getChannelId());
CompletableFuture<List<DelayedActionConfig>> future = new CompletableFuture<>();
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
if(channel.isPresent()) {
Runnable finalAction = super.getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
try {
self.checkValidity(user, systemConfigStepParameter, event);
SystemConfigDelayedActionConfig build = SystemConfigDelayedActionConfig
.builder()
.configKey(systemConfigStepParameter.getConfigKey())
.serverId(user.getGuildId())
.value(event.getMessage().getContentRaw())
.build();
List<DelayedActionConfig> delayedSteps = Arrays.asList(build);
future.complete(delayedSteps);
} catch (Exception e) {
future.completeExceptionally(e);
}
};
interactiveService.createMessageWithResponse(messageTemplateKey, aUserInAServer, channel.get(), parameter.getPreviousMessageId(), configAction, finalAction);
} else {
future.completeExceptionally(new ChannelNotFoundException(user.getGuildId(), user.getChannelId()));
}
return future;
}
@Transactional
public void checkValidity(AServerChannelUserId user, SystemConfigStepParameter systemConfigStepParameter, MessageReceivedEvent event) {
configService.validateConfig(systemConfigStepParameter.getConfigKey(), user.getGuildId(), event.getMessage().getContentRaw());
}
}
@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.interactive;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SystemConfigStepParameter implements SetupStepParameter {
private Long previousMessageId;
private String configKey;
}
@@ -182,7 +182,7 @@ public class ChannelServiceBean implements ChannelService {
@Override
@Transactional
public List<CompletableFuture<Message>> sendTemplateInChannel(String templateKey, Object model, MessageChannel channel) {
public List<CompletableFuture<Message>> sendEmbedTemplateInChannel(String templateKey, Object model, MessageChannel channel) {
MessageToSend messageToSend = templateService.renderEmbedTemplate(templateKey, model);
return sendMessageToSendToChannel(messageToSend, channel);
}
@@ -92,4 +92,28 @@ public class ConfigServiceBean implements ConfigService{
throw new ConfigurationKeyNotFoundException(name);
}
}
@Override
public boolean configIsFitting(String name, Long serverId, String value) {
try {
validateConfig(name, serverId, value);
return true;
} catch (Exception e) {
return false;
}
}
@Override
public void validateConfig(String name, Long serverId, String value) {
if(configManagementService.configExists(serverId, name)) {
AConfig existing = configManagementService.loadConfig(serverId, name);
if(existing.getDoubleValue() != null) {
Double.parseDouble(value);
} else if(existing.getLongValue() != null) {
Long.parseLong(value);
}
} else {
throw new ConfigurationKeyNotFoundException(name);
}
}
}
@@ -0,0 +1,25 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.interactive.DelayedAction;
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class DelayedActionServiceBean implements DelayedActionService {
@Autowired
private List<DelayedAction> delayedActions;
@Override
public void executeDelayedActions(List<DelayedActionConfig> delayedActionConfigList) {
delayedActionConfigList.forEach(delayedActionConfig -> {
delayedActions.stream()
.filter(delayedAction -> delayedAction.handles(delayedActionConfig))
.findFirst()
.ifPresent(delayedAction -> delayedAction.execute(delayedActionConfig));
});
}
}
@@ -13,6 +13,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@@ -37,27 +39,42 @@ public class MessageServiceBean implements MessageService {
@Override
public void addReactionToMessage(String emoteKey, Long serverId, Message message) {
addReactionToMessageWithFuture(emoteKey, serverId, message);
}
@Override
public CompletableFuture<Void> addReactionToMessageWithFuture(String emoteKey, Long serverId, Message message) {
Optional<Guild> guildByIdOptional = botService.getGuildById(serverId);
AEmote emote = emoteService.getEmoteOrFakeEmote(emoteKey, serverId);
if(guildByIdOptional.isPresent()) {
Guild guild = guildByIdOptional.get();
if(emote.getCustom()) {
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
if(emoteById != null) {
message.addReaction(emoteById).queue();
} else {
log.error("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guild.getId());
throw new EmoteNotDefinedException(emoteKey);
}
if(emote.getCustom()) {
Emote emoteById = botService.getInstance().getEmoteById(emote.getEmoteId());
if(emoteById != null) {
return message.addReaction(emoteById).submit();
} else {
message.addReaction(emote.getEmoteKey()).queue();
log.error("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guild.getId());
throw new EmoteNotDefinedException(emoteKey);
}
} else {
return message.addReaction(emote.getEmoteKey()).submit();
}
} else {
log.error("Cannot add reaction, guild not found {}", serverId);
throw new GuildException(serverId);
}
}
@Override
public List<CompletableFuture<Void>> addReactionsToMessageWithFuture(List<String> emoteKeys, Long serverId, Message message) {
List<CompletableFuture<Void>> futures = new ArrayList<>();
emoteKeys.forEach(s -> {
futures.add(addReactionToMessageWithFuture(s, serverId, message));
});
return futures;
}
@Override
public CompletableFuture<Void> deleteMessageInChannelInServer(Long serverId, Long channelId, Long messageId) {
return botService.deleteMessage(serverId, channelId, messageId);
@@ -0,0 +1,117 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.interactive.*;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.template.commands.SetupCompletedNotificationModel;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.TextChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
public class SetupServiceBean implements SetupService {
@Autowired
private SystemConfigSetupStep systemConfigSetupStep;
@Autowired
private PostTargetSetupStep postTargetSetupStep;
@Autowired
private DelayedActionService delayedActionService;
@Autowired
private SetupServiceBean self;
@Autowired
private SetupSummaryStep setupSummaryStep;
@Autowired
private ChannelService channelService;
@Autowired
private TemplateService templateService;
@Override
public void performSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId) {
List<String> requiredSystemConfigKeys = featureConfig.getRequiredSystemConfigKeys();
List<SetupExecution> steps = new ArrayList<>();
requiredSystemConfigKeys.forEach(s -> {
SetupExecution execution = SetupExecution
.builder()
.step(systemConfigSetupStep)
.parameter(SystemConfigStepParameter.builder().configKey(s).build())
.build();
steps.add(execution);
});
featureConfig.getRequiredPostTargets().forEach(postTargetEnum -> {
SetupExecution execution = SetupExecution
.builder()
.step(postTargetSetupStep)
.parameter(PostTargetStepParameter.builder().postTargetKey(postTargetEnum.getKey()).build())
.build();
steps.add(execution);
});
for (int i = 0; i < steps.size(); i++) {
SetupExecution setupExecution = steps.get(i);
setupExecution.getParameter().setPreviousMessageId(initialMessageId);
if(i < steps.size() - 1) {
setupExecution.setNextStep(steps.get(i + 1));
}
}
executeSetup(featureConfig, steps, user, new ArrayList<>());
}
@Override
public void executeSetup(FeatureConfig featureConfig, List<SetupExecution> steps, AServerChannelUserId user, List<DelayedActionConfig> delayedActionConfigs) {
steps.stream().findFirst().ifPresent(execution -> executeStep(user, execution, delayedActionConfigs, featureConfig));
}
private void executeStep(AServerChannelUserId aUserInAServer, SetupExecution execution, List<DelayedActionConfig> delayedActionConfigs, FeatureConfig featureConfig) {
execution.getStep().execute(aUserInAServer, execution.getParameter()).thenAccept(aVoid -> {
delayedActionConfigs.addAll(aVoid);
if(execution.getNextStep() != null) {
executeStep(aUserInAServer, execution.getNextStep(), delayedActionConfigs, featureConfig);
} else {
self.executePostSetupSteps(delayedActionConfigs, aUserInAServer, execution.getParameter().getPreviousMessageId(), featureConfig);
}
}).exceptionally(throwable -> {
executeStep(aUserInAServer, execution, delayedActionConfigs, featureConfig);
return null;
});
}
@Transactional
public void executePostSetupSteps(List<DelayedActionConfig> delayedActionConfigs, AServerChannelUserId user, Long initialMessage, FeatureConfig featureConfig) {
SetupSummaryStepParameter parameter = SetupSummaryStepParameter
.builder()
.delayedActionList(delayedActionConfigs)
.previousMessageId(initialMessage)
.build();
setupSummaryStep.execute(user, parameter).thenAccept(ignored -> {
self.notifyAboutCompletion(user, featureConfig);
});
}
@Transactional
public void notifyAboutCompletion(AServerChannelUserId aServerChannelUserId, FeatureConfig featureConfig) {
String templateName = "setup_completion_notification";
SetupCompletedNotificationModel model = SetupCompletedNotificationModel
.builder()
.completedFeature(featureConfig)
.build();
String text = templateService.renderTemplate(templateName, model);
Optional<TextChannel> textChannel = channelService.getTextChannelInGuild(aServerChannelUserId.getGuildId(), aServerChannelUserId.getChannelId());
textChannel.ifPresent(channel -> channelService.sendTextToChannel(text, channel));
}
}
@@ -4,4 +4,8 @@ abstracto.parameter.lowerBound=50
abstracto.features.core.enabled=true
abstracto.prefix=!
abstracto.eventWaiter.threads=10
abstracto.eventWaiter.threads=10
abstracto.emoteNames.confirmation=confirmation,denial
abstracto.defaultEmotes.confirmation=\u2705
abstracto.defaultEmotes.denial=\u274c
@@ -0,0 +1 @@
<#assign featureName><#include "${completedFeature.feature.key}_feature"></#assign><#include "setup_completion_message">
@@ -0,0 +1,5 @@
<#list actionConfigs as actionConfig>
<#assign param=actionConfig.templateModel>
<#include "${actionConfig.templateName}">
</#list>
@@ -0,0 +1 @@
<#assign postTargetKey>${param.postTargetKey}</#assign><#assign channel>${param.channel.asMention}</#assign><#include "setup_post_target_action_display">
@@ -0,0 +1 @@
<#assign configKey>${param.configKey}</#assign><#assign newValue>${param.newValue}</#assign><#include "setup_system_config_action_display">
@@ -0,0 +1,19 @@
package dev.sheldan.abstracto.core.exception;
import dev.sheldan.abstracto.templating.Templatable;
public class SetupStepException extends AbstractoRunTimeException implements Templatable {
public SetupStepException(String message) {
super(message);
}
@Override
public String getTemplateName() {
return "setup_configuration_timeout";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}
@@ -0,0 +1,7 @@
package dev.sheldan.abstracto.core.interactive;
public interface DelayedAction {
void execute(DelayedActionConfig delayedActionConfig);
boolean handles(DelayedActionConfig delayedActionConfig);
}
@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.templating.Templatable;
public interface DelayedActionConfig extends Templatable {
}
@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import java.util.function.Consumer;
public interface InteractiveService {
void createMessageWithResponse(String templateKey, AUserInAServer responder, AChannel channel, Long messageId, Consumer<MessageReceivedEvent> action, Runnable finalAction);
void createMessageWithResponse(MessageToSend messageToSend, AUserInAServer responder, AChannel channel, Long messageId, Consumer<MessageReceivedEvent> action, Runnable finalAction);
void createMessageWithConfirmation(String text, AUserInAServer responder, AChannel channel, Long messageId, Consumer<Void> confirmation, Consumer<Void> denial, Runnable finalAction);
}
@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.interactive;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SetupExecution {
private SetupStep step;
private SetupStepParameter parameter;
private SetupExecution nextStep;
}
@@ -0,0 +1,11 @@
package dev.sheldan.abstracto.core.interactive;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public interface SetupStep {
CompletableFuture<List<DelayedActionConfig>> execute(AServerChannelUserId aUserInAServer, SetupStepParameter parameter);
}
@@ -0,0 +1,6 @@
package dev.sheldan.abstracto.core.interactive;
public interface SetupStepParameter {
Long getPreviousMessageId();
void setPreviousMessageId(Long previousMessageId);
}
@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.core.models;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class AServerChannelUserId {
private Long guildId;
private Long channelId;
private Long userId;
}
@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.models.template.commands;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.TextChannel;
@Getter
@Setter
@Builder
public class PostTargetActionModel {
private String postTargetKey;
private Long channelId;
private TextChannel channel;
}
@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.models.template.commands;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SetupCompletedNotificationModel {
private FeatureConfig completedFeature;
}
@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.core.models.template.commands;
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
@Builder
public class SetupSummaryModel {
private List<DelayedActionConfig> actionConfigs;
}
@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.models.template.commands;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class SystemConfigActionModel {
private String configKey;
private Object newValue;
}
@@ -28,7 +28,7 @@ public interface ChannelService {
void editMessageInAChannel(MessageToSend messageToSend, MessageChannel channel, Long messageId);
CompletableFuture<Void> deleteTextChannel(AChannel channel);
CompletableFuture<Void> deleteTextChannel(Long serverId, Long channelId);
List<CompletableFuture<Message>> sendTemplateInChannel(String templateKey, Object model, MessageChannel channel);
List<CompletableFuture<Message>> sendEmbedTemplateInChannel(String templateKey, Object model, MessageChannel channel);
CompletableFuture<TextChannel> createTextChannel(String name, AServer server, Long categoryId);
}
@@ -10,5 +10,7 @@ public interface ConfigService {
void setLongValue(String name, Long serverId, Long value);
void setConfigValue(String name, Long serverId, String value);
void setStringValue(String name, Long serverId, String value);
boolean configIsFitting(String name, Long serverId, String value);
void validateConfig(String name, Long serverId, String value);
}
@@ -0,0 +1,9 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
import java.util.List;
public interface DelayedActionService {
void executeDelayedActions(List<DelayedActionConfig> delayedActionConfigList);
}
@@ -7,10 +7,13 @@ import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public interface MessageService {
void addReactionToMessage(String emoteKey, Long serverId, Message message);
CompletableFuture<Void> addReactionToMessageWithFuture(String emoteKey, Long serverId, Message message);
List<CompletableFuture<Void>> addReactionsToMessageWithFuture(List<String> emoteKeys, Long serverId, Message message);
CompletableFuture<Void> deleteMessageInChannelInServer(Long serverId, Long channelId, Long messageId);
CompletableFuture<Message> createStatusMessage(MessageToSend messageToSend, AChannel channel);
void updateStatusMessage(AChannel channel, Long messageId, MessageToSend messageToSend);
@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.interactive.DelayedActionConfig;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.interactive.SetupExecution;
import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import java.util.List;
public interface SetupService {
void performSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId);
void executeSetup(FeatureConfig featureConfig, List<SetupExecution> steps, AServerChannelUserId user, List<DelayedActionConfig> delayedActionConfigs);
}
@@ -0,0 +1 @@
Helps to setup the necessary configuration for a feature.
@@ -0,0 +1,2 @@
Guides you through an interactive wizard where post targets, system configs and other necessary configurations for a feature are setup.
At the end you have the possibility to review the changes, before applying them.
@@ -0,0 +1 @@
${featureName} has been successfully setup.
@@ -0,0 +1 @@
Mod mail category to be used for something
@@ -0,0 +1 @@
Post target ${postTargetKey} will be set to channel ${channel}.
@@ -0,0 +1 @@
System config ${configKey} will be set to ${newValue}.
@@ -0,0 +1 @@
The value each gained experience is multiplied by. Default 1.0
@@ -0,0 +1 @@
The maximum of experience given randomly. Default: 25
@@ -0,0 +1 @@
The minimum experience given randomly. Default: 10
@@ -0,0 +1 @@
The amount of days after which a warning is decayed.
@@ -0,0 +1 @@
The channel in which where bans should be logged to.
@@ -0,0 +1 @@
The channel in which decayed warnings should be logged to.
@@ -0,0 +1 @@
The channel in which deleted messages should be logged to.
@@ -0,0 +1 @@
The channel in which edited messages should be logged to.
@@ -0,0 +1 @@
The channel in which guild joins should be logged to.
@@ -0,0 +1 @@
The channel in which kicks should be logged to.
@@ -0,0 +1 @@
The channel where guild leavers should be logged to.
@@ -0,0 +1 @@
The channel where mutes should be logged to. Un-mutes will also be in this channel.
@@ -0,0 +1 @@
The channel where warnings should be logged to.
@@ -0,0 +1 @@
The channel towards which the closed mod mail threads should be logged to. (In the appropriate mode)
@@ -0,0 +1 @@
The channel which should be used to notify the responsible people about new mod mail threads.