diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/BanId.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/BanId.java index 96fb291ad..990aaa626 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/BanId.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/BanId.java @@ -38,7 +38,7 @@ public class BanId extends AbstractConditionableCommand { banLogModel.setBannedUserId(userId); banLogModel.setBanningUser(commandContext.getAuthor()); banLogModel.setReason(reason); - return banService.banMember(commandContext.getGuild().getIdLong(), userId, reason, banLogModel) + return banService.banUserViaId(commandContext.getGuild().getIdLong(), userId, reason, banLogModel) .thenApply(aVoid -> CommandResult.fromSuccess()); } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarnings.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarnings.java index 3f745b1b9..6cce342f4 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarnings.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarnings.java @@ -26,18 +26,14 @@ public class DecayAllWarnings extends AbstractConditionableCommand { @Override public CompletableFuture executeAsync(CommandContext commandContext) { checkParameters(commandContext); - List parameters = commandContext.getParameters().getParameters(); - boolean logWarnings = !parameters.isEmpty() ? (Boolean) parameters.get(0) : Boolean.FALSE; - return warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer(), logWarnings) + return warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer()) .thenApply(aVoid -> CommandResult.fromSuccess()); } @Override public CommandConfiguration getConfiguration() { List parameters = new ArrayList<>(); - Parameter logWarnings = Parameter.builder().optional(true).name("writeLog").templated(true).type(Boolean.class).build(); HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); - parameters.add(logWarnings); return CommandConfiguration.builder() .name("decayAllWarnings") .module(ModerationModule.MODERATION) diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/Kick.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/Kick.java index c51926e30..f643a3e74 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/Kick.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/Kick.java @@ -56,6 +56,7 @@ public class Kick extends AbstractConditionableCommand { .module(ModerationModule.MODERATION) .templated(true) .supportsEmbedException(true) + .async(true) .causesReaction(true) .parameters(parameters) .help(helpInfo) diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/mute/UnMute.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/mute/UnMute.java index c02d26fcd..2c46d0e1c 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/mute/UnMute.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/commands/mute/UnMute.java @@ -25,7 +25,6 @@ import java.util.concurrent.CompletableFuture; @Component public class UnMute extends AbstractConditionableCommand { - public static final String NO_ACTIVE_MUTE = "unMute_has_no_active_mute"; @Autowired private MuteService muteService; diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java index cb0a0dbc6..d8bcd3efb 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java @@ -3,8 +3,11 @@ package dev.sheldan.abstracto.moderation.service; import dev.sheldan.abstracto.core.exception.GuildNotFoundException; import dev.sheldan.abstracto.core.models.context.ServerContext; import dev.sheldan.abstracto.core.service.BotService; +import dev.sheldan.abstracto.core.service.FeatureModeService; import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.ModerationMode; import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget; import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.templating.service.TemplateService; @@ -12,6 +15,7 @@ import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; +import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -35,20 +39,36 @@ public class BanServiceBean implements BanService { @Autowired private PostTargetService postTargetService; + @Autowired + private FeatureModeService featureModeService; + @Override public CompletableFuture banMember(Member member, String reason, ServerContext banLog) { CompletableFuture banFuture = banUser(member.getGuild(), member.getIdLong(), reason); - MessageToSend banLogMessage = templateService.renderEmbedTemplate(BAN_LOG_TEMPLATE, banLog); - List> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, member.getGuild().getIdLong()); - return CompletableFuture.allOf(banFuture, FutureUtils.toSingleFutureGeneric(notificationFutures)); + CompletableFuture messageFuture = sendBanLogMessage(banLog, member.getGuild().getIdLong(), BAN_LOG_TEMPLATE); + return CompletableFuture.allOf(banFuture, messageFuture); + } + + @NotNull + public CompletableFuture sendBanLogMessage(ServerContext banLog, Long guildId, String template) { + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.MODERATION, guildId, ModerationMode.BAN_LOG)) { + MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog); + log.trace("Sending ban log message in guild {}.", guildId); + List> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId); + completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures); + } else { + log.trace("Feature {} has mode {} for logging disabled for server {}. Not sending notification.", ModerationFeatures.MODERATION, ModerationMode.BAN_LOG, guildId); + completableFuture = CompletableFuture.completedFuture(null); + } + return completableFuture; } @Override - public CompletableFuture banMember(Long guildId, Long userId, String reason, ServerContext banIdLog) { + public CompletableFuture banUserViaId(Long guildId, Long userId, String reason, ServerContext banIdLog) { CompletableFuture banFuture = banUser(guildId, userId, reason); - MessageToSend banLogMessage = templateService.renderEmbedTemplate(BAN_ID_LOG_TEMPLATE, banIdLog); - List> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId); - return CompletableFuture.allOf(banFuture, FutureUtils.toSingleFutureGeneric(notificationFutures)); + CompletableFuture messageFuture = sendBanLogMessage(banIdLog, guildId, BAN_ID_LOG_TEMPLATE); + return CompletableFuture.allOf(banFuture, messageFuture); } private CompletableFuture banUser(Long guildId, Long userId, String reason) { diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java index 62d6a3145..23dc9332e 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java @@ -1,7 +1,10 @@ package dev.sheldan.abstracto.moderation.service; +import dev.sheldan.abstracto.core.service.FeatureModeService; import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.ModerationMode; import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget; import dev.sheldan.abstracto.moderation.models.template.commands.KickLogModel; import dev.sheldan.abstracto.templating.model.MessageToSend; @@ -26,6 +29,9 @@ public class KickServiceBean implements KickService { @Autowired private PostTargetService postTargetService; + @Autowired + private FeatureModeService featureModeService; + @Override public CompletableFuture kickMember(Member member, String reason, KickLogModel kickLogModel) { Guild guild = member.getGuild(); @@ -36,7 +42,15 @@ public class KickServiceBean implements KickService { } private CompletableFuture sendKickLog(KickLogModel kickLogModel) { - MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel); - return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong())); + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.MODERATION, kickLogModel.getGuild().getIdLong(), ModerationMode.KICK_LOG)) { + MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel); + log.trace("Sending kick log message in guild {}.", kickLogModel.getGuild().getIdLong()); + completableFuture = FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong())); + } else { + log.trace("Feature {} has mode {} for logging disabled for server {}. Not sending kick notification.", ModerationFeatures.MODERATION, ModerationMode.BAN_LOG, kickLogModel.getGuild().getIdLong()); + completableFuture = CompletableFuture.completedFuture(null); + } + return completableFuture; } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/MuteServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/MuteServiceBean.java index fbbb59a02..9461c6b9e 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/MuteServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/MuteServiceBean.java @@ -11,6 +11,8 @@ import dev.sheldan.abstracto.core.service.management.ChannelManagementService; import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.MutingMode; import dev.sheldan.abstracto.moderation.config.posttargets.MutingPostTarget; import dev.sheldan.abstracto.moderation.exception.MuteRoleNotSetupException; import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException; @@ -39,7 +41,6 @@ import java.util.Date; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -90,6 +91,9 @@ public class MuteServiceBean implements MuteService { @Autowired private ServerManagementService serverManagementService; + @Autowired + private FeatureModeService featureModeService; + public static final String MUTE_LOG_TEMPLATE = "mute_log"; public static final String UN_MUTE_LOG_TEMPLATE = "unmute_log"; public static final String MUTE_NOTIFICATION_TEMPLATE = "mute_notification"; @@ -212,12 +216,12 @@ public class MuteServiceBean implements MuteService { @Override public CompletableFuture muteMemberWithLog(MuteContext context) { - log.trace("Muting member {} in server {} and sending a mute log.", context.getMutedUser().getId(), context.getMutedUser().getGuild().getId()); + log.trace("Muting member {} in server {}.", context.getMutedUser().getId(), context.getMutedUser().getGuild().getId()); AServer server = serverManagementService.loadOrCreate(context.getContext().getServerId()); Long nextCounterValue = counterService.getNextCounterValue(server, MUTE_COUNTER_KEY); context.setMuteId(nextCounterValue); CompletableFuture mutingFuture = muteMember(context.getMutedUser(), context.getMutingUser(), context.getReason(), context.getMuteTargetDate(), context.getContext()); - CompletableFuture muteLogFuture = sendMuteLog(context); + CompletableFuture muteLogFuture = sendMuteLog(context, server); return CompletableFuture.allOf(mutingFuture, muteLogFuture).thenAccept(aVoid -> self.persistMute(context) ); @@ -229,24 +233,38 @@ public class MuteServiceBean implements MuteService { createMuteObject(context, triggerKey); } - public CompletableFuture sendMuteLog(MuteContext muteLogModel) { - log.trace("Sending mute log to the mute posttarget."); - MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel); - List> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()); - return FutureUtils.toSingleFutureGeneric(completableFutures); + private CompletableFuture sendMuteLog(MuteContext muteLogModel, AServer server) { + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.MUTING, server, MutingMode.MUTE_LOGGING)) { + log.trace("Sending mute log to the mute post target."); + MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel); + List> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()); + completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures); + } else { + completableFuture = CompletableFuture.completedFuture(null); + log.trace("Not sending mute log, because feature mode {} in feature {} has been disabled for server {}.", MutingMode.MUTE_LOGGING, ModerationFeatures.WARNING, server.getId()); + } + return completableFuture; } - private CompletableFuture sendUnMuteLogMessage(UnMuteLog muteLogModel) { - log.trace("Sending unMute log to the mute posttarget."); - MessageToSend message = templateService.renderEmbedTemplate(UN_MUTE_LOG_TEMPLATE, muteLogModel); - List> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getServer().getId()); - return FutureUtils.toSingleFutureGeneric(completableFutures); + private CompletableFuture sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) { + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.MUTING, server, MutingMode.MUTE_LOGGING)) { + log.trace("Sending unMute log for mute {} to the mute posttarget in server {}", muteLogModel.getMute().getMuteId().getId(), server.getId()); + MessageToSend message = templateService.renderEmbedTemplate(UN_MUTE_LOG_TEMPLATE, muteLogModel); + List> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getServer().getId()); + completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures); + } else { + completableFuture = CompletableFuture.completedFuture(null); + log.trace("Not sending unMute log, because feature mode {} in feature {} has been disabled for server {}.", MutingMode.UN_MUTE_LOGGING, ModerationFeatures.WARNING, server.getId()); + } + return completableFuture; } @Override @Transactional public CompletableFuture unMuteUser(AUserInAServer aUserInAServer) { - if(muteManagementService.hasActiveMute(aUserInAServer)) { + if(!muteManagementService.hasActiveMute(aUserInAServer)) { throw new NoMuteFoundException(); } Mute mute = muteManagementService.getAMuteOf(aUserInAServer); @@ -254,7 +272,27 @@ public class MuteServiceBean implements MuteService { log.info("Mute {} has ended already, user {} does not need to be unMuted anymore.", mute.getMuteId().getId(), mute.getMutedUser().getUserReference().getId()); return CompletableFuture.completedFuture(null); } - return endMute(mute); + Long muteId = mute.getMuteId().getId(); + CompletableFuture mutingMemberFuture = botService.getMemberInServerAsync(mute.getMutingUser()); + CompletableFuture mutedMemberFuture = botService.getMemberInServerAsync(mute.getMutedUser()); + Guild guild = botService.getGuildById(mute.getServer().getId()); + return endMute(mute).thenCompose(unused -> + CompletableFuture.allOf(mutingMemberFuture, mutedMemberFuture) + ).thenCompose(unused -> self.sendUnMuteLogForManualUnMute(muteId, mutingMemberFuture, mutedMemberFuture, guild)); + } + + @Transactional + public CompletableFuture sendUnMuteLogForManualUnMute(Long muteId, CompletableFuture mutingMemberFuture, CompletableFuture mutedMemberFuture, Guild guild) { + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.MUTING, guild.getIdLong(), MutingMode.MANUAL_UN_MUTE_LOGGING)) { + completableFuture = self.sendUnmuteLog(muteId, guild, mutingMemberFuture, mutedMemberFuture); + log.trace("Sending un mute notification for manual un mute for mute {} in server {}.", muteId, guild.getIdLong()); + } else { + completableFuture = CompletableFuture.completedFuture(null); + log.trace("Not sending unMute log, because feature mode {} in feature {} has been disabled for server {}.", MutingMode.MANUAL_UN_MUTE_LOGGING, ModerationFeatures.WARNING, guild.getIdLong()); + + } + return completableFuture; } @Override @@ -287,7 +325,7 @@ public class MuteServiceBean implements MuteService { } @Transactional - public CompletionStage sendUnmuteLog(Long muteId, Guild guild, CompletableFuture mutingMemberFuture, CompletableFuture mutedMemberFuture) { + public CompletableFuture sendUnmuteLog(Long muteId, Guild guild, CompletableFuture mutingMemberFuture, CompletableFuture mutedMemberFuture) { Mute mute = muteManagementService.findMute(muteId, guild.getIdLong()); AServer mutingServer = serverManagementService.loadServer(guild.getIdLong()); UnMuteLog unMuteLog = UnMuteLog @@ -298,7 +336,7 @@ public class MuteServiceBean implements MuteService { .guild(guild) .server(mutingServer) .build(); - CompletableFuture notificationFuture = sendUnMuteLogMessage(unMuteLog); + CompletableFuture notificationFuture = sendUnMuteLogMessage(unMuteLog, mutingServer); return CompletableFuture.allOf(notificationFuture).thenAccept(aVoid -> self.endMuteInDatabase(muteId, guild.getIdLong()) ); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java index 706386efe..118c9e5bc 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java @@ -6,7 +6,10 @@ import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.service.*; import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.WarnDecayMode; import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature; +import dev.sheldan.abstracto.moderation.config.features.WarningMode; import dev.sheldan.abstracto.moderation.config.posttargets.WarnDecayPostTarget; import dev.sheldan.abstracto.moderation.config.posttargets.WarningPostTarget; import dev.sheldan.abstracto.moderation.models.template.job.WarnDecayLogModel; @@ -66,6 +69,9 @@ public class WarnServiceBean implements WarnService { @Autowired private ServerManagementService serverManagementService; + @Autowired + private FeatureModeService featureModeService; + @Autowired private WarnServiceBean self; @@ -87,8 +93,13 @@ public class WarnServiceBean implements WarnService { String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification); List> futures = new ArrayList<>(); futures.add(messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage)); - MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context); - futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong())); + if(featureModeService.featureModeActive(ModerationFeatures.WARNING, server.getId(), WarningMode.WARN_LOG)) { + log.trace("Logging warning for server {}.", server.getId()); + MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context); + futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong())); + } else { + log.trace("Not logging warning because of feature {} with feature mode {} in server {}.", ModerationFeatures.WARNING, WarningMode.WARN_LOG, server.getId()); + } return FutureUtils.toSingleFutureGeneric(futures); } @@ -119,7 +130,15 @@ public class WarnServiceBean implements WarnService { List warningsToDecay = warnManagementService.getActiveWarningsInServerOlderThan(server, cutOffDay); List warningIds = flattenWarnings(warningsToDecay); Long serverId = server.getId(); - return logDecayedWarnings(server, warningsToDecay).thenAccept(aVoid -> + CompletableFuture completableFuture; + if(featureModeService.featureModeActive(ModerationFeatures.AUTOMATIC_WARN_DECAY, server, WarnDecayMode.AUTOMATIC_WARN_DECAY_LOG)) { + log.trace("Sending log messages for automatic warn decay in server {}.", server.getId()); + completableFuture = logDecayedWarnings(server, warningsToDecay); + } else { + log.trace("Not logging automatic warn decay, because feature {} has its mode {} disabled in server {}.", ModerationFeatures.AUTOMATIC_WARN_DECAY, WarnDecayMode.AUTOMATIC_WARN_DECAY_LOG, server.getId()); + completableFuture = CompletableFuture.completedFuture(null); + } + return completableFuture.thenAccept(aVoid -> self.decayWarnings(warningIds, serverId) ); } @@ -187,8 +206,8 @@ public class WarnServiceBean implements WarnService { // TODO add ids to render in case any member left the server WarnDecayWarning warnDecayWarning = WarnDecayWarning .builder() - .warnedMember(pair.getFirstMember().join()) - .warningMember(pair.getSecondMember().join()) + .warningMember(pair.getFirstMember().join()) + .warnedMember(pair.getSecondMember().join()) .warning(warning) .build(); warnDecayWarnings.add(warnDecayWarning); @@ -205,16 +224,18 @@ public class WarnServiceBean implements WarnService { } @Override - public CompletableFuture decayAllWarningsForServer(AServer server, boolean logWarnings) { + public CompletableFuture decayAllWarningsForServer(AServer server) { List warningsToDecay = warnManagementService.getActiveWarningsInServerOlderThan(server, Instant.now()); List warnIds = flattenWarnings(warningsToDecay); - log.info("Decaying ALL warning in server {} with logging {}.", server.getId(), logWarnings); + log.info("Decaying ALL warning in server {}.", server.getId()); Long serverId = server.getId(); - if(logWarnings) { + if(featureModeService.featureModeActive(ModerationFeatures.WARNING, server, WarningMode.WARN_DECAY_LOG)) { + log.trace("Logging warn decays in server {}", serverId); return logDecayedWarnings(server, warningsToDecay).thenAccept(aVoid -> self.decayWarnings(warnIds, serverId) ); } else { + log.trace("Not logging warn decays for manual decay in server {} because feature {} with feature mode: {}", serverId, ModerationFeatures.WARNING, WarningMode.WARN_DECAY_LOG); decayWarnings(warnIds, serverId); return CompletableFuture.completedFuture(null); } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/migrations/1.0-moderation/moderation-seedData/default_feature_mode.xml b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/migrations/1.0-moderation/moderation-seedData/default_feature_mode.xml new file mode 100644 index 000000000..d269b17ab --- /dev/null +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/migrations/1.0-moderation/moderation-seedData/default_feature_mode.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/BanIdTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/BanIdTest.java index 7afc3d4c1..f311300fe 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/BanIdTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/BanIdTest.java @@ -44,7 +44,7 @@ public class BanIdTest { Long guildId = parameters.getUserInitiatedContext().getServer().getId(); when(templateService.renderSimpleTemplate(Ban.BAN_DEFAULT_REASON_TEMPLATE)).thenReturn(REASON); when(parameters.getGuild().getIdLong()).thenReturn(guildId); - when(banService.banMember(eq(guildId), eq(BANNED_USER_ID), eq(REASON), banLogModelCaptor.capture())).thenReturn(CompletableFuture.completedFuture(null)); + when(banService.banUserViaId(eq(guildId), eq(BANNED_USER_ID), eq(REASON), banLogModelCaptor.capture())).thenReturn(CompletableFuture.completedFuture(null)); CompletableFuture result = testUnit.executeAsync(parameters); BanIdLog usedModel = banLogModelCaptor.getValue(); Assert.assertEquals(REASON, usedModel.getReason()); @@ -60,7 +60,7 @@ public class BanIdTest { Long guildId = parameters.getUserInitiatedContext().getServer().getId(); when(parameters.getGuild().getIdLong()).thenReturn(guildId); when(templateService.renderSimpleTemplate(Ban.BAN_DEFAULT_REASON_TEMPLATE)).thenReturn(REASON); - when(banService.banMember(eq(guildId), eq(BANNED_USER_ID), eq(customReason), banLogModelCaptor.capture())).thenReturn(CompletableFuture.completedFuture(null)); + when(banService.banUserViaId(eq(guildId), eq(BANNED_USER_ID), eq(customReason), banLogModelCaptor.capture())).thenReturn(CompletableFuture.completedFuture(null)); CompletableFuture result = testUnit.executeAsync(parameters); BanIdLog usedModel = banLogModelCaptor.getValue(); Assert.assertEquals(customReason, usedModel.getReason()); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarningsTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarningsTest.java index 67cc6793e..67fdd3004 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarningsTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/commands/DecayAllWarningsTest.java @@ -1,6 +1,5 @@ package dev.sheldan.abstracto.moderation.commands; -import dev.sheldan.abstracto.core.command.exception.IncorrectParameterTypeException; import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.moderation.service.WarnService; @@ -12,7 +11,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import java.util.Arrays; import java.util.concurrent.CompletableFuture; import static org.mockito.Mockito.*; @@ -27,13 +25,11 @@ public class DecayAllWarningsTest { private WarnService warnService; @Test - public void testDecayAllWarningsWithLog() { - executeTest(true); - } - - @Test - public void testDecayAllWarningsWithoutLog() { - executeTest(false); + public void testDecayAllWarnings() { + CommandContext commandContext = CommandTestUtilities.getNoParameters(); + when(warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer())).thenReturn(CompletableFuture.completedFuture(null)); + CompletableFuture result = testUnit.executeAsync(commandContext); + CommandTestUtilities.checkSuccessfulCompletionAsync(result); } @Test @@ -41,15 +37,4 @@ public class DecayAllWarningsTest { CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration()); } - @Test(expected = IncorrectParameterTypeException.class) - public void testIncorrectParameterType() { - CommandTestUtilities.executeWrongParametersTestAsync(testUnit); - } - - private void executeTest(Boolean logWarnings) { - CommandContext commandContext = CommandTestUtilities.getWithParameters(Arrays.asList(logWarnings)); - when(warnService.decayAllWarningsForServer(commandContext.getUserInitiatedContext().getServer(), logWarnings)).thenReturn(CompletableFuture.completedFuture(null)); - CompletableFuture result = testUnit.executeAsync(commandContext); - CommandTestUtilities.checkSuccessfulCompletionAsync(result); - } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/BanServiceBeanTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/BanServiceBeanTest.java index e4e01c055..e3d873714 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/BanServiceBeanTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/BanServiceBeanTest.java @@ -3,7 +3,10 @@ package dev.sheldan.abstracto.moderation.service; import dev.sheldan.abstracto.core.exception.GuildNotFoundException; import dev.sheldan.abstracto.core.models.context.ServerContext; import dev.sheldan.abstracto.core.service.BotService; +import dev.sheldan.abstracto.core.service.FeatureModeService; import dev.sheldan.abstracto.core.service.PostTargetService; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.ModerationMode; import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget; import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.templating.service.TemplateService; @@ -38,8 +41,32 @@ public class BanServiceBeanTest { @Mock private PostTargetService postTargetService; + @Mock + private FeatureModeService featureModeService; + @Test - public void testBanMemberByMember() { + public void testBanMemberByMemberWithoutLog() { + Long userId = 8L; + Long serverId = 9L; + Member memberToBan = Mockito.mock(Member.class); + when(memberToBan.getIdLong()).thenReturn(userId); + ServerContext context = Mockito.mock(ServerContext.class); + Guild mockedGuild = Mockito.mock(Guild.class); + when(memberToBan.getGuild()).thenReturn(mockedGuild); + when(mockedGuild.getIdLong()).thenReturn(serverId); + AuditableRestAction mockedAction = mock(AuditableRestAction.class); + when(mockedAction.submit()).thenReturn(CompletableFuture.completedFuture(null)); + when(mockedGuild.ban(userId.toString(), 0, REASON)).thenReturn(mockedAction); + MessageToSend mockedMessage = Mockito.mock(MessageToSend.class); + when(featureModeService.featureModeActive(ModerationFeatures.MODERATION, serverId, ModerationMode.BAN_LOG)).thenReturn(false); + testUnit.banMember(memberToBan, REASON, context); + verify(mockedGuild, times(1)).ban(userId.toString(), 0, REASON); + verify(postTargetService, times(0)).sendEmbedInPostTarget(mockedMessage, ModerationPostTarget.BAN_LOG, serverId); + verify(templateService, times(0)).renderEmbedTemplate(BanServiceBean.BAN_LOG_TEMPLATE, context); + } + + @Test + public void testBanMemberWithLog() { Long userId = 8L; Long serverId = 9L; Member memberToBan = Mockito.mock(Member.class); @@ -53,6 +80,7 @@ public class BanServiceBeanTest { when(mockedGuild.ban(userId.toString(), 0, REASON)).thenReturn(mockedAction); MessageToSend mockedMessage = Mockito.mock(MessageToSend.class); when(templateService.renderEmbedTemplate(BanServiceBean.BAN_LOG_TEMPLATE, context)).thenReturn(mockedMessage); + when(featureModeService.featureModeActive(ModerationFeatures.MODERATION, serverId, ModerationMode.BAN_LOG)).thenReturn(true); testUnit.banMember(memberToBan, REASON, context); verify(mockedGuild, times(1)).ban(userId.toString(), 0, REASON); verify(postTargetService, times(1)).sendEmbedInPostTarget(mockedMessage, ModerationPostTarget.BAN_LOG, serverId); @@ -70,8 +98,9 @@ public class BanServiceBeanTest { when(mockedGuild.ban(userId.toString(), 0, REASON)).thenReturn(mockedAction); MessageToSend mockedMessage = Mockito.mock(MessageToSend.class); when(templateService.renderEmbedTemplate(BanServiceBean.BAN_ID_LOG_TEMPLATE, context)).thenReturn(mockedMessage); + when(featureModeService.featureModeActive(ModerationFeatures.MODERATION, serverId, ModerationMode.BAN_LOG)).thenReturn(true); when(botService.getGuildByIdOptional(serverId)).thenReturn(Optional.of(mockedGuild)); - testUnit.banMember(serverId, userId, REASON, context); + testUnit.banUserViaId(serverId, userId, REASON, context); verify(mockedGuild, times(1)).ban(userId.toString(), 0, REASON); verify(postTargetService, times(1)).sendEmbedInPostTarget(mockedMessage, ModerationPostTarget.BAN_LOG, serverId); } @@ -82,7 +111,7 @@ public class BanServiceBeanTest { Long serverId = 5L; ServerContext context = Mockito.mock(ServerContext.class); when(botService.getGuildByIdOptional(serverId)).thenReturn(Optional.empty()); - testUnit.banMember(serverId, userId, REASON, context); + testUnit.banUserViaId(serverId, userId, REASON, context); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/KickServiceBeanTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/KickServiceBeanTest.java index 6f7ad4d0b..8e4ff53da 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/KickServiceBeanTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/KickServiceBeanTest.java @@ -1,13 +1,15 @@ package dev.sheldan.abstracto.moderation.service; import dev.sheldan.abstracto.core.models.database.AServer; +import dev.sheldan.abstracto.core.service.FeatureModeService; import dev.sheldan.abstracto.core.service.PostTargetService; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.ModerationMode; import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget; import dev.sheldan.abstracto.moderation.models.template.commands.KickLogModel; import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.templating.service.TemplateService; import dev.sheldan.abstracto.core.test.MockUtils; -import dev.sheldan.abstracto.core.test.command.CommandTestUtilities; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.User; @@ -35,8 +37,33 @@ public class KickServiceBeanTest { @Mock private PostTargetService postTargetService; + @Mock + private FeatureModeService featureModeService; + @Test - public void testKickMember() { + public void testKickMemberWithoutLog() { + AServer server = MockUtils.getServer(); + User user = Mockito.mock(User.class); + Member member = Mockito.mock(Member.class); + when(member.getUser()).thenReturn(user); + when(user.getIdLong()).thenReturn(6L); + Guild mockedGuild = Mockito.mock(Guild.class); + when(mockedGuild.getIdLong()).thenReturn(server.getId()); + when(member.getGuild()).thenReturn(mockedGuild); + String reason = "reason"; + AuditableRestAction mockedAction = Mockito.mock(AuditableRestAction.class); + when(mockedGuild.kick(member, reason)).thenReturn(mockedAction); + when(mockedAction.submit()).thenReturn(CompletableFuture.completedFuture(null)); + KickLogModel model = Mockito.mock(KickLogModel.class); + when(model.getGuild()).thenReturn(mockedGuild); + when(featureModeService.featureModeActive(ModerationFeatures.MODERATION, server.getId(), ModerationMode.KICK_LOG)).thenReturn(false); + testUnit.kickMember(member, reason, model); + verify(postTargetService, times(0)).sendEmbedInPostTarget(any(MessageToSend.class), eq(ModerationPostTarget.KICK_LOG), eq(server.getId())); + verify(templateService, times(0)).renderEmbedTemplate(KickServiceBean.KICK_LOG_TEMPLATE, model); + } + + @Test + public void testKickMemberWithLog() { AServer server = MockUtils.getServer(); User user = Mockito.mock(User.class); Member member = Mockito.mock(Member.class); @@ -53,7 +80,8 @@ public class KickServiceBeanTest { when(model.getGuild()).thenReturn(mockedGuild); MessageToSend messageToSend = Mockito.mock(MessageToSend.class); when(templateService.renderEmbedTemplate(KickServiceBean.KICK_LOG_TEMPLATE, model)).thenReturn(messageToSend); - when(postTargetService.sendEmbedInPostTarget(messageToSend, ModerationPostTarget.KICK_LOG, server.getId())).thenReturn(CommandTestUtilities.messageFutureList()); + when(featureModeService.featureModeActive(ModerationFeatures.MODERATION, server.getId(), ModerationMode.KICK_LOG)).thenReturn(true); testUnit.kickMember(member, reason, model); + verify(postTargetService, times(1)).sendEmbedInPostTarget(messageToSend, ModerationPostTarget.KICK_LOG, server.getId()); } } \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/MuteServiceBeanTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/MuteServiceBeanTest.java index 0c6e647ff..bfcb4eb77 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/MuteServiceBeanTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/MuteServiceBeanTest.java @@ -11,6 +11,8 @@ import dev.sheldan.abstracto.core.service.*; import dev.sheldan.abstracto.core.service.management.ChannelManagementService; import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.MutingMode; import dev.sheldan.abstracto.moderation.config.posttargets.MutingPostTarget; import dev.sheldan.abstracto.moderation.exception.MuteRoleNotSetupException; import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException; @@ -18,7 +20,6 @@ import dev.sheldan.abstracto.moderation.models.database.Mute; import dev.sheldan.abstracto.moderation.models.database.MuteRole; import dev.sheldan.abstracto.moderation.models.template.commands.MuteContext; import dev.sheldan.abstracto.moderation.models.template.commands.MuteNotification; -import dev.sheldan.abstracto.moderation.models.template.commands.UnMuteLog; import dev.sheldan.abstracto.moderation.service.management.MuteManagementService; import dev.sheldan.abstracto.moderation.service.management.MuteRoleManagementService; import dev.sheldan.abstracto.scheduling.service.SchedulerService; @@ -42,7 +43,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledExecutorService; import static dev.sheldan.abstracto.moderation.service.MuteServiceBean.MUTE_NOTIFICATION_TEMPLATE; -import static dev.sheldan.abstracto.moderation.service.MuteServiceBean.UN_MUTE_LOG_TEMPLATE; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) @@ -134,6 +134,9 @@ public class MuteServiceBeanTest { @Mock private CounterService counterService; + @Mock + private FeatureModeService featureModeService; + private static final Long CHANNEL_ID = 8L; private static final String REASON = "reason"; private static final String NOTIFICATION_TEXT = "text"; @@ -251,6 +254,8 @@ public class MuteServiceBeanTest { when(muteLog.getMutingUser()).thenReturn(memberMuting); when(muteLog.getContext()).thenReturn(serverChannelMessage); when(muteLog.getMuteTargetDate()).thenReturn(unMuteDate); + when(serverManagementService.loadOrCreate(SERVER_ID)).thenReturn(server); + when(featureModeService.featureModeActive(ModerationFeatures.MUTING, server, MutingMode.MUTE_LOGGING)).thenReturn(true); String notificationText = "text"; when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class))).thenReturn(notificationText); when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null)); @@ -262,10 +267,39 @@ public class MuteServiceBeanTest { verify(postTargetService, times(1)).sendEmbedInPostTarget(messageToSend, MutingPostTarget.MUTE_LOG, SERVER_ID); } + @Test + public void testMuteMemberWithoutLog() { + when(userInServerManagementService.loadUser(memberBeingMuted)).thenReturn(userBeingMuted); + when(userInServerManagementService.loadUser(memberMuting)).thenReturn(userMuting); + Instant unMuteDate = shorterMute(); + when(memberBeingMuted.getGuild()).thenReturn(guild); + when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted); + when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(true); + when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole); + + ServerChannelMessage serverChannelMessage = Mockito.mock(ServerChannelMessage.class); + when(serverChannelMessage.getServerId()).thenReturn(SERVER_ID); + MuteContext muteLog = Mockito.mock(MuteContext.class); + when(muteLog.getMutedUser()).thenReturn(memberBeingMuted); + when(muteLog.getMutingUser()).thenReturn(memberMuting); + when(muteLog.getContext()).thenReturn(serverChannelMessage); + when(muteLog.getMuteTargetDate()).thenReturn(unMuteDate); + when(serverManagementService.loadOrCreate(SERVER_ID)).thenReturn(server); + when(featureModeService.featureModeActive(ModerationFeatures.MUTING, server, MutingMode.MUTE_LOGGING)).thenReturn(false); + String notificationText = "text"; + when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class))).thenReturn(notificationText); + when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null)); + when(roleService.addRoleToUserFuture(userBeingMuted, muteRole.getRole())).thenReturn(CompletableFuture.completedFuture(null)); + testUnit.muteMemberWithLog(muteLog); + verifyDirectMute(); + verify(postTargetService, times(0)).sendEmbedInPostTarget(messageToSend, MutingPostTarget.MUTE_LOG, SERVER_ID); + } + @Test public void testUnMuteMemberWhoseMuteEnded() { when(mute.getMuteEnded()).thenReturn(true); when(mute.getMutedUser()).thenReturn(userBeingMuted); + when(muteManagementService.hasActiveMute(userBeingMuted)).thenReturn(true); when(muteManagementService.getAMuteOf(userBeingMuted)).thenReturn(mute); when(mute.getMuteId()).thenReturn(new ServerSpecificId(SERVER_ID, MUTE_ID)); testUnit.unMuteUser(userBeingMuted); @@ -291,8 +325,6 @@ public class MuteServiceBeanTest { when(guild.getIdLong()).thenReturn(SERVER_ID); when(muteManagementService.findMute(MUTE_ID, SERVER_ID)).thenReturn(mute); when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server); - when(templateService.renderEmbedTemplate(eq(UN_MUTE_LOG_TEMPLATE), any(UnMuteLog.class))).thenReturn(messageToSend); - when(postTargetService.sendEmbedInPostTarget(eq(messageToSend), eq(MutingPostTarget.MUTE_LOG), anyLong())).thenReturn(Arrays.asList(CompletableFuture.completedFuture(null))); testUnit.sendUnmuteLog(MUTE_ID, guild, CompletableFuture.completedFuture(memberMuting), CompletableFuture.completedFuture(memberBeingMuted)); verify(self, times(1)).endMuteInDatabase(MUTE_ID, SERVER_ID); } @@ -383,6 +415,7 @@ public class MuteServiceBeanTest { private void setupUnMuteMocks(boolean stillInGuild) { when(mute.getMuteId()).thenReturn(new ServerSpecificId(SERVER_ID, MUTE_ID)); when(muteManagementService.getAMuteOf(userBeingMuted)).thenReturn(mute); + when(muteManagementService.hasActiveMute(userBeingMuted)).thenReturn(true); when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole); when(botService.getGuildById(server.getId())).thenReturn(guild); when(botService.isUserInGuild(guild, userBeingMuted)).thenReturn(stillInGuild); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/WarnServiceBeanTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/WarnServiceBeanTest.java index 902364337..ee8748a59 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/WarnServiceBeanTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/service/WarnServiceBeanTest.java @@ -5,7 +5,10 @@ import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.service.*; import dev.sheldan.abstracto.core.service.management.ServerManagementService; +import dev.sheldan.abstracto.moderation.config.features.ModerationFeatures; +import dev.sheldan.abstracto.moderation.config.features.WarnDecayMode; import dev.sheldan.abstracto.moderation.config.features.WarningDecayFeature; +import dev.sheldan.abstracto.moderation.config.features.WarningMode; import dev.sheldan.abstracto.moderation.config.posttargets.WarnDecayPostTarget; import dev.sheldan.abstracto.moderation.config.posttargets.WarningPostTarget; import dev.sheldan.abstracto.moderation.models.database.Warning; @@ -114,6 +117,9 @@ public class WarnServiceBeanTest { @Mock private MessageService messageService; + @Mock + private FeatureModeService featureModeService; + private static final String NOTIFICATION_TEXT = "text"; private static final String GUILD_NAME = "guild"; private static final Long SERVER_ID = 4L; @@ -130,36 +136,60 @@ public class WarnServiceBeanTest { @Test public void testDecayWarningsForServer() { setupWarnDecay(); + when(featureModeService.featureModeActive(ModerationFeatures.AUTOMATIC_WARN_DECAY, server, WarnDecayMode.AUTOMATIC_WARN_DECAY_LOG)).thenReturn(true); testUnit.decayWarningsForServer(server); verify(self, times(1)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); } @Test - public void testDecayAllWarningsForServerWithLog() { + public void testDecayWarningsForServerWithoutLog() { setupWarnDecay(); - testUnit.decayAllWarningsForServer(server, true); + when(featureModeService.featureModeActive(ModerationFeatures.AUTOMATIC_WARN_DECAY, server, WarnDecayMode.AUTOMATIC_WARN_DECAY_LOG)).thenReturn(false); + testUnit.decayWarningsForServer(server); + verify(self, times(0)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); + } + + @Test + public void testDecayAllWarningsForServer() { + setupWarnDecay(); + when(featureModeService.featureModeActive(ModerationFeatures.WARNING, server, WarningMode.WARN_DECAY_LOG)).thenReturn(true); + testUnit.decayAllWarningsForServer(server); verify(self, times(1)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); } @Test public void testDecayAllWarningsForServerWithoutLog() { setupWarnDecay(); - testUnit.decayAllWarningsForServer(server, false); - verifyWarnDecayWithLog(false); + when(featureModeService.featureModeActive(ModerationFeatures.WARNING, server, WarningMode.WARN_DECAY_LOG)).thenReturn(false); + testUnit.decayAllWarningsForServer(server); + verify(self, times(0)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); } + @Test - public void testDecayAllWarningsWithoutWarnings() { + public void testDecayAllWarningsWithoutWarningsWithoutLog() { List warnings = Collections.emptyList(); when(server.getId()).thenReturn(SERVER_ID); when(warnManagementService.getActiveWarningsInServerOlderThan(eq(server), any(Instant.class))).thenReturn(warnings); - testUnit.decayAllWarningsForServer(server, true); + when(featureModeService.featureModeActive(ModerationFeatures.WARNING, server, WarningMode.WARN_DECAY_LOG)).thenReturn(false); + testUnit.decayAllWarningsForServer(server); + verify(self, times(0)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); + } + + @Test + public void testDecayAllWarningsWithoutWarningsWithLog() { + List warnings = Collections.emptyList(); + when(server.getId()).thenReturn(SERVER_ID); + when(warnManagementService.getActiveWarningsInServerOlderThan(eq(server), any(Instant.class))).thenReturn(warnings); + when(featureModeService.featureModeActive(ModerationFeatures.WARNING, server, WarningMode.WARN_DECAY_LOG)).thenReturn(true); + testUnit.decayAllWarningsForServer(server); verify(self, times(1)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any()); } @Test public void testWarnFullUser() { setupWarnContext(); + when(featureModeService.featureModeActive(ModerationFeatures.WARNING, SERVER_ID, WarningMode.WARN_LOG)).thenReturn(true); setupMocksForWarning(); testUnit.notifyAndLogFullUserWarning(context); } @@ -197,22 +227,6 @@ public class WarnServiceBeanTest { when(server.getId()).thenReturn(SERVER_ID); } - private void verifyWarnDecayWithLog(boolean withLog) { - int logCount = withLog ? 1 : 0; - verify(postTargetService, times(logCount)).sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId()); - if(withLog) { - WarnDecayLogModel model = warnDecayLogModelArgumentCaptor.getValue(); - List usedWarnings = model.getWarnings(); - Assert.assertEquals(firstWarning, usedWarnings.get(0).getWarning()); - Assert.assertEquals(warnedMember, usedWarnings.get(0).getWarnedMember()); - Assert.assertEquals(warningMember, usedWarnings.get(0).getWarningMember()); - Assert.assertEquals(secondWarning, usedWarnings.get(1).getWarning()); - Assert.assertEquals(secondWarnedMember, usedWarnings.get(1).getWarnedMember()); - Assert.assertEquals(warningMember, usedWarnings.get(1).getWarningMember()); - Assert.assertEquals(2, usedWarnings.size()); - } - } - private void setupWarnDecay() { setupWarnings(); when(configService.getLongValue(WarningDecayFeature.DECAY_DAYS_KEY, server.getId())).thenReturn(5L); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeature.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeature.java index 887f457b5..ebee5f76d 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeature.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeature.java @@ -2,6 +2,7 @@ package dev.sheldan.abstracto.moderation.config.features; import dev.sheldan.abstracto.core.config.FeatureEnum; import dev.sheldan.abstracto.core.config.FeatureConfig; +import dev.sheldan.abstracto.core.config.FeatureMode; import dev.sheldan.abstracto.core.config.PostTargetEnum; import dev.sheldan.abstracto.moderation.config.posttargets.ModerationPostTarget; import org.springframework.stereotype.Component; @@ -21,4 +22,9 @@ public class ModerationFeature implements FeatureConfig { public List getRequiredPostTargets() { return Arrays.asList(ModerationPostTarget.BAN_LOG, ModerationPostTarget.KICK_LOG); } + + @Override + public List getAvailableModes() { + return Arrays.asList(ModerationMode.BAN_LOG, ModerationMode.KICK_LOG); + } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeatures.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeatures.java index 012742ada..aef4b7c41 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeatures.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationFeatures.java @@ -7,7 +7,7 @@ import lombok.Getter; public enum ModerationFeatures implements FeatureEnum { MODERATION("moderation"), WARNING("warnings"), LOGGING("logging"), MUTING("muting"), AUTOMATIC_WARN_DECAY("warnDecay"), USER_NOTES("userNotes"); - private String key; + private final String key; ModerationFeatures(String key) { this.key = key; diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationMode.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationMode.java new file mode 100644 index 000000000..cfcbbbad4 --- /dev/null +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/ModerationMode.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.moderation.config.features; + +import dev.sheldan.abstracto.core.config.FeatureMode; +import lombok.Getter; + +@Getter +public enum ModerationMode implements FeatureMode { + BAN_LOG("banLogging"), KICK_LOG("kickLogging"); + + private final String key; + + ModerationMode(String key) { + this.key = key; + } + +} diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingFeature.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingFeature.java index 98f8907c6..955c6c82d 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingFeature.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingFeature.java @@ -2,6 +2,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.FeatureMode; import dev.sheldan.abstracto.core.config.PostTargetEnum; import dev.sheldan.abstracto.moderation.config.posttargets.MutingPostTarget; import org.springframework.stereotype.Component; @@ -21,4 +22,9 @@ public class MutingFeature implements FeatureConfig { public List getRequiredPostTargets() { return Arrays.asList(MutingPostTarget.MUTE_LOG); } + + @Override + public List getAvailableModes() { + return Arrays.asList(MutingMode.MANUAL_UN_MUTE_LOGGING, MutingMode.MUTE_LOGGING, MutingMode.UN_MUTE_LOGGING); + } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingMode.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingMode.java new file mode 100644 index 000000000..46bccb114 --- /dev/null +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/MutingMode.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.moderation.config.features; + +import dev.sheldan.abstracto.core.config.FeatureMode; +import lombok.Getter; + +@Getter +public enum MutingMode implements FeatureMode { + MUTE_LOGGING("muteLogging"), UN_MUTE_LOGGING("unMuteLogging"), MANUAL_UN_MUTE_LOGGING("manualUnMuteLogging"); + + private final String key; + + MutingMode(String key) { + this.key = key; + } + +} diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarnDecayMode.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarnDecayMode.java new file mode 100644 index 000000000..af45afbc4 --- /dev/null +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarnDecayMode.java @@ -0,0 +1,17 @@ +package dev.sheldan.abstracto.moderation.config.features; + + +import dev.sheldan.abstracto.core.config.FeatureMode; +import lombok.Getter; + +@Getter +public enum WarnDecayMode implements FeatureMode { + AUTOMATIC_WARN_DECAY_LOG("automaticWarnDecayLogging"); + + private final String key; + + WarnDecayMode(String key) { + this.key = key; + } + +} \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningDecayFeature.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningDecayFeature.java index 0be69bb06..0339dbf59 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningDecayFeature.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningDecayFeature.java @@ -2,6 +2,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.FeatureMode; import dev.sheldan.abstracto.core.config.PostTargetEnum; import dev.sheldan.abstracto.moderation.config.posttargets.WarnDecayPostTarget; import org.springframework.beans.factory.annotation.Autowired; @@ -38,4 +39,8 @@ public class WarningDecayFeature implements FeatureConfig { return Arrays.asList(WarnDecayPostTarget.DECAY_LOG); } + @Override + public List getAvailableModes() { + return Arrays.asList(WarnDecayMode.AUTOMATIC_WARN_DECAY_LOG); + } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningFeature.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningFeature.java index f12718600..f7041ae59 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningFeature.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningFeature.java @@ -2,6 +2,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.FeatureMode; import dev.sheldan.abstracto.core.config.PostTargetEnum; import dev.sheldan.abstracto.moderation.config.posttargets.WarningPostTarget; import org.springframework.beans.factory.annotation.Autowired; @@ -30,4 +31,9 @@ public class WarningFeature implements FeatureConfig { public List getRequiredPostTargets() { return Arrays.asList(WarningPostTarget.WARN_LOG); } + + @Override + public List getAvailableModes() { + return Arrays.asList(WarningMode.WARN_DECAY_LOG, WarningMode.WARN_LOG); + } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningMode.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningMode.java new file mode 100644 index 000000000..02d2ed3cf --- /dev/null +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/config/features/WarningMode.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.moderation.config.features; + +import dev.sheldan.abstracto.core.config.FeatureMode; +import lombok.Getter; + +@Getter +public enum WarningMode implements FeatureMode { + WARN_LOG("warnLogging"), WARN_DECAY_LOG("warnDecayLogging"); + + private final String key; + + WarningMode(String key) { + this.key = key; + } + +} \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/BanService.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/BanService.java index e1751a63f..7266ef4c4 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/BanService.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/BanService.java @@ -7,5 +7,5 @@ import java.util.concurrent.CompletableFuture; public interface BanService { CompletableFuture banMember(Member member, String reason, ServerContext banLog); - CompletableFuture banMember(Long guildId, Long userId, String reason, ServerContext banIdLog); + CompletableFuture banUserViaId(Long guildId, Long userId, String reason, ServerContext banIdLog); } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/WarnService.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/WarnService.java index 908c2e307..e1ff965e8 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/WarnService.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/service/WarnService.java @@ -13,5 +13,5 @@ public interface WarnService { CompletableFuture warnUserWithLog(WarnContext context); void decayWarning(Warning warning, Instant decayDate); CompletableFuture decayWarningsForServer(AServer server); - CompletableFuture decayAllWarningsForServer(AServer server, boolean logWarnings); + CompletableFuture decayAllWarningsForServer(AServer server); } diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/InvalidCategoryException.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/InvalidCategoryException.java index 3f8519448..b2b994599 100644 --- a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/InvalidCategoryException.java +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/InvalidCategoryException.java @@ -14,7 +14,7 @@ public class InvalidCategoryException extends AbstractoRunTimeException implemen @Override public String getTemplateName() { - return "setup_category_not_valid_exception"; + return "feature_setup_category_not_valid_exception"; } @Override diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategoryDelayedActionConfig.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategoryDelayedActionConfig.java index 0557360e3..034337ba1 100644 --- a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategoryDelayedActionConfig.java +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategoryDelayedActionConfig.java @@ -23,7 +23,7 @@ public class ModMailCategoryDelayedActionConfig implements DelayedActionConfig { @Override public String getTemplateName() { - return "setup_modmail_category_action"; + return "feature_setup_modmail_category_action"; } @Override diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategorySetupBean.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategorySetupBean.java index f06aeaa53..25a6c458b 100644 --- a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategorySetupBean.java +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/setup/ModMailCategorySetupBean.java @@ -73,7 +73,7 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup { */ @Override public CompletableFuture execute(AServerChannelUserId user, SetupStepParameter parameter) { - String messageTemplateKey = "setup_modmail_category_message"; + String messageTemplateKey = "feature_setup_modmail_category_message"; SetupModMailCategoryMessageModel model = SetupModMailCategoryMessageModel .builder() .build(); diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailMode.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailMode.java index 986897575..0c22424f9 100644 --- a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailMode.java +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailMode.java @@ -11,7 +11,7 @@ import lombok.Getter; public enum ModMailMode implements FeatureMode { LOGGING("log"); - private String key; + private final String key; ModMailMode(String key) { this.key = key; diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailCategoryValidationErrorModel.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailCategoryValidationErrorModel.java index 805be9a35..6e3dfd8ea 100644 --- a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailCategoryValidationErrorModel.java +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailCategoryValidationErrorModel.java @@ -18,7 +18,7 @@ public class ModMailCategoryValidationErrorModel implements ValidationErrorModel @Override public String getTemplateName() { - return "setup_modmail_category_not_setup"; + return "feature_setup_modmail_category_not_setup"; } @Override diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/Setup.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetupFeature.java similarity index 90% rename from abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/Setup.java rename to abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetupFeature.java index 42f8dd269..15cc9de64 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/Setup.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetupFeature.java @@ -14,7 +14,7 @@ import dev.sheldan.abstracto.core.exception.FeatureNotFoundException; 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 dev.sheldan.abstracto.core.service.FeatureSetupService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -23,7 +23,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; @Component -public class Setup extends AbstractConditionableCommand { +public class SetupFeature extends AbstractConditionableCommand { @Autowired private InteractiveService interactiveService; @@ -35,7 +35,7 @@ public class Setup extends AbstractConditionableCommand { private FeatureConfigService featureConfigService; @Autowired - private SetupService setupService; + private FeatureSetupService setupService; @Override public CompletableFuture executeAsync(CommandContext commandContext) { @@ -48,7 +48,7 @@ public class Setup extends AbstractConditionableCommand { .channelId(commandContext.getChannel().getIdLong()) .userId(commandContext.getAuthor().getIdLong()) .build(); - return setupService.performSetup(feature, initiatingUser, commandContext.getMessage().getIdLong()) + return setupService.performFeatureSetup(feature, initiatingUser, commandContext.getMessage().getIdLong()) .thenApply(aVoid -> CommandResult.fromSuccess()); } throw new FeatureNotFoundException(name, featureConfigService.getFeaturesAsList()); @@ -60,7 +60,7 @@ public class Setup extends AbstractConditionableCommand { List parameters = Arrays.asList(newPrefixParameter); HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); return CommandConfiguration.builder() - .name("setup") + .name("setupFeature") .module(ConfigModuleInterface.CONFIG) .parameters(parameters) .templated(true) diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Disable.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeature.java similarity index 97% rename from abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Disable.java rename to abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeature.java index e1491cbf3..7cadb82b6 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Disable.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeature.java @@ -25,7 +25,7 @@ import java.util.List; import java.util.concurrent.CompletableFuture; @Component -public class Disable extends AbstractConditionableCommand { +public class DisableFeature extends AbstractConditionableCommand { @Autowired private FeatureConfigService featureConfigService; @@ -67,7 +67,7 @@ public class Disable extends AbstractConditionableCommand { List parameters = Arrays.asList(featureName); HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build(); return CommandConfiguration.builder() - .name("disable") + .name("disableFeature") .module(ConfigModuleInterface.CONFIG) .parameters(parameters) .async(true) diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Enable.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeature.java similarity index 97% rename from abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Enable.java rename to abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeature.java index 8b9fa08b5..cb0b301d0 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/Enable.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeature.java @@ -28,7 +28,7 @@ import java.util.concurrent.CompletableFuture; @Component @Slf4j -public class Enable extends AbstractConditionableCommand { +public class EnableFeature extends AbstractConditionableCommand { @Autowired private FeatureConfigService featureConfigService; @@ -75,7 +75,7 @@ public class Enable extends AbstractConditionableCommand { List parameters = Arrays.asList(featureName); HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build(); return CommandConfiguration.builder() - .name("enable") + .name("enableFeature") .module(ConfigModuleInterface.CONFIG) .parameters(parameters) .async(true) diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/NoChannelProvidedException.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/NoChannelProvidedException.java index d813222b1..26f2711be 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/NoChannelProvidedException.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/NoChannelProvidedException.java @@ -10,7 +10,7 @@ public class NoChannelProvidedException extends AbstractoRunTimeException implem @Override public String getTemplateName() { - return "setup_no_channel_provided_exception"; + return "feature_setup_no_channel_provided_exception"; } @Override diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetDelayedActionConfig.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetDelayedActionConfig.java index b4b61b06a..9265883fa 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetDelayedActionConfig.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetDelayedActionConfig.java @@ -18,7 +18,7 @@ public class PostTargetDelayedActionConfig implements DelayedActionConfig { @Override public String getTemplateName() { - return "setup_post_target_action"; + return "feature_setup_post_target_action"; } @Override diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetSetupStep.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetSetupStep.java index 38b474e41..e7897b10c 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetSetupStep.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/PostTargetSetupStep.java @@ -27,6 +27,7 @@ import java.util.function.Consumer; @Slf4j public class PostTargetSetupStep extends AbstractConfigSetupStep { + public static final String FEATURE_SETUP_POST_TARGET_MESSAGE_TEMPLATE_KEY = "feature_setup_post_target_message"; @Autowired private ConfigService configService; @@ -66,8 +67,7 @@ public class PostTargetSetupStep extends AbstractConfigSetupStep { .postTargetKey(postTargetStepParameter.getPostTargetKey()) .currentTextChannel(currentTextChannel) .build(); - String messageTemplateKey = "setup_post_target_message"; - String messageText = templateService.renderTemplate(messageTemplateKey, model); + String messageText = templateService.renderTemplate(FEATURE_SETUP_POST_TARGET_MESSAGE_TEMPLATE_KEY, model); AChannel channel = channelManagementService.loadChannel(user.getChannelId()); CompletableFuture future = new CompletableFuture<>(); AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId()); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SetupSummaryStep.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SetupSummaryStep.java index c23373094..6c70255e0 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SetupSummaryStep.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SetupSummaryStep.java @@ -20,6 +20,7 @@ import java.util.function.Consumer; @Slf4j public class SetupSummaryStep extends AbstractConfigSetupStep { + public static final String FEATURE_SETUP_CONFIRMATION_TEMPLATE_KEY = "feature_setup_confirmation"; @Autowired private InteractiveService interactiveService; @@ -45,7 +46,7 @@ public class SetupSummaryStep extends AbstractConfigSetupStep { .builder() .actionConfigs(parameter.getDelayedActionList()) .build(); - String messageToSend = templateService.renderTemplate("setup_confirmation", model); + String messageToSend = templateService.renderTemplate(FEATURE_SETUP_CONFIRMATION_TEMPLATE_KEY, model); AChannel channel = channelManagementService.loadChannel(user.getChannelId()); CompletableFuture future = new CompletableFuture<>(); AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId()); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigDelayedActionConfig.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigDelayedActionConfig.java index 9a44e2fdd..285a39b67 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigDelayedActionConfig.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigDelayedActionConfig.java @@ -16,7 +16,7 @@ public class SystemConfigDelayedActionConfig implements DelayedActionConfig { @Override public String getTemplateName() { - return "setup_system_config_action"; + return "feature_setup_system_config_action"; } @Override diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigSetupStep.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigSetupStep.java index 94ec4f6f3..eb1fff89d 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigSetupStep.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/interactive/SystemConfigSetupStep.java @@ -27,6 +27,7 @@ import java.util.function.Consumer; @Slf4j public class SystemConfigSetupStep extends AbstractConfigSetupStep { + public static final String SETUP_SYSTEM_CONFIG_MESSAGE_TEMPLATE_KEY = "feature_setup_system_config_message"; @Autowired private ConfigService configService; @@ -57,8 +58,7 @@ public class SystemConfigSetupStep extends AbstractConfigSetupStep { .configKey(systemConfigStepParameter.getConfigKey()) .defaultConfig(defaultConfig) .build(); - String messageTemplateKey = "setup_system_config_message"; - String messageText = templateService.renderTemplate(messageTemplateKey, model); + String messageText = templateService.renderTemplate(SETUP_SYSTEM_CONFIG_MESSAGE_TEMPLATE_KEY, model); AChannel channel = channelManagementService.loadChannel(user.getChannelId()); CompletableFuture future = new CompletableFuture<>(); AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId()); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeServiceBean.java index 349378724..933754867 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeServiceBean.java @@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.models.template.commands.FeatureModeDisplay; import dev.sheldan.abstracto.core.service.management.DefaultFeatureModeManagement; import dev.sheldan.abstracto.core.service.management.FeatureFlagManagementService; import dev.sheldan.abstracto.core.service.management.FeatureModeManagementService; +import dev.sheldan.abstracto.core.service.management.ServerManagementService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -38,6 +39,9 @@ public class FeatureModeServiceBean implements FeatureModeService { @Autowired private DefaultFeatureModeManagement defaultFeatureModeManagement; + @Autowired + private ServerManagementService serverManagementService; + @Override public void enableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode) { AFeature feature = featureManagementService.getFeature(featureEnum.getKey()); @@ -81,6 +85,12 @@ public class FeatureModeServiceBean implements FeatureModeService { } } + @Override + public boolean featureModeActive(FeatureEnum featureEnum, Long serverId, FeatureMode mode) { + AServer server = serverManagementService.loadServer(serverId); + return featureModeActive(featureEnum, server, mode); + } + @Override public FeatureMode getFeatureModeForKey(String key) { return getAllAvailableFeatureModes().stream().filter(mode -> mode.getKey().equalsIgnoreCase(key)).findAny().orElseThrow(() -> new FeatureModeNotFoundException(key, getFeatureModesAsStrings())); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/SetupServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupServiceBean.java similarity index 89% rename from abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/SetupServiceBean.java rename to abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupServiceBean.java index 3dddbd70a..d411f6dfb 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/SetupServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupServiceBean.java @@ -22,8 +22,11 @@ import java.util.concurrent.CompletableFuture; @Component @Slf4j -public class SetupServiceBean implements SetupService { +public class FeatureSetupServiceBean implements FeatureSetupService { + public static final String FEATURE_SETUP_CANCELLATION_NOTIFICATION_TEMPLATE = "feature_setup_cancellation_notification"; + public static final String FEATURE_SETUP_COMPLETION_NOTIFICATION_TEMPLATE = "feature_setup_completion_notification"; + public static final String FEATURE_SETUP_INITIAL_MESSAGE_TEMPLATE_KEY = "feature_setup_initial_message"; @Autowired private SystemConfigSetupStep systemConfigSetupStep; @@ -34,7 +37,7 @@ public class SetupServiceBean implements SetupService { private DelayedActionService delayedActionService; @Autowired - private SetupServiceBean self; + private FeatureSetupServiceBean self; @Autowired private SetupSummaryStep setupSummaryStep; @@ -52,7 +55,7 @@ public class SetupServiceBean implements SetupService { private ExceptionService exceptionService; @Override - public CompletableFuture performSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId) { + public CompletableFuture performFeatureSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId) { log.info("Performing setup of feature {} for user {} in channel {} in server {}.", featureConfig.getFeature().getKey(), user.getUserId(), user.getChannelId(), user.getGuildId()); Optional textChannelInGuild = channelService.getTextChannelInGuild(user.getGuildId(), user.getChannelId()); @@ -99,15 +102,15 @@ public class SetupServiceBean implements SetupService { .featureConfig(featureConfig) .build(); TextChannel textChannel = textChannelInGuild.get(); - String text = templateService.renderTemplate("setup_initial_message", setupInitialMessageModel); + String text = templateService.renderTemplate(FEATURE_SETUP_INITIAL_MESSAGE_TEMPLATE_KEY, setupInitialMessageModel); channelService.sendTextToChannel(text, textChannel); - return executeSetup(featureConfig, steps, user, new ArrayList<>()); + return executeFeatureSetup(featureConfig, steps, user, new ArrayList<>()); } throw new ChannelNotFoundException(user.getChannelId()); } @Override - public CompletableFuture executeSetup(FeatureConfig featureConfig, List steps, AServerChannelUserId user, List delayedActionConfigs) { + public CompletableFuture executeFeatureSetup(FeatureConfig featureConfig, List steps, AServerChannelUserId user, List delayedActionConfigs) { SetupExecution nextStep = steps.get(0); return executeStep(user, nextStep, delayedActionConfigs, featureConfig); } @@ -162,7 +165,7 @@ public class SetupServiceBean implements SetupService { public void notifyAboutCompletion(AServerChannelUserId aServerChannelUserId, FeatureConfig featureConfig) { log.trace("Notifying user {} in channel {} in server {} about completion of setup for feature {}.", aServerChannelUserId.getUserId(), aServerChannelUserId.getChannelId(), aServerChannelUserId.getGuildId(), featureConfig.getFeature().getKey()); - notifyUserWithTemplate(aServerChannelUserId, featureConfig, "setup_completion_notification"); + notifyUserWithTemplate(aServerChannelUserId, featureConfig, FEATURE_SETUP_COMPLETION_NOTIFICATION_TEMPLATE); } private void notifyUserWithTemplate(AServerChannelUserId aServerChannelUserId, FeatureConfig featureConfig, String templateName) { @@ -179,6 +182,6 @@ public class SetupServiceBean implements SetupService { public void notifyAboutCancellation(AServerChannelUserId aServerChannelUserId, FeatureConfig featureConfig) { log.trace("Notifying user {} in channel {} in server {} about cancellation of setup for feature {}.", aServerChannelUserId.getUserId(), aServerChannelUserId.getChannelId(), aServerChannelUserId.getGuildId(), featureConfig.getFeature().getKey()); - notifyUserWithTemplate(aServerChannelUserId, featureConfig, "setup_cancellation_notification"); + notifyUserWithTemplate(aServerChannelUserId, featureConfig, FEATURE_SETUP_CANCELLATION_NOTIFICATION_TEMPLATE); } } diff --git a/abstracto-application/core/core-impl/src/main/resources/migrations/1.0-core/core-seedData/command.xml b/abstracto-application/core/core-impl/src/main/resources/migrations/1.0-core/core-seedData/command.xml index c4d394bd9..6e3eab36c 100644 --- a/abstracto-application/core/core-impl/src/main/resources/migrations/1.0-core/core-seedData/command.xml +++ b/abstracto-application/core/core-impl/src/main/resources/migrations/1.0-core/core-seedData/command.xml @@ -110,7 +110,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -140,7 +140,7 @@ - + diff --git a/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableModeTest.java b/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeatureModeTest.java similarity index 98% rename from abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableModeTest.java rename to abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeatureModeTest.java index 16dfd03ed..1fb5496e9 100644 --- a/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableModeTest.java +++ b/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/DisableFeatureModeTest.java @@ -24,7 +24,7 @@ import java.util.Arrays; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) -public class DisableModeTest { +public class DisableFeatureModeTest { @InjectMocks private DisableMode testUnit; diff --git a/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableModeTest.java b/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeatureModeTest.java similarity index 99% rename from abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableModeTest.java rename to abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeatureModeTest.java index d2574800c..1a1bac107 100644 --- a/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableModeTest.java +++ b/abstracto-application/core/core-impl/src/test/java/dev/sheldan/abstracto/core/commands/config/features/EnableFeatureModeTest.java @@ -26,7 +26,7 @@ import static org.mockito.Mockito.when; @RunWith(MockitoJUnitRunner.class) -public class EnableModeTest { +public class EnableFeatureModeTest { @InjectMocks private EnableMode testUnit; diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/InteractiveUtils.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/InteractiveUtils.java index 905837fc2..6cf634474 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/InteractiveUtils.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/InteractiveUtils.java @@ -20,7 +20,7 @@ public class InteractiveUtils { @Transactional public void sendTimeoutMessage(Long serverId, Long channelId) { - String s = templateService.renderSimpleTemplate("setup_configuration_timeout"); + String s = templateService.renderSimpleTemplate("feature_setup_configuration_timeout"); Optional channelOptional = channelService.getTextChannelInGuild(serverId, channelId); channelOptional.ifPresent(channel -> channelService.sendTextToChannelNotAsync(s, channel)); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/SetupStepException.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/SetupStepException.java index 595c67699..f891d1cb1 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/SetupStepException.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/interactive/SetupStepException.java @@ -21,7 +21,7 @@ public class SetupStepException extends AbstractoRunTimeException implements Tem @Override public String getTemplateName() { - return "setup_step_exception"; + return "feature_setup_step_exception"; } @Override diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeService.java index 2ac44da16..262e3802a 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureModeService.java @@ -14,6 +14,7 @@ public interface FeatureModeService { void setFutureModeForFuture(FeatureEnum featureEnum, AServer server, FeatureMode mode, Boolean newValue); void disableFeatureModeForFeature(FeatureEnum featureEnum, AServer server, FeatureMode mode); boolean featureModeActive(FeatureEnum featureEnum, AServer server, FeatureMode mode); + boolean featureModeActive(FeatureEnum featureEnum, Long serverId, FeatureMode mode); FeatureMode getFeatureModeForKey(String key); List getAllAvailableFeatureModes(); List getEffectiveFeatureModes(AServer server); diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/SetupService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupService.java similarity index 51% rename from abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/SetupService.java rename to abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupService.java index 6b38f1548..a72577c14 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/SetupService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/FeatureSetupService.java @@ -8,7 +8,7 @@ import dev.sheldan.abstracto.core.models.AServerChannelUserId; import java.util.List; import java.util.concurrent.CompletableFuture; -public interface SetupService { - CompletableFuture performSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId); - CompletableFuture executeSetup(FeatureConfig featureConfig, List steps, AServerChannelUserId user, List delayedActionConfigs); +public interface FeatureSetupService { + CompletableFuture performFeatureSetup(FeatureConfig featureConfig, AServerChannelUserId user, Long initialMessageId); + CompletableFuture executeFeatureSetup(FeatureConfig featureConfig, List steps, AServerChannelUserId user, List delayedActionConfigs); } diff --git a/abstracto-application/documentation/src/main/docs/asciidoc/features/core.adoc b/abstracto-application/documentation/src/main/docs/asciidoc/features/core.adoc index 23903cc88..afb65f3f3 100644 --- a/abstracto-application/documentation/src/main/docs/asciidoc/features/core.adoc +++ b/abstracto-application/documentation/src/main/docs/asciidoc/features/core.adoc @@ -3,8 +3,8 @@ The core feature contains necessary commands in order for Abstracto to function and be configured. ==== Emotes -* reaction emote in case the command completed successfully `successReaction` -* reaction emote in case the command did not complete successfully `warnReaction` +* `successReaction` reaction emote in case the command completed successfully +* `warnReaction` reaction emote in case the command did not complete successfully ==== Commands Help:: @@ -43,13 +43,13 @@ Listing the features:: * Usage: `features` * Description: Lists the available features and whether or not they are enabled in this server. Enabling a feature:: -* Usage: `enable ` +* Usage: `enableFeature ` * Description: Enables the feature identified by `key` in this server. If the feature dependents on other features, they will be enabled as well. -* Example: `enable moderation` to enable the moderation feature +* Example: `enableFeature moderation` to enable the moderation feature Disabling a feature:: -* Usage: `disable ` +* Usage: `disableFeature ` * Description: Disables the feature identified by `key` in this server. If the feature is required for other features, they will be disabled as well. -* Example: `disable moderation` to disable the moderation feature +* Example: `disableFeature moderation` to disable the moderation feature Creating a channel group:: * Usage: `createChannelGroup ` * Description: Creates a new channel group identified by `key`. @@ -112,7 +112,7 @@ Listing all feature modes:: * usage `featureModes [feature]` * Description: Lists all of the currently available feature modes and the feature they are associated with. If `feature` is given, it only lists the feature modes of this feature. The output also includes whether or not the current mode is enabled and if this value comes from the default configuration. Setting up a feature with an interactive wizard:: -Usage: `setup ` +Usage: `setupFeature ` * Description: Starts an interactive wizard to configure the necessary properties and post targets of a feature. Also includes custom steps. Closes with a summary page to see all changes. diff --git a/abstracto-application/documentation/src/main/docs/asciidoc/features/moderation.adoc b/abstracto-application/documentation/src/main/docs/asciidoc/features/moderation.adoc index 34e0f3f44..7e6a91122 100644 --- a/abstracto-application/documentation/src/main/docs/asciidoc/features/moderation.adoc +++ b/abstracto-application/documentation/src/main/docs/asciidoc/features/moderation.adoc @@ -6,6 +6,10 @@ Feature key: `moderation` `banLog`:: target of the log message containing information about the ban for both `ban` and `banId`. Will still ban if not setup. `kickLog`:: target of the log message containing information about the kick. Will still kick if not setup. +==== Feature modes +`banLogging`:: if enabled, log bans to the post target `banLog`. Enabled by default. +`kickLogging`:: if enabled, log bans to the post target `kickLog`. Enabled by default. + ==== Commands Ban a member:: * Usage: `ban [reason]` @@ -42,8 +46,13 @@ This feature can be used to warn specific users if they did something not allowe Feature key: `warnings` ==== Post targets -`warnLog`:: target of the log message containing information about the warn. -`decayLog`:: Will be used when all the warnings are decayed by a command and logging has been selected. +`warnLog`:: target of the log message containing information about a created warn, only used if feature mode `warnLogging` is enabled. +`decayLog`:: will be used when all the warnings are decayed by `decayAllWarnings` and feature mode `warnDecayLogging` is enabled. + +==== Feature modes +`warnLogging`:: if enabled, each warn is logged to the post target `warnLog`. Enabled by default. +`automaticWarnDecayLogging`:: if enabled, warn decays by `decayAllWarnings` are logged to the post target `decayLog`. Enabled by default. + ==== Commands Warn a user:: @@ -59,9 +68,8 @@ Showing your warnings:: * Usage: `myWarnings` * Description: Displays the amount of warnings of the user executing on the server. This will show both active and total warnings. Decaying all warnings regardless of the date:: -* Usage: `decayAllWarnings [writeLog]` -* Description: This will cause all warnings of this server which are not decayed yet to be decayed instantly. If this command should log the decaying of the warnings -the `writeLog` parameter needs to be `true`. +* Usage: `decayAllWarnings` +* Description: This will cause all warnings of this server which are not decayed yet to be decayed instantly. Deleting a warning:: * Usage: `deleteWarning ` * Description: Deletes the warning identified by `warnId` completely from the database. @@ -79,6 +87,9 @@ Feature key: `warnDecay` ==== Post targets `decayLog`:: target of the log message containing the information in case a warning is decayed. +==== Feature modes +`automaticWarnDecayLogging`:: if enabled, automatic warn decays are logged to the `decayLog` post target. Enabled by default. + ==== Commands Decaying all warnings if necessary:: * Usage: `decayWarnings` @@ -95,6 +106,12 @@ Feature key `muting` ==== Post targets `muteLog`:: target of log message containing the information in case a member was muted and when the mute ended automatically. +==== Feature modes +`muteLogging`:: if enabled, each mute is to be logged to the post target `muteLog`. Enabled by default. +`unMuteLogging`:: if enabled, each un mute which happens 'naturally' (after the defined time period is over) will be logged to the `muteLog` post target. Enabled by default. +`manualUnMuteLogging`:: if enabled, each un mute which happens via the command `unmute` will be logged to the `muteLog` post target. Enabled by default. + + ==== Commands Muting a user:: * Usage: `mute [reason]` diff --git a/abstracto-application/documentation/src/main/docs/asciidoc/features/modmail.adoc b/abstracto-application/documentation/src/main/docs/asciidoc/features/modmail.adoc index 155e3c23a..edc80d4ff 100644 --- a/abstracto-application/documentation/src/main/docs/asciidoc/features/modmail.adoc +++ b/abstracto-application/documentation/src/main/docs/asciidoc/features/modmail.adoc @@ -26,11 +26,11 @@ Feature key: `modmail` `modmailLog`:: Will be used to log the interactions when a thread is closed. ==== Feature modes -`log`:: If this is enabled, the messages should be logged into the `modmailLog` post target when the thread is closed (by the respective commands). This is required for the command `closeNoLog` to be available. +`log`:: If this is enabled, the messages should be logged into the `modmailLog` post target when the thread is closed (by the respective commands). This is required for the command `closeNoLog` to be available. Enabled by default. ==== Emotes -* to indicate to the user that the message sent was processed `readReaction` +* `readReaction` to indicate to the user that the message sent was processed ==== Commands Opening a mod mail thread for a user:: diff --git a/abstracto-application/documentation/src/main/docs/asciidoc/features/utility.adoc b/abstracto-application/documentation/src/main/docs/asciidoc/features/utility.adoc index cc31519bf..1288024d5 100644 --- a/abstracto-application/documentation/src/main/docs/asciidoc/features/utility.adoc +++ b/abstracto-application/documentation/src/main/docs/asciidoc/features/utility.adoc @@ -29,16 +29,14 @@ When the poster of the message reacts to the message with a star, this is not co Feature key: `starboard` ==== Emotes -* to vote on posting something to starboard: `star` -* for the different level of starboard posts: -** Level 1: `star1` -** Level 2: `star2` -** Level 3: `star3` -** Level 4: `star4` -* as badges in the `starStats` command: -** First place: `starboardBadge1` -** Second place: `starboardBadge2` -** Third place: `starboardBadge3` +* `star` to vote on posting something to starboard +* `star1` for level 1 of starboard +* `star2` for level 2 of starboard +* `star3` for level 3 of starboard +* `star4` for level 4 of starboard +* `starboardBadge1` used as marker for first place in the command `starStats` +* `starboardBadge2` used as marker for first place in the command `starStats` +* `starboardBadge3` used as marker for first place in the command `starStats` ==== Relevant system configuration @@ -68,8 +66,8 @@ Feature key: `suggestion` `suggestions`:: the target of the messages containing the suggestions ==== Emotes -* for up-voting a suggestion: `suggestionYes` -* for down-voting a suggestion: `suggestionNo` +* `suggestionYes` for up-voting a suggestion +* `suggestionNo` for down-voting a suggestion ==== Commands Creating a suggestion:: @@ -110,7 +108,7 @@ Displaying information about server:: === Link embeds ==== Emotes -* to remove the embed of a link: `removeEmbed` +* `removeEmbed` to remove the embed of a link This feature enables the automatic embedding of messages containing a message link. If a message contains a link to a discord message this will create an embed containing the the message content. This supports image attachments, but not videos or files.