mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-24 06:30:34 +00:00
[AB-52] upgrading to alpha 12
adding anonymous reporting reworking message context commands refactoring interaction packages adding post execution handling for message context commands and modals reworking feature mode response fixing setup using component ids storing infraction parameters, for example mute duration, with every infraction adding infractions for more moderation actions creating general method to format a duration string adding infractions command reworking muting to use built-in functionality of discord enabling chunking of members removing manual unmuting feature mode adding ability to update infractions with a command implemented infraction listeners for ban and warn refactored infraction notifications storing log messages to the infraction for editing said log messages
This commit is contained in:
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
@@ -29,6 +30,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.moderation.model.BanResult.NOTIFICATION_FAILED;
|
||||
import static dev.sheldan.abstracto.moderation.service.BanService.BAN_EFFECT_KEY;
|
||||
|
||||
@Component
|
||||
@@ -69,10 +71,14 @@ public class Ban extends AbstractConditionableCommand {
|
||||
Member banningMember = commandContext.getAuthor();
|
||||
return banService.banUserWithNotification(user, reason, commandContext.getAuthor(), 0)
|
||||
.thenCompose(banResult -> {
|
||||
String errorNotification = templateService.renderSimpleTemplate(BAN_NOTIFICATION_NOT_POSSIBLE, guild.getIdLong());
|
||||
return channelService.sendTextToChannel(errorNotification, message.getChannel())
|
||||
.thenAccept(message1 -> log.info("Notified about not being able to send ban notification in server {} and channel {} from user {}."
|
||||
, guild, message.getChannel().getIdLong(), banningMember.getIdLong()));
|
||||
if(banResult == NOTIFICATION_FAILED) {
|
||||
String errorNotification = templateService.renderSimpleTemplate(BAN_NOTIFICATION_NOT_POSSIBLE, guild.getIdLong());
|
||||
return channelService.sendTextToChannel(errorNotification, message.getChannel())
|
||||
.thenAccept(message1 -> log.info("Notified about not being able to send ban notification in server {} and channel {} from user {}."
|
||||
, guild, message.getChannel().getIdLong(), banningMember.getIdLong()));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
})
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
@@ -83,14 +89,28 @@ public class Ban extends AbstractConditionableCommand {
|
||||
if(slashCommandParameterService.hasCommandOptionWithFullType(USER_PARAMETER, event, OptionType.USER)) {
|
||||
Member member = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, User.class, Member.class);
|
||||
return banService.banUserWithNotification(member.getUser(), reason, event.getMember(), 0)
|
||||
.thenCompose(banResult -> interactionService.replyEmbed(BAN_RESPONSE, event))
|
||||
.thenCompose(banResult -> {
|
||||
if(banResult == NOTIFICATION_FAILED) {
|
||||
String errorNotification = templateService.renderSimpleTemplate(BAN_NOTIFICATION_NOT_POSSIBLE, event.getGuild().getIdLong());
|
||||
return interactionService.replyString(errorNotification, event);
|
||||
} else {
|
||||
return interactionService.replyEmbed(BAN_RESPONSE, event);
|
||||
}
|
||||
})
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
} else {
|
||||
String userIdStr = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, User.class, String.class);
|
||||
Long userId = Long.parseLong(userIdStr);
|
||||
return userService.retrieveUserForId(userId)
|
||||
.thenCompose(user -> banService.banUserWithNotification(user, reason, event.getMember(), 0))
|
||||
.thenCompose(banResult -> interactionService.replyEmbed(BAN_RESPONSE, event))
|
||||
.thenCompose(banResult -> {
|
||||
if(banResult == NOTIFICATION_FAILED) {
|
||||
String errorNotification = templateService.renderSimpleTemplate(BAN_NOTIFICATION_NOT_POSSIBLE, event.getGuild().getIdLong());
|
||||
return interactionService.replyString(errorNotification, event);
|
||||
} else {
|
||||
return interactionService.replyEmbed(BAN_RESPONSE, event);
|
||||
}
|
||||
})
|
||||
.thenApply(banResult -> CommandResult.fromSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
@@ -64,7 +64,7 @@ public class DecayAllWarnings extends AbstractConditionableCommand {
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(ModerationSlashCommandNames.MUTE)
|
||||
.rootCommandName(ModerationSlashCommandNames.WARN_DECAY)
|
||||
.commandName(DECAY_ALL_WARNINGS_COMMAND)
|
||||
.build();
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
|
||||
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
|
||||
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationSlashCommandNames;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.service.InfractionService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class EditInfraction extends AbstractConditionableCommand {
|
||||
|
||||
private static final String EDIT_INFRACTION_COMMAND = "editInfraction";
|
||||
private static final String REASON_PARAMETER = "newReason";
|
||||
private static final String ID_PARAMETER = "id";
|
||||
private static final String EDIT_INFRACTION_RESPONSE = "editInfraction_response";
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long infractionId = slashCommandParameterService.getCommandOption(ID_PARAMETER, event, Long.class, Integer.class).longValue();
|
||||
String newReason = slashCommandParameterService.getCommandOption(REASON_PARAMETER, event, String.class);
|
||||
return infractionService.editInfraction(infractionId, newReason, event.getGuild().getIdLong())
|
||||
.thenCompose(unused -> interactionService.replyEmbed(EDIT_INFRACTION_RESPONSE, event))
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
|
||||
Parameter idParameter = Parameter
|
||||
.builder()
|
||||
.name(ID_PARAMETER)
|
||||
.type(Long.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(idParameter);
|
||||
|
||||
Parameter typeParameter = Parameter
|
||||
.builder()
|
||||
.name(REASON_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
parameters.add(typeParameter);
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(ModerationSlashCommandNames.INFRACTIONS)
|
||||
.commandName("edit")
|
||||
.build();
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(EDIT_INFRACTION_COMMAND)
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(false)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.INFRACTIONS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.core.service.UserService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationSlashCommandNames;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.InfractionParameter;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.InfractionEntry;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.InfractionsModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class Infractions extends AbstractConditionableCommand {
|
||||
|
||||
private static final String INFRACTIONS_COMMAND = "infractions";
|
||||
private static final String USER_PARAMETER = "user";
|
||||
private static final String INFRACTIONS_RESPONSE_TEMPLATE = "infractions_display_response";
|
||||
private static final String NO_INFRACTIONS_TEMPLATE_KEY = "infractions_no_infractions_found";
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Infraction> infractions;
|
||||
if(!commandContext.getParameters().getParameters().isEmpty()) {
|
||||
Member member = (Member) commandContext.getParameters().getParameters().get(0);
|
||||
if(!member.getGuild().equals(commandContext.getGuild())) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
infractions = infractionManagementService.getInfractionsForUser(userInServerManagementService.loadOrCreateUser(member));
|
||||
} else {
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild());
|
||||
infractions = infractionManagementService.getInfractionsForServer(server);
|
||||
}
|
||||
if(infractions.isEmpty()) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_INFRACTIONS_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
|
||||
} else {
|
||||
List<InfractionEntry> convertedInfractions = fromInfractions(infractions);
|
||||
InfractionsModel model = InfractionsModel
|
||||
.builder()
|
||||
.entries(convertedInfractions)
|
||||
.build();
|
||||
return paginatorService.createPaginatorFromTemplate(INFRACTIONS_RESPONSE_TEMPLATE, model, commandContext.getChannel(), commandContext.getAuthor().getIdLong())
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<Infraction> infractions;
|
||||
if(slashCommandParameterService.hasCommandOptionWithFullType(USER_PARAMETER, event, OptionType.USER)) {
|
||||
Member member = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, User.class, Member.class);
|
||||
if(!member.getGuild().equals(event.getGuild())) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
infractions = infractionManagementService.getInfractionsForUser(userInServerManagementService.loadOrCreateUser(member));
|
||||
} else if(slashCommandParameterService.hasCommandOptionWithFullType(USER_PARAMETER, event, OptionType.STRING)){
|
||||
String userIdStr = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, User.class, String.class);
|
||||
Long userId = Long.parseLong(userIdStr);
|
||||
AUserInAServer userInServer = userInServerManagementService.createUserInServer(event.getGuild().getIdLong(), userId);
|
||||
infractions = infractionManagementService.getInfractionsForUser(userInServer);
|
||||
|
||||
} else {
|
||||
AServer server = serverManagementService.loadServer(event.getGuild());
|
||||
infractions = infractionManagementService.getInfractionsForServer(server);
|
||||
}
|
||||
if(infractions.isEmpty()) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_INFRACTIONS_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
|
||||
} else {
|
||||
List<InfractionEntry> convertedInfractions = fromInfractions(infractions);
|
||||
InfractionsModel model = InfractionsModel
|
||||
.builder()
|
||||
.entries(convertedInfractions)
|
||||
.build();
|
||||
return paginatorService.createPaginatorFromTemplate(INFRACTIONS_RESPONSE_TEMPLATE, model, event)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
}
|
||||
|
||||
public List<InfractionEntry> fromInfractions(List<Infraction> infractions) {
|
||||
return infractions
|
||||
.stream()
|
||||
.map(this::fromInfraction)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private InfractionEntry fromInfraction(Infraction infraction) {
|
||||
Map<String, String> parameters = infraction
|
||||
.getParameters()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(infractionParameter -> infractionParameter.getInfractionParameterId().getName(), InfractionParameter::getValue));
|
||||
return InfractionEntry
|
||||
.builder()
|
||||
.infractionId(infraction.getId())
|
||||
.serverId(infraction.getServer().getId())
|
||||
.decayed(infraction.getDecayed())
|
||||
.decayDate(infraction.getDecayedDate())
|
||||
.parameters(parameters)
|
||||
.creationDate(infraction.getCreated())
|
||||
.infractionUser(MemberDisplay.fromAUserInAServer(infraction.getUser()))
|
||||
.infractionCreationUser(MemberDisplay.fromAUserInAServer(infraction.getInfractionCreator()))
|
||||
.reason(infraction.getDescription())
|
||||
.type(infraction.getType())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
Parameter userParameter = Parameter
|
||||
.builder()
|
||||
.name(USER_PARAMETER)
|
||||
.type(User.class)
|
||||
.templated(true)
|
||||
.optional(true)
|
||||
.build();
|
||||
parameters.add(userParameter);
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(ModerationSlashCommandNames.INFRACTIONS)
|
||||
.commandName("list")
|
||||
.build();
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
return CommandConfiguration.builder()
|
||||
.name(INFRACTIONS_COMMAND)
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(false)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.INFRACTIONS;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -5,11 +5,11 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.ParseUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
@@ -18,7 +18,6 @@ import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefiniti
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteContext;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -59,29 +58,19 @@ public class Mute extends AbstractConditionableCommand {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Member member = (Member) parameters.get(0);
|
||||
Guild guild = commandContext.getGuild();
|
||||
GuildMessageChannel channel = commandContext.getChannel();
|
||||
if(!member.getGuild().equals(guild)) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
Duration duration = (Duration) parameters.get(1);
|
||||
String defaultReason = templateService.renderSimpleTemplate(MUTE_DEFAULT_REASON_TEMPLATE, guild.getIdLong());
|
||||
String reason = parameters.size() == 3 ? (String) parameters.get(2) : defaultReason;
|
||||
ServerChannelMessage context = ServerChannelMessage
|
||||
.builder()
|
||||
.serverId(guild.getIdLong())
|
||||
.channelId(channel.getIdLong())
|
||||
.messageId(commandContext.getMessage().getIdLong())
|
||||
.build();
|
||||
MuteContext muteLogModel = MuteContext
|
||||
.builder()
|
||||
.muteDate(Instant.now())
|
||||
.muteTargetDate(Instant.now().plus(duration))
|
||||
.mutedUser(member)
|
||||
.channelId(commandContext.getChannel().getIdLong())
|
||||
.reason(reason)
|
||||
.contextChannel(channel)
|
||||
.message(commandContext.getMessage())
|
||||
.mutingUser(commandContext.getAuthor())
|
||||
.context(context)
|
||||
.build();
|
||||
return muteService.muteMemberWithLog(muteLogModel)
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
@@ -90,7 +79,6 @@ public class Mute extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Guild guild = event.getGuild();
|
||||
GuildMessageChannel channel = event.getGuildChannel();
|
||||
Member targetMember = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, Member.class);
|
||||
String durationStr = slashCommandParameterService.getCommandOption(DURATION_PARAMETER, event, Duration.class, String.class);
|
||||
Duration duration = ParseUtils.parseDuration(durationStr);
|
||||
@@ -100,20 +88,13 @@ public class Mute extends AbstractConditionableCommand {
|
||||
} else {
|
||||
reason = templateService.renderSimpleTemplate(MUTE_DEFAULT_REASON_TEMPLATE, guild.getIdLong());
|
||||
}
|
||||
ServerChannelMessage context = ServerChannelMessage
|
||||
.builder()
|
||||
.serverId(guild.getIdLong())
|
||||
.channelId(channel.getIdLong())
|
||||
.build();
|
||||
MuteContext muteLogModel = MuteContext
|
||||
.builder()
|
||||
.muteDate(Instant.now())
|
||||
.muteTargetDate(Instant.now().plus(duration))
|
||||
.mutedUser(targetMember)
|
||||
.reason(reason)
|
||||
.contextChannel(channel)
|
||||
.channelId(event.getChannel().getIdLong())
|
||||
.mutingUser(event.getMember())
|
||||
.context(context)
|
||||
.build();
|
||||
return muteService.muteMemberWithLog(muteLogModel)
|
||||
.thenCompose(unused -> interactionService.replyEmbed(MUTE_RESPONSE, event))
|
||||
@@ -146,7 +127,11 @@ public class Mute extends AbstractConditionableCommand {
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(userParameter, durationParameter, reasonParameter);
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).hasExample(true).build();
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.hasExample(true)
|
||||
.build();
|
||||
EffectConfig muteEffect = EffectConfig
|
||||
.builder()
|
||||
.position(0)
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
|
||||
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.config.validator.MinIntegerValueValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteRoleManagementService;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class SetMuteRole extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private MuteRoleManagementService muteRoleManagementService;
|
||||
|
||||
@Autowired
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
Role jdaRole = (Role) commandContext.getParameters().getParameters().get(0);
|
||||
if(!jdaRole.getGuild().equals(commandContext.getGuild())) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
ARole role = roleManagementService.findRole(jdaRole.getIdLong());
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild());
|
||||
muteRoleManagementService.setMuteRoleForServer(server, role);
|
||||
return CommandResult.fromSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("role").templated(true).type(Role.class).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("setMuteRole")
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.MUTING;
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -5,10 +5,10 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.service.UserService;
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
@@ -53,7 +53,7 @@ public class UnMute extends AbstractConditionableCommand {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
AUserInAServer userToUnMute = userInServerManagementService.loadOrCreateUser(member);
|
||||
return muteService.unMuteUser(userToUnMute).thenApply(aVoid ->
|
||||
return muteService.unMuteUser(userToUnMute, commandContext.getAuthor()).thenApply(aVoid ->
|
||||
CommandResult.fromSuccess()
|
||||
);
|
||||
}
|
||||
@@ -65,7 +65,7 @@ public class UnMute extends AbstractConditionableCommand {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
AUserInAServer userToUnMute = userInServerManagementService.loadOrCreateUser(targetMember);
|
||||
return muteService.unMuteUser(userToUnMute)
|
||||
return muteService.unMuteUser(userToUnMute, event.getMember())
|
||||
.thenCompose(unused -> interactionService.replyEmbed(UN_MUTE_RESPONSE, event))
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -5,7 +5,8 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
|
||||
import dev.sheldan.abstracto.core.command.config.*;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -4,10 +4,10 @@ import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
|
||||
@@ -21,4 +21,9 @@ public class ModerationListenerConfig {
|
||||
return executorService.setupExecutorFor("warningCreatedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "reportMessageCreatedExecutor")
|
||||
public TaskExecutor reportMessageCreatedExecutor() {
|
||||
return executorService.setupExecutorFor("reportMessageCreatedListener");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteEntry;
|
||||
@@ -25,9 +24,6 @@ public class MuteEntryConverter {
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
|
||||
@@ -5,14 +5,18 @@ import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncJoinListener;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class JoinMuteListener implements AsyncJoinListener {
|
||||
@@ -21,17 +25,15 @@ public class JoinMuteListener implements AsyncJoinListener {
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Autowired
|
||||
private MuteService muteService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
private MemberService memberService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberJoinModel model) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getJoiningUser().getUserId());
|
||||
if(muteManagementService.hasActiveMute(aUserInAServer)) {
|
||||
Optional<Mute> optionalMute = muteManagementService.getAMuteOfOptional(model.getMember());
|
||||
if(optionalMute.isPresent()) {
|
||||
log.info("Re-muting user {} which joined the server {}, because the mute has not ended yet.", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
muteService.applyMuteRole(aUserInAServer);
|
||||
Mute mute = optionalMute.get();
|
||||
memberService.timeoutUser(model.getMember(), mute.getMuteTargetDate());
|
||||
}
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMemberTimeoutUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.audit.ActionType;
|
||||
import net.dv8tion.jda.api.audit.AuditLogEntry;
|
||||
import net.dv8tion.jda.api.audit.AuditLogKey;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MemberTimeoutListener implements AsyncMemberTimeoutUpdatedListener {
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private MemberTimeoutListener self;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberTimeoutUpdatedModel model) {
|
||||
Guild guild = model.getGuild();
|
||||
guild.retrieveAuditLogs()
|
||||
.type(ActionType.MEMBER_UPDATE)
|
||||
.limit(10)
|
||||
.queue(auditLogEntries -> {
|
||||
CompletableFuture<Void> notificationFuture = null;
|
||||
if(auditLogEntries.isEmpty()) {
|
||||
log.info("Did not find recent timeouts in guild {}.", model.getServerId());
|
||||
notificationFuture = self.sendMutingUpdateNotification(model, null);
|
||||
} else {
|
||||
Optional<AuditLogEntry> timeoutEntryOptional = auditLogEntries
|
||||
.stream()
|
||||
.filter(auditLogEntry -> auditLogEntry.getChangeByKey(AuditLogKey.MEMBER_TIME_OUT) != null
|
||||
&& auditLogEntry.getTargetIdLong() == model.getTimeoutUser().getUserId())
|
||||
.findFirst();
|
||||
if(timeoutEntryOptional.isPresent()) {
|
||||
AuditLogEntry auditLogEntry = timeoutEntryOptional.get();
|
||||
User responsibleUser = auditLogEntry.getUser();
|
||||
if(guild.getSelfMember().getIdLong() != responsibleUser.getIdLong()) {
|
||||
notificationFuture = self.sendMutingUpdateNotification(model, auditLogEntry);
|
||||
}
|
||||
} else {
|
||||
notificationFuture = self.sendMutingUpdateNotification(model, null);
|
||||
}
|
||||
}
|
||||
if(notificationFuture != null) {
|
||||
notificationFuture.thenAccept(unused -> {
|
||||
log.info("Sent notification about timeout change {} -> {} of user {} in server {}.",
|
||||
model.getOldTimeout(), model.getNewTimeout(), model.getTimeoutUser().getUserId(), model.getServerId());
|
||||
}).exceptionally(throwable -> {
|
||||
log.info("Sent notification about timeout change {} -> {} of user {} in server {}.",
|
||||
model.getOldTimeout(), model.getNewTimeout(), model.getTimeoutUser().getUserId(), model.getServerId());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> sendMutingUpdateNotification(MemberTimeoutUpdatedModel model, AuditLogEntry logEntry) {
|
||||
User responsibleUser;
|
||||
Guild guild = model.getGuild();
|
||||
CompletableFuture<Member> future;
|
||||
String reason;
|
||||
if(logEntry != null) {
|
||||
responsibleUser = logEntry.getUser();
|
||||
if(responsibleUser != null) {
|
||||
ServerUser responsibleServerUser = ServerUser
|
||||
.builder()
|
||||
.serverId(guild.getIdLong())
|
||||
.isBot(responsibleUser.isBot())
|
||||
.userId(responsibleUser.getIdLong())
|
||||
.build();
|
||||
future = memberService.retrieveMemberInServer(responsibleServerUser);
|
||||
} else {
|
||||
future = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
reason = logEntry.getReason();
|
||||
} else {
|
||||
future = CompletableFuture.completedFuture(null);
|
||||
reason = null;
|
||||
}
|
||||
CompletableFuture<Void> returningFuture = new CompletableFuture<>();
|
||||
future.whenComplete((aVoid, throwable) -> {
|
||||
try {
|
||||
MuteListenerModel muteLogModel = MuteListenerModel
|
||||
.builder()
|
||||
.muteTargetDate(model.getNewTimeout() != null ? model.getNewTimeout().toInstant() : null)
|
||||
.oldMuteTargetDate(model.getOldTimeout() != null ? model.getOldTimeout().toInstant() : null)
|
||||
.mutingUser(future.isCompletedExceptionally() ? null : future.join())
|
||||
.mutedUser(model.getMember())
|
||||
.reason(reason)
|
||||
.build();
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MuteServiceBean.MUTE_LOG_TEMPLATE, muteLogModel, guild.getIdLong());
|
||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, model.getServerId()));
|
||||
returningFuture.complete(null);
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to log timeout update event for user {} in guild {}.", model.getTimeoutUser().getUserId(), model.getServerId(), exception);
|
||||
}
|
||||
});
|
||||
|
||||
return returningFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.MUTING;
|
||||
}
|
||||
}
|
||||
@@ -48,9 +48,14 @@ public class ReactionReportListener implements AsyncReactionAddedListener {
|
||||
memberService.retrieveMemberInServer(model.getUserReacting())
|
||||
.thenCompose(member -> reactionService.removeReactionFromMessage(model.getReaction(), cachedMessage, member.getUser()))
|
||||
.thenAccept(unused -> log.info("Removed report reaction on message {} in server {} in channel {}.", cachedMessage.getMessageId(), serverId, cachedMessage.getChannelId()));
|
||||
log.info("User {} in server {} reacted to report a message {} from channel {}.",
|
||||
model.getUserReacting().getUserId(), model.getServerId(), cachedMessage.getMessageId(), cachedMessage.getChannelId());
|
||||
reactionReportService.createReactionReport(cachedMessage, model.getUserReacting()).exceptionally(throwable -> {
|
||||
|
||||
if(!reactionReportService.allowedToReport(model.getUserReacting())) {
|
||||
log.info("User {} was reported on message {} in server {} within the cooldown. Ignoring.",
|
||||
cachedMessage.getAuthor().getAuthorId(), cachedMessage.getMessageId(), cachedMessage.getServerId());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
reactionReportService.createReactionReport(cachedMessage, model.getUserReacting(), null).exceptionally(throwable -> {
|
||||
log.error("Failed to create reaction report in server {} on message {} in channel {}.", serverId, cachedMessage.getMessageId(), cachedMessage.getChannelId(), throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -4,7 +4,6 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncUserBannedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.UserBannedModel;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
@@ -27,9 +26,6 @@ import java.util.concurrent.CompletableFuture;
|
||||
@Slf4j
|
||||
public class UserBannedListener implements AsyncUserBannedListener {
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.infraction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.UserService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.listener.InfractionUpdatedDescriptionListener;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.InfractionParameter;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.InfractionDescriptionEventModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.BanLog;
|
||||
import dev.sheldan.abstracto.moderation.service.BanService;
|
||||
import dev.sheldan.abstracto.moderation.service.BanServiceBean;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BanReasonUpdatedListener implements InfractionUpdatedDescriptionListener {
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private BanServiceBean banServiceBean;
|
||||
|
||||
@Autowired
|
||||
private BanReasonUpdatedListener self;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DefaultListenerResult> execute(InfractionDescriptionEventModel model) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(model.getInfractionId());
|
||||
CompletableFuture<User> infractionUser = userService.retrieveUserForId(infraction.getUser().getUserReference().getId());
|
||||
CompletableFuture<Member> creatorUser = memberService.retrieveMemberInServer(ServerUser.fromAUserInAServer(infraction.getInfractionCreator()));
|
||||
CompletableFuture<DefaultListenerResult> returningFuture = new CompletableFuture<>();
|
||||
Long infractionId = infraction.getId();
|
||||
CompletableFuture.allOf(infractionUser, creatorUser)
|
||||
.whenComplete((unused, throwable) -> {
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to load members for infraction update of ban {} in server {}.", infractionId, model.getServerId(), throwable);
|
||||
}
|
||||
self.handleBanUpdate(model, infractionUser, creatorUser, returningFuture);
|
||||
});
|
||||
return returningFuture;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void handleBanUpdate(InfractionDescriptionEventModel model, CompletableFuture<User> infractionUser, CompletableFuture<Member> infractionCreator, CompletableFuture<DefaultListenerResult> returningFuture) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(model.getInfractionId());
|
||||
GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(model.getServerId(), infraction.getLogChannel().getId());
|
||||
Integer deletionDays = infraction
|
||||
.getParameters()
|
||||
.stream()
|
||||
.filter(infractionParameter -> infractionParameter.getInfractionParameterId().getName().equals(BanService.INFRACTION_PARAMETER_DELETION_DAYS_KEY))
|
||||
.findAny()
|
||||
.map(InfractionParameter::getValue)
|
||||
.map(Integer::parseInt)
|
||||
.orElse(0);
|
||||
BanLog banLog = BanLog
|
||||
.builder()
|
||||
.bannedUser(infractionUser.isCompletedExceptionally() ? null : infractionUser.join())
|
||||
.banningMember(infractionCreator.isCompletedExceptionally() ? null : infractionCreator.join())
|
||||
.deletionDays(deletionDays)
|
||||
.reason(model.getNewDescription())
|
||||
.build();
|
||||
|
||||
MessageToSend message = banServiceBean.renderBanMessage(banLog, model.getServerId());
|
||||
messageService.editMessageInChannel(messageChannel, message, infraction.getLogMessageId())
|
||||
.thenAccept(unused1 -> returningFuture.complete(DefaultListenerResult.PROCESSED))
|
||||
.exceptionally(throwable1 -> {
|
||||
returningFuture.complete(DefaultListenerResult.PROCESSED);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(InfractionDescriptionEventModel model) {
|
||||
return model.getType().equals(BanService.BAN_INFRACTION_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.MODERATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.infraction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.GuildService;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.listener.InfractionUpdatedDescriptionListener;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.InfractionDescriptionEventModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnContext;
|
||||
import dev.sheldan.abstracto.moderation.service.WarnServiceBean;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class WarnReasonUpdatedListener implements InfractionUpdatedDescriptionListener {
|
||||
|
||||
@Autowired
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@Autowired
|
||||
private WarnServiceBean warnService;
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private WarnReasonUpdatedListener self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<DefaultListenerResult> execute(InfractionDescriptionEventModel model) {
|
||||
Optional<Warning> potentialWarning = warnManagementService.findWarnByInfraction(model.getInfractionId());
|
||||
if(potentialWarning.isPresent()) {
|
||||
Warning warning = potentialWarning.get();
|
||||
Long warnId = warning.getWarnId().getId();
|
||||
CompletableFuture<Member> warnedUser = memberService.retrieveMemberInServer(ServerUser.fromAUserInAServer(warning.getWarnedUser()));
|
||||
CompletableFuture<Member> warningUser = memberService.retrieveMemberInServer(ServerUser.fromAUserInAServer(warning.getWarningUser()));
|
||||
CompletableFuture<DefaultListenerResult> returningFuture = new CompletableFuture<>();
|
||||
CompletableFuture.allOf(warnedUser, warningUser)
|
||||
.whenComplete((unused, throwable) -> {
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to load members for infraction update of warning {} in server {}.", warnId, model.getServerId(), throwable);
|
||||
}
|
||||
self.handleWarnUpdate(model, warnId, warnedUser, warningUser, returningFuture);
|
||||
});
|
||||
return returningFuture;
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(DefaultListenerResult.IGNORED);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleWarnUpdate(InfractionDescriptionEventModel model, Long warnId, CompletableFuture<Member> warnedUser, CompletableFuture<Member> warningUser, CompletableFuture<DefaultListenerResult> returningFuture) {
|
||||
Guild guild = guildService.getGuildById(model.getServerId());
|
||||
Infraction infraction = infractionManagementService.loadInfraction(model.getInfractionId());
|
||||
GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(model.getServerId(), infraction.getLogChannel().getId());
|
||||
WarnContext context = WarnContext
|
||||
.builder()
|
||||
.warnedMember(warnedUser.isCompletedExceptionally() ? null : warnedUser.join())
|
||||
.member(warningUser.isCompletedExceptionally() ? null : warningUser.join())
|
||||
.reason(model.getNewDescription())
|
||||
.warnId(warnId)
|
||||
.guild(guild)
|
||||
.build();
|
||||
MessageToSend message = warnService.renderMessageModel(context);
|
||||
messageService.editMessageInChannel(messageChannel, message, infraction.getLogMessageId())
|
||||
.thenAccept(unused1 -> returningFuture.complete(DefaultListenerResult.PROCESSED))
|
||||
.exceptionally(throwable1 -> {
|
||||
returningFuture.complete(DefaultListenerResult.PROCESSED);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.WARNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(InfractionDescriptionEventModel model) {
|
||||
return model.getType().equals(WarnServiceBean.WARN_INFRACTION_TYPE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.interaction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.MessageContextConfig;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageContextCommandListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.interaction.MessageContextInteractionModel;
|
||||
import dev.sheldan.abstracto.core.interaction.context.ContextCommandService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.service.ReactionReportService;
|
||||
import dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean.REACTION_REPORT_RESPONSE_TEMPLATE;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReportContextCommandListener implements MessageContextCommandListener {
|
||||
|
||||
@Autowired
|
||||
private ContextCommandService contextCommandService;
|
||||
|
||||
@Autowired
|
||||
private ReactionReportService reactionReportService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageContextInteractionModel model) {
|
||||
Message targetMessage = model.getEvent().getTarget();
|
||||
if(targetMessage.getAuthor().getIdLong() == model.getEvent().getUser().getIdLong()) {
|
||||
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
ServerUser userReporting = ServerUser
|
||||
.builder()
|
||||
.serverId(model.getServerId())
|
||||
.userId(model.getEvent().getUser().getIdLong())
|
||||
.isBot(model.getEvent().getUser().isBot())
|
||||
.build();
|
||||
|
||||
if(!reactionReportService.allowedToReport(userReporting)) {
|
||||
log.info("User {} was reported on message {} in server {} within the cooldown. Ignoring.",
|
||||
targetMessage.getAuthor().getIdLong(), targetMessage.getIdLong(), targetMessage.getGuild().getIdLong());
|
||||
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
reactionReportService.createReactionReport(targetMessage, userReporting, null).exceptionally(throwable -> {
|
||||
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
|
||||
model.getServerId(), targetMessage.getIdLong(), model.getEvent().getChannel().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
interactionService.replyEmbed(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageContextConfig getConfig() {
|
||||
return MessageContextConfig
|
||||
.builder()
|
||||
.isTemplated(true)
|
||||
.name("report_message")
|
||||
.templateKey("report_message_context_menu_label")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(MessageContextInteractionModel model) {
|
||||
return contextCommandService.matchesGuildContextName(model, getConfig(), model.getServerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.REPORT_REACTIONS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.interaction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListener;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerResult;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.service.MessageCache;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.model.interaction.MessageReportModalPayload;
|
||||
import dev.sheldan.abstracto.moderation.service.ReactionReportService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.interactions.modals.ModalMapping;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import static dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean.REACTION_REPORT_RESPONSE_TEMPLATE;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReportContextModalListener implements ModalInteractionListener {
|
||||
|
||||
@Autowired
|
||||
private MessageCache messageCache;
|
||||
|
||||
@Autowired
|
||||
private ReactionReportService reactionReportService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public ModalInteractionListenerResult execute(ModalInteractionListenerModel model) {
|
||||
MessageReportModalPayload payload = (MessageReportModalPayload) model.getDeserializedPayload();
|
||||
String context = model
|
||||
.getEvent()
|
||||
.getValues()
|
||||
.stream()
|
||||
.filter(modalMapping -> modalMapping.getId().equals(payload.getTextInputId()))
|
||||
.map(ModalMapping::getAsString)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
messageCache.getMessageFromCache(payload.getServerId(), payload.getChannelId(), payload.getMessageId()).thenAccept(cachedMessage -> {
|
||||
ServerUser userReporting = ServerUser
|
||||
.builder()
|
||||
.serverId(model.getServerId())
|
||||
.userId(cachedMessage.getAuthor().getAuthorId())
|
||||
.isBot(cachedMessage.getAuthor().getIsBot())
|
||||
.build();
|
||||
reactionReportService.createReactionReport(cachedMessage, userReporting, context)
|
||||
.thenAccept(unused -> {
|
||||
interactionService.replyEmbed(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
log.info("Handled modal for message report with id {} in guild {} in channel {} on message {}",
|
||||
model.getEvent().getModalId(), payload.getServerId(), payload.getChannelId(), payload.getMessageId());
|
||||
componentPayloadManagementService.deletePayload(payload.getModalId());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
|
||||
model.getServerId(), cachedMessage.getMessageId(), model.getEvent().getChannel().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to load reported message.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return ModalInteractionListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.REPORT_REACTIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ModalInteractionListenerModel model) {
|
||||
return model.getDeserializedPayload() instanceof MessageReportModalPayload && model.getEvent().isFromGuild();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.interaction;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentService;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.MessageContextConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalConfigPayload;
|
||||
import dev.sheldan.abstracto.core.interaction.modal.ModalService;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.interaction.context.message.listener.MessageContextCommandListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.interaction.MessageContextInteractionModel;
|
||||
import dev.sheldan.abstracto.core.interaction.context.ContextCommandService;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.model.interaction.MessageReportModalPayload;
|
||||
import dev.sheldan.abstracto.moderation.model.template.listener.ReportInputModalModel;
|
||||
import dev.sheldan.abstracto.moderation.service.ReactionReportService;
|
||||
import dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReportWithContextContextCommandListener implements MessageContextCommandListener {
|
||||
|
||||
@Autowired
|
||||
private ContextCommandService contextCommandService;
|
||||
|
||||
@Autowired
|
||||
private ModalService modalService;
|
||||
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||
|
||||
@Autowired
|
||||
private ReportWithContextContextCommandListener self;
|
||||
|
||||
@Autowired
|
||||
private ReactionReportService reactionReportService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
private static final String REACTION_REPORT_MODAL_TEMPLATE = "reactionReport_input";
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageContextInteractionModel model) {
|
||||
Message targetMessage = model.getEvent().getTarget();
|
||||
if(targetMessage.getAuthor().getIdLong() == model.getEvent().getUser().getIdLong()) {
|
||||
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
ServerUser userReporting = ServerUser
|
||||
.builder()
|
||||
.serverId(model.getServerId())
|
||||
.userId(model.getEvent().getUser().getIdLong())
|
||||
.isBot(model.getEvent().getUser().isBot())
|
||||
.build();
|
||||
if(!reactionReportService.allowedToReport(userReporting)) {
|
||||
log.info("User {} was reported on message {} in server {} within the cooldown. Ignoring.",
|
||||
targetMessage.getAuthor().getIdLong(), targetMessage.getIdLong(), targetMessage.getGuild().getIdLong());
|
||||
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE, new Object(), model.getEvent());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
String modalId = componentService.generateComponentId();
|
||||
String textInputId = componentService.generateComponentId();
|
||||
|
||||
ReportInputModalModel modalModel = ReportInputModalModel
|
||||
.builder()
|
||||
.modalId(modalId)
|
||||
.inputComponentId(textInputId)
|
||||
.build();
|
||||
modalService.replyModal(model.getEvent(), REACTION_REPORT_MODAL_TEMPLATE, modalModel)
|
||||
.thenAccept(unused -> {
|
||||
log.info("Created modal for report on message {} from user {} in server {}.",
|
||||
targetMessage.getIdLong(), targetMessage.getAuthor().getIdLong(), targetMessage.getGuild().getIdLong());
|
||||
self.persistModalPayload(targetMessage, modalId, textInputId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to create modal for report on message {} from user {} in server {}.",
|
||||
targetMessage.getIdLong(), targetMessage.getAuthor().getIdLong(), targetMessage.getGuild().getIdLong());
|
||||
return null;
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistModalPayload(Message message, String modalId, String inputId) {
|
||||
MessageReportModalPayload payload = MessageReportModalPayload
|
||||
.builder()
|
||||
.channelId(message.getChannel().getIdLong())
|
||||
.messageId(message.getIdLong())
|
||||
.serverId(message.getGuild().getIdLong())
|
||||
.modalId(modalId)
|
||||
.textInputId(inputId)
|
||||
.build();
|
||||
ModalConfigPayload payloadConfig = ModalConfigPayload
|
||||
.builder()
|
||||
.modalPayload(payload)
|
||||
.origin(ReactionReportServiceBean.REACTION_REPORT_MODAL_ORIGIN)
|
||||
.payloadType(payload.getClass())
|
||||
.modalId(modalId)
|
||||
.build();
|
||||
componentPayloadManagementService.createModalPayload(payloadConfig, message.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MessageContextConfig getConfig() {
|
||||
return MessageContextConfig
|
||||
.builder()
|
||||
.isTemplated(true)
|
||||
.name("report_message_context")
|
||||
.templateKey("report_message_with_context_context_menu_label")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(MessageContextInteractionModel model) {
|
||||
return contextCommandService.matchesGuildContextName(model, getConfig(), model.getServerId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.REPORT_REACTIONS;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.manager;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.moderation.listener.ReportMessageCreatedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.ReportMessageCreatedModel;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class ReportMessageCreatedListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<ReportMessageCreatedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("reportMessageCreatedExecutor")
|
||||
private TaskExecutor reportMessageCreatedExecutor;
|
||||
|
||||
public void sendReportMessageCreatedEvent(CachedMessage cachedMessage, Message message, ServerUser reporter) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ReportMessageCreatedModel model = createEventModel(cachedMessage, message, reporter);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model, reportMessageCreatedExecutor));
|
||||
}
|
||||
|
||||
private ReportMessageCreatedModel createEventModel(CachedMessage reportedMessage, Message message, ServerUser reporter) {
|
||||
return ReportMessageCreatedModel
|
||||
.builder()
|
||||
.reportedMessage(ServerChannelMessage.fromCachedMessage(reportedMessage))
|
||||
.reportMessage(ServerChannelMessage.fromMessage(message))
|
||||
.reporter(reporter)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.moderation.model.database.InfractionParameter;
|
||||
import dev.sheldan.abstracto.moderation.model.database.embedded.InfractionParameterId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface InfractionParameterRepository extends JpaRepository<InfractionParameter, InfractionParameterId> {
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
@@ -10,4 +11,6 @@ import java.util.List;
|
||||
@Repository
|
||||
public interface InfractionRepository extends JpaRepository<Infraction, Long> {
|
||||
List<Infraction> findByUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
List<Infraction> findByUserOrderByCreated(AUserInAServer aUserInAServer);
|
||||
List<Infraction> findByServerOrderByCreated(AServer server);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.Optional;
|
||||
public interface MuteRepository extends JpaRepository<Mute, ServerSpecificId> {
|
||||
boolean existsByMutedUserAndMuteEndedFalse(AUserInAServer userInAServer);
|
||||
|
||||
Mute findTopByMutedUserAndMuteEndedFalse(AUserInAServer userInAServer);
|
||||
Optional<Mute> findTopByMutedUserAndMuteEndedFalse(AUserInAServer userInAServer);
|
||||
|
||||
List<Mute> findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(AUserInAServer aUserInAServer);
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.MuteRole;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface MuteRoleRepository extends JpaRepository<MuteRole, Long> {
|
||||
|
||||
MuteRole findByRoleServer(AServer server);
|
||||
|
||||
List<MuteRole> findAllByRoleServer(AServer server);
|
||||
|
||||
boolean existsByRoleServer(AServer server);
|
||||
}
|
||||
@@ -6,10 +6,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface ReactionReportRepository extends JpaRepository<ReactionReport, Long> {
|
||||
|
||||
Optional<ReactionReport> findByReportedUserAndCreatedLessThan(AUserInAServer aUserInAServer, Instant maxCreated);
|
||||
List<ReactionReport> findByReportedUserAndCreatedLessThan(AUserInAServer aUserInAServer, Instant maxCreated);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@@ -27,6 +26,6 @@ public interface WarnRepository extends JpaRepository<Warning, ServerSpecificId>
|
||||
|
||||
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
@NotNull
|
||||
Optional<Warning> findByWarnId_IdAndWarnId_ServerId(Long warnId, Long serverId);
|
||||
Optional<Warning> findByInfraction_Id(Long infractionId);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.moderation.model.BanResult;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.BanLog;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.BanNotificationModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.UnBanLog;
|
||||
@@ -13,8 +18,12 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -37,6 +46,18 @@ public class BanServiceBean implements BanService {
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<BanResult> banUserWithNotification(User user, String reason, Member banningMember, Integer deletionDays) {
|
||||
BanLog banLog = BanLog
|
||||
@@ -47,18 +68,31 @@ public class BanServiceBean implements BanService {
|
||||
.reason(reason)
|
||||
.build();
|
||||
Guild guild = banningMember.getGuild();
|
||||
CompletableFuture<BanResult> returningFuture = new CompletableFuture<>();
|
||||
sendBanNotification(user, reason, guild)
|
||||
.whenComplete((unused, throwable) -> banUser(guild, user, deletionDays, reason)
|
||||
.thenCompose(unused1 -> sendBanLogMessage(banLog, guild.getIdLong()))
|
||||
.thenAccept(unused1 -> {
|
||||
if(throwable != null) {
|
||||
returningFuture.complete(BanResult.NOTIFICATION_FAILED);
|
||||
} else {
|
||||
returningFuture.complete(BanResult.SUCCESSFUL);
|
||||
}
|
||||
}));
|
||||
return returningFuture;
|
||||
BanResult[] result = {BanResult.SUCCESSFUL};
|
||||
return sendBanNotification(user, reason, guild)
|
||||
.exceptionally(throwable -> {
|
||||
result[0] = BanResult.NOTIFICATION_FAILED;
|
||||
return null;
|
||||
})
|
||||
.thenCompose(unused -> banUser(guild, user, deletionDays, reason))
|
||||
.thenCompose(unused -> sendBanLogMessage(banLog, guild.getIdLong()))
|
||||
.thenAccept(banLogMessage -> self.evaluateAndStoreInfraction(user, guild, reason, banningMember, banLogMessage, deletionDays))
|
||||
.thenApply(unused -> result[0]);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Long> evaluateAndStoreInfraction(User user, Guild guild, String reason, Member banningMember, Message banLogMessage, Integer deletionDays) {
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, guild.getIdLong())) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(ModerationFeatureConfig.BAN_INFRACTION_POINTS, guild.getIdLong());
|
||||
AUserInAServer bannedUser = userInServerManagementService.loadOrCreateUser(guild.getIdLong(), user.getIdLong());
|
||||
AUserInAServer banningUser = userInServerManagementService.loadOrCreateUser(banningMember);
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put(INFRACTION_PARAMETER_DELETION_DAYS_KEY, deletionDays.toString());
|
||||
return infractionService.createInfractionWithNotification(bannedUser, infractionPoints, BAN_INFRACTION_TYPE, reason, banningUser, parameters, banLogMessage)
|
||||
.thenApply(Infraction::getId);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendBanNotification(User user, String reason, Guild guild) {
|
||||
@@ -102,10 +136,15 @@ public class BanServiceBean implements BanService {
|
||||
.thenCompose(unused -> unbanUser(guild, user));
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId) {
|
||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(BAN_LOG_TEMPLATE, banLog, guildId);
|
||||
public CompletableFuture<Message> sendBanLogMessage(BanLog banLog, Long guildId) {
|
||||
MessageToSend banLogMessage = renderBanMessage(banLog, guildId);
|
||||
log.debug("Sending ban log message in guild {}.", guildId);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId));
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId);
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures).thenApply(unused -> messageFutures.get(0).join());
|
||||
}
|
||||
|
||||
public MessageToSend renderBanMessage(BanLog banLog, Long guildId) {
|
||||
return templateService.renderEmbedTemplate(BAN_LOG_TEMPLATE, banLog, guildId);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendUnBanLogMessage(UnBanLog banLog, Long guildId, String template) {
|
||||
|
||||
@@ -1,30 +1,36 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.Prioritized;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.InfractionFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.InfractionPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.InfractionUpdatedDescriptionListener;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.InfractionLevelChangedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.InfractionDescriptionEventModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.InfractionLevelChangeModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionParameterManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -35,9 +41,6 @@ public class InfractionServiceBean implements InfractionService {
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@@ -56,6 +59,15 @@ public class InfractionServiceBean implements InfractionService {
|
||||
@Autowired
|
||||
private InfractionLevelChangedListenerManager infractionLevelChangedListenerManager;
|
||||
|
||||
@Autowired
|
||||
private InfractionParameterManagementService infractionParameterManagementService;
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<InfractionUpdatedDescriptionListener> infractionDescriptionListeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
private static final String INFRACTION_NOTIFICATION_TEMPLATE_KEY = "infraction_level_notification";
|
||||
|
||||
@Override
|
||||
@@ -74,15 +86,31 @@ public class InfractionServiceBean implements InfractionService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction createdInfraction = infractionManagementService.createInfraction(aUserInAServer, points);
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer target, Long points, String type, String description, AUserInAServer creator, Map<String, String> parameters, Message message) {
|
||||
Infraction createdInfraction = infractionManagementService.createInfraction(target, points, type, description, creator, message);
|
||||
parameters.forEach((key, value) -> infractionParameterManagementService.createInfractionParameter(createdInfraction, key, value));
|
||||
Long infractionId = createdInfraction.getId();
|
||||
return createInfractionNotification(aUserInAServer, points)
|
||||
.thenApply(aBoolean -> self.reloadInfraction(infractionId));
|
||||
return createInfractionNotification(target, points, type, description)
|
||||
.thenApply(avoid -> self.reloadInfraction(infractionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createInfractionNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer target, Long points, String type, String description, AUserInAServer creator, Map<String, String> parameters) {
|
||||
return createInfractionWithNotification(target, points, type, description, creator, new HashMap<>(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer target, Long points, String type, String description, AUserInAServer creator, Message logMessage) {
|
||||
return createInfractionWithNotification(target, points, type, description, creator, new HashMap<>(), logMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer target, Long points, String type, String description, AUserInAServer creator) {
|
||||
return createInfractionWithNotification(target, points, type, description, creator, new HashMap<>(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createInfractionNotification(AUserInAServer aUserInAServer, Long points, String type, String description) {
|
||||
Long serverId = aUserInAServer.getServerReference().getId();
|
||||
Long currentPoints = getActiveInfractionPointsForUser(aUserInAServer);
|
||||
Long newPoints = currentPoints + points;
|
||||
@@ -95,6 +123,8 @@ public class InfractionServiceBean implements InfractionService {
|
||||
.member(MemberDisplay.fromAUserInAServer(aUserInAServer))
|
||||
.newLevel(newLevel)
|
||||
.oldLevel(oldLevel)
|
||||
.type(type)
|
||||
.description(description)
|
||||
.oldPoints(currentPoints)
|
||||
.newPoints(newPoints)
|
||||
.build();
|
||||
@@ -107,6 +137,38 @@ public class InfractionServiceBean implements InfractionService {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> editInfraction(Long infractionId, String newReason, Long serverId) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(infractionId);
|
||||
if(!infraction.getServer().getId().equals(serverId)) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
infraction.setDescription(newReason);
|
||||
return notifyInfractionListeners(infraction);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> notifyInfractionListeners(Infraction infraction) {
|
||||
InfractionDescriptionEventModel model = getInfractionDescriptionModel(infraction);
|
||||
return infractionDescriptionListeners
|
||||
.stream()
|
||||
.filter(listener -> listener.handlesEvent(model))
|
||||
.max(Comparator.comparing(Prioritized::getPriority))
|
||||
.map(listener -> listenerService.executeAsyncFeatureAwareListener(listener, model))
|
||||
.orElse(CompletableFuture.completedFuture(null))
|
||||
.thenApply(defaultListenerResult -> null);
|
||||
}
|
||||
|
||||
private InfractionDescriptionEventModel getInfractionDescriptionModel(Infraction infraction) {
|
||||
return InfractionDescriptionEventModel
|
||||
.builder()
|
||||
.infractionId(infraction.getId())
|
||||
.newDescription(infraction.getDescription())
|
||||
.userId(infraction.getUser().getUserReference().getId())
|
||||
.serverId(infraction.getServer().getId())
|
||||
.type(infraction.getType())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Infraction reloadInfraction(Long infractionId) {
|
||||
return infractionManagementService.loadInfraction(infractionId);
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.KickLogModel;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -27,18 +36,47 @@ public class KickServiceBean implements KickService {
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Autowired
|
||||
private KickServiceBean self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> kickMember(Member member, String reason, KickLogModel kickLogModel) {
|
||||
Guild guild = member.getGuild();
|
||||
log.info("Kicking user {} from guild {}", member.getUser().getIdLong(), guild.getIdLong());
|
||||
CompletableFuture<Void> kickFuture = guild.kick(member, reason).submit();
|
||||
CompletableFuture<Void> logFuture = this.sendKickLog(kickLogModel);
|
||||
return CompletableFuture.allOf(kickFuture, logFuture);
|
||||
CompletableFuture<Message> logFuture = this.sendKickLog(kickLogModel);
|
||||
return CompletableFuture.allOf(kickFuture, logFuture)
|
||||
.thenAccept(unused -> self.storeInfraction(member, reason, kickLogModel, guild, logFuture.join()));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendKickLog(KickLogModel kickLogModel) {
|
||||
@Transactional
|
||||
public CompletableFuture<Long> storeInfraction(Member member, String reason, KickLogModel kickLogModel, Guild guild, Message logMessage) {
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, guild.getIdLong())) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(ModerationFeatureConfig.KICK_INFRACTION_POINTS, guild.getIdLong());
|
||||
AUserInAServer kickedUser = userInServerManagementService.loadOrCreateUser(member);
|
||||
AUserInAServer kickingUser = userInServerManagementService.loadOrCreateUser(kickLogModel.getMember());
|
||||
return infractionService.createInfractionWithNotification(kickedUser, infractionPoints, KICK_INFRACTION_TYPE, reason, kickingUser, logMessage).thenApply(Infraction::getId);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Message> sendKickLog(KickLogModel kickLogModel) {
|
||||
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, kickLogModel.getGuild().getIdLong());
|
||||
log.debug("Sending kick log message in guild {}.", kickLogModel.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures).thenApply(unused -> messageFutures.get(0).join());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.FullUserInServer;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
@@ -10,25 +10,27 @@ 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.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.MutingMode;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.MutingFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.exception.MuteRoleNotSetupException;
|
||||
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.model.database.MuteRole;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteContext;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.UnMuteLog;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteRoleManagementService;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.*;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -45,12 +47,6 @@ import java.util.concurrent.TimeUnit;
|
||||
@Slf4j
|
||||
public class MuteServiceBean implements MuteService {
|
||||
|
||||
@Autowired
|
||||
private MuteRoleManagementService muteRoleManagementService;
|
||||
|
||||
@Autowired
|
||||
private RoleService roleService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@@ -91,51 +87,38 @@ public class MuteServiceBean implements MuteService {
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
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";
|
||||
public static final String MUTE_COUNTER_KEY = "MUTES";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> muteMember(Member memberToMute, Member mutingMember, String reason, Instant unMuteDate, ServerChannelMessage message) {
|
||||
public CompletableFuture<Void> muteMember(Member memberToMute, String reason, Instant unMuteDate, Long channelId) {
|
||||
FullUserInServer mutedUser = FullUserInServer
|
||||
.builder()
|
||||
.aUserInAServer(userInServerManagementService.loadOrCreateUser(memberToMute))
|
||||
.member(memberToMute)
|
||||
.build();
|
||||
|
||||
FullUserInServer mutingUser = FullUserInServer
|
||||
.builder()
|
||||
.aUserInAServer(userInServerManagementService.loadOrCreateUser(mutingMember))
|
||||
.member(mutingMember)
|
||||
.build();
|
||||
return muteUserInServer(mutedUser, mutingUser, reason, unMuteDate, message);
|
||||
return muteUserInServer(mutedUser, reason, unMuteDate, channelId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> muteUserInServer(FullUserInServer userBeingMuted, FullUserInServer userMuting, String reason, Instant unMuteDate, ServerChannelMessage message) {
|
||||
AServer serverBeingMutedIn = userBeingMuted.getAUserInAServer().getServerReference();
|
||||
if(!muteRoleManagementService.muteRoleForServerExists(serverBeingMutedIn)) {
|
||||
log.error("Mute role for server {} has not been setup.", serverBeingMutedIn.getId());
|
||||
throw new MuteRoleNotSetupException();
|
||||
}
|
||||
public CompletableFuture<Void> muteUserInServer(FullUserInServer userBeingMuted, String reason, Instant unMuteDate, Long channelId) {
|
||||
Member memberBeingMuted = userBeingMuted.getMember();
|
||||
log.info("User {} mutes user {} in server {} until {}",
|
||||
memberBeingMuted.getIdLong(), message.getServerId(), userMuting.getMember().getIdLong(), unMuteDate);
|
||||
if(message.getMessageId() != null) {
|
||||
log.info("because of message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
|
||||
} else {
|
||||
log.info("This mute was not triggered by a message.");
|
||||
}
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
AUserInAServer userInServerBeingMuted = userBeingMuted.getAUserInAServer();
|
||||
futures.add(applyMuteRole(userInServerBeingMuted));
|
||||
|
||||
futures.add(memberService.timeoutUser(userBeingMuted.getMember(), unMuteDate));
|
||||
Guild guild = memberBeingMuted.getGuild();
|
||||
if(memberBeingMuted.getVoiceState() != null && memberBeingMuted.getVoiceState().getChannel() != null) {
|
||||
futures.add(guild.kickVoiceMember(memberBeingMuted).submit());
|
||||
@@ -146,17 +129,18 @@ public class MuteServiceBean implements MuteService {
|
||||
.reason(reason)
|
||||
.serverName(guild.getName())
|
||||
.build();
|
||||
futures.add(sendMuteNotification(message, memberBeingMuted, muteNotification));
|
||||
futures.add(sendMuteNotification(memberBeingMuted, muteNotification, channelId));
|
||||
return FutureUtils.toSingleFutureGeneric(futures);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendMuteNotification(ServerChannelMessage message, Member memberBeingMuted, MuteNotification muteNotification) {
|
||||
private CompletableFuture<Void> sendMuteNotification(Member memberBeingMuted, MuteNotification muteNotification, Long channelId) {
|
||||
log.info("Notifying the user about the mute.");
|
||||
CompletableFuture<Void> notificationFuture = new CompletableFuture<>();
|
||||
String muteNotificationMessage = templateService.renderTemplate(MUTE_NOTIFICATION_TEMPLATE, muteNotification, message.getServerId());
|
||||
Long guildId = memberBeingMuted.getGuild().getIdLong();
|
||||
String muteNotificationMessage = templateService.renderTemplate(MUTE_NOTIFICATION_TEMPLATE, muteNotification, guildId);
|
||||
CompletableFuture<Message> messageCompletableFuture = messageService.sendMessageToUser(memberBeingMuted.getUser(), muteNotificationMessage);
|
||||
messageCompletableFuture.exceptionally(throwable -> {
|
||||
GuildMessageChannel feedBackChannel = channelService.getMessageChannelFromServer(message.getServerId(), message.getChannelId());
|
||||
GuildMessageChannel feedBackChannel = channelService.getMessageChannelFromServer(guildId, channelId);
|
||||
channelService.sendTextToChannel(throwable.getMessage(), feedBackChannel).whenComplete((exceptionMessage, innerThrowable) -> {
|
||||
notificationFuture.complete(null);
|
||||
log.info("Successfully notified user {} in server {} about mute.", memberBeingMuted.getId(), memberBeingMuted.getGuild().getId());
|
||||
@@ -172,23 +156,16 @@ public class MuteServiceBean implements MuteService {
|
||||
return notificationFuture;
|
||||
}
|
||||
|
||||
private void createMuteObject(MuteContext muteContext, String triggerKey) {
|
||||
AChannel channel = channelManagementService.loadChannel(muteContext.getContext().getChannelId());
|
||||
private void createMuteObject(MuteContext muteContext, String triggerKey, Long infractionId) {
|
||||
AChannel channel = channelManagementService.loadChannel(muteContext.getChannelId());
|
||||
AServerAChannelMessage origin = AServerAChannelMessage
|
||||
.builder()
|
||||
.channel(channel)
|
||||
.server(channel.getServer())
|
||||
.messageId(muteContext.getContext().getMessageId())
|
||||
.build();
|
||||
AUserInAServer userInServerBeingMuted = userInServerManagementService.loadOrCreateUser(muteContext.getMutedUser());
|
||||
AUserInAServer userInServerMuting = userInServerManagementService.loadOrCreateUser(muteContext.getMutingUser());
|
||||
muteManagementService.createMute(userInServerBeingMuted, userInServerMuting, muteContext.getReason(), muteContext.getMuteTargetDate(), origin, triggerKey, muteContext.getMuteId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> applyMuteRole(AUserInAServer aUserInAServer) {
|
||||
MuteRole muteRole = muteRoleManagementService.retrieveMuteRoleForServer(aUserInAServer.getServerReference());
|
||||
return roleService.addRoleToUserAsync(aUserInAServer, muteRole.getRole());
|
||||
muteManagementService.createMute(userInServerBeingMuted, userInServerMuting, muteContext.getReason(), muteContext.getMuteTargetDate(), origin, triggerKey, muteContext.getMuteId(), infractionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -217,6 +194,7 @@ public class MuteServiceBean implements MuteService {
|
||||
@Override
|
||||
public void cancelUnMuteJob(Mute mute) {
|
||||
if(mute.getTriggerKey() != null) {
|
||||
log.info("Cancelling un-mute job for mute {} in server {}.", mute.getMuteId().getId(), mute.getServer().getId());
|
||||
schedulerService.stopTrigger(mute.getTriggerKey());
|
||||
}
|
||||
}
|
||||
@@ -224,107 +202,116 @@ public class MuteServiceBean implements MuteService {
|
||||
@Override
|
||||
public CompletableFuture<Void> muteMemberWithLog(MuteContext context) {
|
||||
log.debug("Muting member {} in server {}.", context.getMutedUser().getId(), context.getMutedUser().getGuild().getId());
|
||||
AServer server = serverManagementService.loadOrCreate(context.getContext().getServerId());
|
||||
AServer server = serverManagementService.loadOrCreate(context.getMutedUser().getGuild().getIdLong());
|
||||
Long nextCounterValue = counterService.getNextCounterValue(server, MUTE_COUNTER_KEY);
|
||||
context.setMuteId(nextCounterValue);
|
||||
CompletableFuture<Void> mutingFuture = muteMember(context.getMutedUser(), context.getMutingUser(), context.getReason(), context.getMuteTargetDate(), context.getContext());
|
||||
CompletableFuture<Void> muteLogFuture = sendMuteLog(context, server);
|
||||
return CompletableFuture.allOf(mutingFuture, muteLogFuture).thenAccept(aVoid ->
|
||||
self.persistMute(context)
|
||||
);
|
||||
return muteMember(context.getMutedUser(), context.getReason(), context.getMuteTargetDate(), context.getChannelId())
|
||||
.thenCompose(unused -> self.sendMuteLog(context))
|
||||
.thenCompose(logMessage -> self.evaluateAndStoreInfraction(context, logMessage))
|
||||
.thenAccept(infractionId -> self.persistMute(context, infractionId));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistMute(MuteContext context) {
|
||||
String triggerKey = startUnMuteJobFor(context.getMuteTargetDate(), context.getMuteId(), context.getContext().getServerId());
|
||||
createMuteObject(context, triggerKey);
|
||||
public CompletableFuture<Long> evaluateAndStoreInfraction(MuteContext context, Message logMessage) {
|
||||
Guild guild = context.getMutedUser().getGuild();
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, guild.getIdLong())) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(MutingFeatureConfig.MUTE_INFRACTION_POINTS, guild.getIdLong());
|
||||
AUserInAServer mutedUser = userInServerManagementService.loadOrCreateUser(context.getMutedUser());
|
||||
AUserInAServer mutingUser = userInServerManagementService.loadOrCreateUser(context.getMutingUser());
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put(INFRACTION_PARAMETER_DURATION_KEY, templateService.renderDuration(Duration.between(Instant.now(), context.getMuteTargetDate()), guild.getIdLong()));
|
||||
return infractionService.createInfractionWithNotification(mutedUser, infractionPoints, MUTE_INFRACTION_TYPE, context.getReason(), mutingUser, parameters, logMessage)
|
||||
.thenApply(Infraction::getId);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendMuteLog(MuteContext muteLogModel, AServer server) {
|
||||
@Transactional
|
||||
public void persistMute(MuteContext context, Long infractionId) {
|
||||
completelyUnMuteMember(context.getMutedUser());
|
||||
String triggerKey = startUnMuteJobFor(context.getMuteTargetDate(), context.getMuteId(), context.getMutedUser().getGuild().getIdLong());
|
||||
createMuteObject(context, triggerKey, infractionId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Message> sendMuteLog(MuteContext muteLogModel) {
|
||||
MuteListenerModel model = MuteListenerModel
|
||||
.builder()
|
||||
.mutedUser(muteLogModel.getMutedUser())
|
||||
.mutingUser(muteLogModel.getMutingUser())
|
||||
.channelId(muteLogModel.getChannelId())
|
||||
.oldMuteTargetDate(null)
|
||||
.muteTargetDate(muteLogModel.getMuteTargetDate())
|
||||
.reason(muteLogModel.getReason())
|
||||
.build();
|
||||
log.debug("Sending mute log to the mute post target.");
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()));
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, model, muteLogModel.getMutedUser().getIdLong());
|
||||
List<CompletableFuture<Message>> futures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getMutedUser().getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(futures).thenApply(unused -> futures.get(0).join());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) {
|
||||
log.debug("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, server.getId());
|
||||
MuteListenerModel model = MuteListenerModel
|
||||
.builder()
|
||||
.mutedUser(muteLogModel.getUnMutedUser())
|
||||
.mutingUser(muteLogModel.getMutingUser())
|
||||
.oldMuteTargetDate(muteLogModel.getMute() != null ? muteLogModel.getMute().getMuteTargetDate() : null)
|
||||
.muteTargetDate(null)
|
||||
.build();
|
||||
if(muteLogModel.getMute() != null) {
|
||||
log.debug("Sending unMute log for mute {} to the mute posttarget in server {}", muteLogModel.getMute().getMuteId().getId(), server.getId());
|
||||
}
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, model, server.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CompletableFuture<Void> unMuteUser(AUserInAServer aUserInAServer) {
|
||||
if(!muteManagementService.hasActiveMute(aUserInAServer)) {
|
||||
throw new NoMuteFoundException();
|
||||
}
|
||||
Mute mute = muteManagementService.getAMuteOf(aUserInAServer);
|
||||
Long muteId = mute.getMuteId().getId();
|
||||
CompletableFuture<Member> mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser());
|
||||
CompletableFuture<Member> mutedMemberFuture = memberService.getMemberInServerAsync(mute.getMutedUser());
|
||||
Guild guild = guildService.getGuildById(mute.getMuteId().getServerId());
|
||||
return endMute(mute, false).thenCompose(unused ->
|
||||
CompletableFuture.allOf(mutingMemberFuture, mutedMemberFuture)
|
||||
).thenCompose(unused -> self.sendUnMuteLogForManualUnMute(muteId, mutingMemberFuture, mutedMemberFuture, guild));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> sendUnMuteLogForManualUnMute(Long muteId, CompletableFuture<Member> mutingMemberFuture, CompletableFuture<Member> mutedMemberFuture, Guild guild) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
if(featureModeService.featureModeActive(ModerationFeatureDefinition.MUTING, guild.getIdLong(), MutingMode.MANUAL_UN_MUTE_LOGGING)) {
|
||||
completableFuture = self.sendUnmuteLog(muteId, guild, mutingMemberFuture, mutedMemberFuture);
|
||||
log.info("Sending un mute notification for manual un mute for mute {} in server {}.", muteId, guild.getIdLong());
|
||||
public CompletableFuture<Void> unMuteUser(AUserInAServer userToUnmute, Member unMutingMember) {
|
||||
boolean muteActive = muteManagementService.hasActiveMute(userToUnmute);
|
||||
if(!muteActive) {
|
||||
CompletableFuture<Member> unMutedMemberFuture = memberService.retrieveMemberInServer(ServerUser.fromAUserInAServer(userToUnmute));
|
||||
return unMutedMemberFuture
|
||||
.thenCompose(member -> memberService.removeTimeout(member))
|
||||
.thenCompose(unused -> self.sendUnmuteLog(null, unMutingMember.getGuild(), unMutedMemberFuture.join(), unMutingMember));
|
||||
} else {
|
||||
completableFuture = CompletableFuture.completedFuture(null);
|
||||
log.info("Not sending unMute log, because feature mode {} in feature {} has been disabled for server {}.", MutingMode.MANUAL_UN_MUTE_LOGGING, ModerationFeatureDefinition.WARNING, guild.getIdLong());
|
||||
Mute mute = muteManagementService.getAMuteOf(userToUnmute);
|
||||
return endMute(mute);
|
||||
}
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> endMute(Mute mute, Boolean sendNotification) {
|
||||
public CompletableFuture<Void> endMute(Mute mute) {
|
||||
if(mute.getMuteEnded()) {
|
||||
log.info("Mute {} in server {} has already ended. Not unmuting.", mute.getMuteId().getId(), mute.getMuteId().getServerId());
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
Long muteId = mute.getMuteId().getId();
|
||||
Long serverId = mute.getMuteId().getServerId();
|
||||
Guild guild = guildService.getGuildById(mute.getMuteId().getServerId());
|
||||
AServer mutingServer = mute.getServer();
|
||||
log.info("UnMuting {} in server {}", mute.getMutedUser().getUserReference().getId(), mutingServer.getId());
|
||||
MuteRole muteRole = muteRoleManagementService.retrieveMuteRoleForServer(mutingServer);
|
||||
log.debug("Using the mute role {} mapping to role {}", muteRole.getId(), muteRole.getRole().getId());
|
||||
Guild guild = guildService.getGuildById(mutingServer.getId());
|
||||
CompletableFuture<Void> roleRemovalFuture = roleService.removeRoleFromUserAsync(mute.getMutedUser(), muteRole.getRole());
|
||||
CompletableFuture<Member> mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser());
|
||||
CompletableFuture<Member> mutedMemberFuture = memberService.getMemberInServerAsync(mute.getMutedUser());
|
||||
CompletableFuture<Void> finalFuture = new CompletableFuture<>();
|
||||
CompletableFuture.allOf(mutingMemberFuture, mutedMemberFuture, roleRemovalFuture, mutingMemberFuture, mutedMemberFuture).handle((aVoid, throwable) -> {
|
||||
if(sendNotification) {
|
||||
self.sendUnmuteLog(muteId, guild, mutingMemberFuture, mutedMemberFuture).thenAccept(aVoid1 ->
|
||||
finalFuture.complete(null)
|
||||
).exceptionally(throwable1 -> {
|
||||
log.error("Unmute log failed to send for mute {} in server {}.", muteId, serverId, throwable1);
|
||||
finalFuture.completeExceptionally(null);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
finalFuture.complete(null);
|
||||
}
|
||||
return null;
|
||||
}).exceptionally(throwable -> {
|
||||
finalFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return finalFuture;
|
||||
CompletableFuture<Member> mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser());
|
||||
return CompletableFuture.allOf(mutedMemberFuture, mutingMemberFuture)
|
||||
.thenAccept(member -> memberService.removeTimeout(mutedMemberFuture.join()))
|
||||
.thenCompose(unused -> self.sendUnmuteLog(muteId, guild, mutingMemberFuture, mutedMemberFuture));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> sendUnmuteLog(Long muteId, Guild guild, CompletableFuture<Member> mutingMemberFuture, CompletableFuture<Member> mutedMemberFuture) {
|
||||
Mute mute = muteManagementService.findMute(muteId, guild.getIdLong());
|
||||
AServer mutingServer = serverManagementService.loadServer(guild.getIdLong());
|
||||
Member mutingMember = !mutingMemberFuture.isCompletedExceptionally() ? mutingMemberFuture.join() : null;
|
||||
Member mutedMember = !mutedMemberFuture.isCompletedExceptionally() ? mutedMemberFuture.join() : null;
|
||||
return sendUnmuteLog(muteId, guild, mutedMember, mutingMember);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> sendUnmuteLog(Long muteId, Guild guild, Member mutedMember, Member mutingMember) {
|
||||
Mute mute = null;
|
||||
if(muteId != null) {
|
||||
mute = muteManagementService.findMute(muteId, guild.getIdLong());
|
||||
}
|
||||
AServer mutingServer = serverManagementService.loadServer(guild.getIdLong());
|
||||
UnMuteLog unMuteLog = UnMuteLog
|
||||
.builder()
|
||||
.mute(mute)
|
||||
@@ -333,9 +320,11 @@ public class MuteServiceBean implements MuteService {
|
||||
.guild(guild)
|
||||
.build();
|
||||
CompletableFuture<Void> notificationFuture = sendUnMuteLogMessage(unMuteLog, mutingServer);
|
||||
return CompletableFuture.allOf(notificationFuture).thenAccept(aVoid ->
|
||||
self.endMuteInDatabase(muteId, guild.getIdLong())
|
||||
);
|
||||
return CompletableFuture.allOf(notificationFuture).thenAccept(aVoid -> {
|
||||
if(muteId != null) {
|
||||
self.endMuteInDatabase(muteId, guild.getIdLong());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -344,7 +333,6 @@ public class MuteServiceBean implements MuteService {
|
||||
muteOptional.ifPresent(mute ->
|
||||
completelyUnMuteUser(mute.getMutedUser())
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -353,7 +341,7 @@ public class MuteServiceBean implements MuteService {
|
||||
log.info("UnMuting the mute {} in server {}", muteId, serverId);
|
||||
Optional<Mute> muteOptional = muteManagementService.findMuteOptional(muteId, serverId);
|
||||
if(muteOptional.isPresent()) {
|
||||
return endMute(muteOptional.get(), true);
|
||||
return endMute(muteOptional.get());
|
||||
} else {
|
||||
throw new NoMuteFoundException();
|
||||
}
|
||||
@@ -375,10 +363,4 @@ public class MuteServiceBean implements MuteService {
|
||||
completelyUnMuteUser(userInServerManagementService.loadOrCreateUser(member));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> muteMemberWithoutContext(Member member) {
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
return applyMuteRole(aUserInAServer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,14 +3,15 @@ package dev.sheldan.abstracto.moderation.service;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.ReportReactionMode;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.ReactionReportPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.ReportMessageCreatedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.ModerationUser;
|
||||
import dev.sheldan.abstracto.moderation.model.database.ReactionReport;
|
||||
import dev.sheldan.abstracto.moderation.model.template.listener.ReportReactionNotificationModel;
|
||||
@@ -19,7 +20,6 @@ import dev.sheldan.abstracto.moderation.service.management.ReactionReportManagem
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.TextChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -59,46 +59,60 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
||||
@Autowired
|
||||
private ReactionReportServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private CacheEntityService cacheEntityService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private ReportMessageCreatedListenerManager reportMessageCreatedListenerManager;
|
||||
|
||||
private static final String REACTION_REPORT_TEMPLATE_KEY = "reactionReport_notification";
|
||||
public static final String REACTION_REPORT_MODAL_ORIGIN = "reportMessageModal";
|
||||
public static final String REACTION_REPORT_RESPONSE_TEMPLATE = "reactionReport_response";
|
||||
public static final String REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE = "reactionReport_cooldown_response";
|
||||
public static final String REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE = "reactionReport_own_message_response";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createReactionReport(CachedMessage reportedMessage, ServerUser reporter) {
|
||||
public CompletableFuture<Void> createReactionReport(CachedMessage reportedMessage, ServerUser reporter, String context) {
|
||||
AUserInAServer reportedUser = userInServerManagementService.loadOrCreateUser(reportedMessage.getAuthorAsServerUser());
|
||||
AUserInAServer reportingUser = userInServerManagementService.loadOrCreateUser(reporter);
|
||||
Optional<ModerationUser> moderationUserOptional = moderationUserManagementService.findModerationUser(reportingUser);
|
||||
Long serverId = reporter.getServerId();
|
||||
log.info("User {} in server {} was reported on message {}", reportedMessage.getAuthor().getAuthorId(), serverId, reportedMessage.getMessageId());
|
||||
Long cooldownSeconds = configService.getLongValueOrConfigDefault(REACTION_REPORT_COOLDOWN, serverId);
|
||||
Duration maxAge = Duration.of(cooldownSeconds, ChronoUnit.SECONDS);
|
||||
if(moderationUserOptional.isPresent()) {
|
||||
ModerationUser reporterModerationUser = moderationUserOptional.get();
|
||||
Instant minAllowedReportTime = Instant.now().minus(maxAge);
|
||||
if(reporterModerationUser.getLastReportTimeStamp() != null && reporterModerationUser.getLastReportTimeStamp().isAfter(minAllowedReportTime)) {
|
||||
log.info("User {} in server {} reported user {} within the cooldown. Ignoring.", reporter.getUserId(), serverId, reportedMessage.getAuthor().getAuthorId());
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
log.info("User {} in server {} reported user {}..", reporter.getUserId(), serverId, reportedMessage.getAuthor().getAuthorId());
|
||||
Optional<ReactionReport> recentReportOptional = reactionReportManagementService.findRecentReactionReportAboutUser(reportedUser, maxAge);
|
||||
if(!recentReportOptional.isPresent()) {
|
||||
ReportReactionNotificationModel model = ReportReactionNotificationModel
|
||||
.builder()
|
||||
.reportCount(1)
|
||||
.reportedMessage(reportedMessage)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(REACTION_REPORT_TEMPLATE_KEY, model, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, ReactionReportPostTarget.REACTION_REPORTS, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures)
|
||||
.thenAccept(unused -> self.createReactionReportInDb(reportedMessage, messageFutures.get(0).join(), reporter));
|
||||
} else {
|
||||
boolean singularMessage = featureModeService.featureModeActive(ModerationFeatureDefinition.REPORT_REACTIONS, serverId, ReportReactionMode.SINGULAR_MESSAGE);
|
||||
boolean anonym = featureModeService.featureModeActive(ModerationFeatureDefinition.REPORT_REACTIONS, reporter.getServerId(), ReportReactionMode.ANONYMOUS);
|
||||
if(recentReportOptional.isPresent() && singularMessage) {
|
||||
ReactionReport report = recentReportOptional.get();
|
||||
log.info("Report is already present in channel {} with message {}. Updating field.", report.getReportChannel().getId(), report.getReportMessageId());
|
||||
report.setReportCount(report.getReportCount() + 1);
|
||||
GuildMessageChannel reportTextChannel = channelService.getMessageChannelFromServer(serverId, report.getReportChannel().getId());
|
||||
return channelService.editFieldValueInMessage(reportTextChannel, report.getReportMessageId(), 0, report.getReportCount().toString())
|
||||
.thenAccept(message -> self.updateModerationUserReportCooldown(reporter));
|
||||
} else {
|
||||
ReportReactionNotificationModel model = ReportReactionNotificationModel
|
||||
.builder()
|
||||
.reportCount(1)
|
||||
.context(context)
|
||||
.singularMessage(singularMessage)
|
||||
.reportedMessage(reportedMessage)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(REACTION_REPORT_TEMPLATE_KEY, model, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, ReactionReportPostTarget.REACTION_REPORTS, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures)
|
||||
.thenAccept(unused -> reportMessageCreatedListenerManager.sendReportMessageCreatedEvent(reportedMessage, messageFutures.get(0).join(), anonym ? null : reporter))
|
||||
.thenAccept(unused -> self.createReactionReportInDb(reportedMessage, messageFutures.get(0).join(), reporter));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createReactionReport(Message message, ServerUser reporter, String context) {
|
||||
return cacheEntityService.buildCachedMessageFromMessage(message)
|
||||
.thenCompose(cachedMessage -> createReactionReport(cachedMessage, reporter, context));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser reporter) {
|
||||
if(reportMessage == null) {
|
||||
@@ -112,15 +126,35 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
||||
|
||||
@Transactional
|
||||
public void updateModerationUserReportCooldown(ServerUser reporter) {
|
||||
AUserInAServer reporterAUserInServer = userInServerManagementService.loadOrCreateUser(reporter);
|
||||
Optional<ModerationUser> optionalModerationUser = moderationUserManagementService.findModerationUser(reporterAUserInServer);
|
||||
Instant reportTimeStamp = Instant.now();
|
||||
if(optionalModerationUser.isPresent()) {
|
||||
log.info("Updating last report time of user {}.", reporter.getUserId());
|
||||
optionalModerationUser.get().setLastReportTimeStamp(reportTimeStamp);
|
||||
} else {
|
||||
log.info("Creating new moderation user instance for user {} to track report cooldowns.", reporter.getUserId());
|
||||
moderationUserManagementService.createModerationUserWithReportTimeStamp(reporterAUserInServer, reportTimeStamp);
|
||||
if(!featureModeService.featureModeActive(ModerationFeatureDefinition.REPORT_REACTIONS, reporter.getServerId(), ReportReactionMode.ANONYMOUS)) {
|
||||
AUserInAServer reporterAUserInServer = userInServerManagementService.loadOrCreateUser(reporter);
|
||||
Optional<ModerationUser> optionalModerationUser = moderationUserManagementService.findModerationUser(reporterAUserInServer);
|
||||
Instant reportTimeStamp = Instant.now();
|
||||
if(optionalModerationUser.isPresent()) {
|
||||
log.info("Updating last report time of user {}.", reporter.getUserId());
|
||||
optionalModerationUser.get().setLastReportTimeStamp(reportTimeStamp);
|
||||
} else {
|
||||
log.info("Creating new moderation user instance for user {} to track report cooldowns.", reporter.getUserId());
|
||||
moderationUserManagementService.createModerationUserWithReportTimeStamp(reporterAUserInServer, reportTimeStamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowedToReport(ServerUser reporter) {
|
||||
Long cooldownSeconds = configService.getLongValueOrConfigDefault(REACTION_REPORT_COOLDOWN, reporter.getServerId());
|
||||
Duration maxAge = Duration.of(cooldownSeconds, ChronoUnit.SECONDS);
|
||||
AUserInAServer reportingUser = userInServerManagementService.loadOrCreateUser(reporter);
|
||||
Optional<ModerationUser> moderationUserOptional = moderationUserManagementService.findModerationUser(reportingUser);
|
||||
if(moderationUserOptional.isPresent()) {
|
||||
ModerationUser reporterModerationUser = moderationUserOptional.get();
|
||||
Instant minAllowedReportTime = Instant
|
||||
.now()
|
||||
.minus(maxAge);
|
||||
if(reporterModerationUser.getLastReportTimeStamp() != null) {
|
||||
return !reporterModerationUser.getLastReportTimeStamp().isAfter(minAllowedReportTime);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,8 @@ public class WarnServiceBean implements WarnService {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> notifyAndLogFullUserWarning(WarnContext context) {
|
||||
AServer server = serverManagementService.loadOrCreate(context.getGuild().getIdLong());
|
||||
Long warningId = counterService.getNextCounterValue(server, WARNINGS_COUNTER_KEY);
|
||||
Long serverId = context.getGuild().getIdLong();
|
||||
Long warningId = counterService.getNextCounterValue(serverId, WARNINGS_COUNTER_KEY);
|
||||
context.setWarnId(warningId);
|
||||
Member warnedMember = context.getWarnedMember();
|
||||
Member warningMember = context.getMember();
|
||||
@@ -124,29 +124,39 @@ public class WarnServiceBean implements WarnService {
|
||||
.warnId(warningId)
|
||||
.serverName(guild.getName())
|
||||
.build();
|
||||
Long serverId = server.getId();
|
||||
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification, server.getId());
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
CompletableFuture<Void> notificationFuture = new CompletableFuture<>();
|
||||
messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage).whenComplete((message, throwable) -> {
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to notify user {} of warning {} in guild {}.", warnedMember.getId(), warningId, serverId);
|
||||
}
|
||||
notificationFuture.complete(null);
|
||||
});
|
||||
futures.add(notificationFuture);
|
||||
log.debug("Logging warning for server {}.", server.getId());
|
||||
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification, serverId);
|
||||
return messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage)
|
||||
.exceptionally(throwable -> {
|
||||
log.warn("Failed to notify user {} of warning {} in guild {}.", warnedMember.getId(), warningId, serverId);
|
||||
return null;
|
||||
})
|
||||
.thenCompose(message -> self.sendWarningLog(context))
|
||||
.thenCompose(logMessage -> self.evaluateInfraction(context, logMessage))
|
||||
.thenAccept(context::setInfractionId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Message> sendWarningLog(WarnContext context) {
|
||||
MessageToSend message = renderMessageModel(context);
|
||||
List<CompletableFuture<Message>> futures = postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(futures).thenCompose(unused -> futures.get(0));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Long> evaluateInfraction(WarnContext context, Message logMessage) {
|
||||
Long serverId = context.getGuild().getIdLong();
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, serverId)) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(WarningFeatureConfig.WARN_INFRACTION_POINTS, serverId);
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(warnedMember);
|
||||
warnedUser.setServerReference(server);
|
||||
futures.add(infractionService.createInfractionWithNotification(warnedUser, infractionPoints)
|
||||
.thenAccept(infraction -> context.setInfractionId(infraction.getId())));
|
||||
AServer server = serverManagementService.loadServer(context.getGuild());
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(server, context.getWarnedMember().getIdLong());
|
||||
AUserInAServer warningUser = userInServerManagementService.loadOrCreateUser(server, context.getMember().getIdLong());
|
||||
// both user could create the server object, we need to make sure we have the same reference
|
||||
warnedUser.setServerReference(warningUser.getServerReference());
|
||||
return infractionService.createInfractionWithNotification(warnedUser, infractionPoints, WARN_INFRACTION_TYPE, context.getReason(), warningUser, logMessage)
|
||||
.thenApply(Infraction::getId);
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context, server.getId());
|
||||
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
||||
|
||||
return FutureUtils.toSingleFuture(futures);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -298,6 +308,10 @@ public class WarnServiceBean implements WarnService {
|
||||
}
|
||||
}
|
||||
|
||||
public MessageToSend renderMessageModel(WarnContext warnContext) {
|
||||
return templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, warnContext, warnContext.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
||||
log.debug("Loading members decaying {} warnings in server {}.", warningsToDecay.size(), server.getId());
|
||||
HashMap<ServerSpecificId, FutureMemberPair> warningMembers = new HashMap<>();
|
||||
|
||||
@@ -1,25 +1,44 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.repository.InfractionRepository;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class InfractionManagementServiceBean implements InfractionManagementService{
|
||||
public class InfractionManagementServiceBean implements InfractionManagementService {
|
||||
|
||||
@Autowired
|
||||
private InfractionRepository infractionRepository;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public Infraction createInfraction(AUserInAServer aUserInAServer, Long points) {
|
||||
public Infraction createInfraction(AUserInAServer target, Long points, String type, String description, AUserInAServer creator, Message message) {
|
||||
AChannel channel;
|
||||
if(message != null) {
|
||||
channel = channelManagementService.loadChannel(message.getChannel().getIdLong());
|
||||
} else {
|
||||
channel = null;
|
||||
}
|
||||
Infraction infraction = Infraction
|
||||
.builder()
|
||||
.user(aUserInAServer)
|
||||
.server(aUserInAServer.getServerReference())
|
||||
.user(target)
|
||||
.infractionCreator(creator)
|
||||
.server(target.getServerReference())
|
||||
.decayed(false)
|
||||
.logChannel(channel)
|
||||
.logMessageId(message != null ? message.getIdLong() : null)
|
||||
.type(type)
|
||||
.description(description)
|
||||
.points(points)
|
||||
.build();
|
||||
return infractionRepository.save(infraction);
|
||||
@@ -30,6 +49,16 @@ public class InfractionManagementServiceBean implements InfractionManagementServ
|
||||
return infractionRepository.findByUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Infraction> getInfractionsForUser(AUserInAServer aUserInAServer) {
|
||||
return infractionRepository.findByUserOrderByCreated(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Infraction> getInfractionsForServer(AServer server) {
|
||||
return infractionRepository.findByServerOrderByCreated(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Infraction loadInfraction(Long infraction) {
|
||||
return infractionRepository.getOne(infraction);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.InfractionParameter;
|
||||
import dev.sheldan.abstracto.moderation.model.database.embedded.InfractionParameterId;
|
||||
import dev.sheldan.abstracto.moderation.repository.InfractionParameterRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class InfractionParameterManagementServiceBean implements InfractionParameterManagementService{
|
||||
|
||||
@Autowired
|
||||
private InfractionParameterRepository infractionParameterRepository;
|
||||
|
||||
@Override
|
||||
public InfractionParameter createInfractionParameter(Infraction infraction, String key, String value) {
|
||||
InfractionParameterId id = new InfractionParameterId(infraction.getId(), key);
|
||||
InfractionParameter parameter = InfractionParameter
|
||||
.builder()
|
||||
.infractionParameterId(id)
|
||||
.value(value)
|
||||
.infraction(infraction)
|
||||
.build();
|
||||
return infractionParameterRepository.save(parameter);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.repository.MuteRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -27,11 +29,20 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Override
|
||||
public Mute createMute(AUserInAServer mutedUser, AUserInAServer mutingUser, String reason, Instant unMuteDate, AServerAChannelMessage muteMessage, String triggerKey, Long muteId) {
|
||||
public Mute createMute(AUserInAServer mutedUser, AUserInAServer mutingUser, String reason, Instant unMuteDate, AServerAChannelMessage muteMessage, String triggerKey, Long muteId, Long infractionId) {
|
||||
log.debug("Creating mute for user {} executed by user {} in server {}, user will be un-muted at {}",
|
||||
mutedUser.getUserReference().getId(), mutingUser.getUserReference().getId(), mutedUser.getServerReference().getId(), unMuteDate);
|
||||
ServerSpecificId id = new ServerSpecificId(muteMessage.getServer().getId(), muteId);
|
||||
Infraction infraction;
|
||||
if(infractionId != null) {
|
||||
infraction = infractionManagementService.loadInfraction(infractionId);
|
||||
} else {
|
||||
infraction = null;
|
||||
}
|
||||
ServerSpecificId id = new ServerSpecificId(mutedUser.getServerReference().getId(), muteId);
|
||||
Mute mute = Mute
|
||||
.builder()
|
||||
.mutedUser(mutedUser)
|
||||
@@ -41,6 +52,7 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
.mutingChannel(muteMessage.getChannel())
|
||||
.messageId(muteMessage.getMessageId())
|
||||
.reason(reason)
|
||||
.infraction(infraction)
|
||||
.triggerKey(triggerKey)
|
||||
.muteId(id)
|
||||
.muteEnded(false)
|
||||
@@ -76,6 +88,11 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
|
||||
@Override
|
||||
public Mute getAMuteOf(AUserInAServer userInAServer) {
|
||||
return getAMuteOfOptional(userInAServer).orElseThrow(NoMuteFoundException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Mute> getAMuteOfOptional(AUserInAServer userInAServer) {
|
||||
return muteRepository.findTopByMutedUserAndMuteEndedFalse(userInAServer);
|
||||
}
|
||||
|
||||
@@ -84,6 +101,11 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
return getAMuteOf(userInServerManagementService.loadOrCreateUser(member));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Mute> getAMuteOfOptional(Member member) {
|
||||
return getAMuteOfOptional(userInServerManagementService.loadOrCreateUser(member));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mute> getAllActiveMutesOf(AUserInAServer aUserInAServer) {
|
||||
return muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(aUserInAServer);
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.MuteRole;
|
||||
import dev.sheldan.abstracto.moderation.repository.MuteRoleRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class MuteRoleManagementServiceBean implements MuteRoleManagementService {
|
||||
|
||||
@Autowired
|
||||
private MuteRoleRepository muteRoleRepository;
|
||||
|
||||
@Override
|
||||
public MuteRole retrieveMuteRoleForServer(AServer server) {
|
||||
return muteRoleRepository.findByRoleServer(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuteRole createMuteRoleForServer(AServer server, ARole role) {
|
||||
log.debug("Creating mute role for server {} to be role {}", server.getId(), role.getId());
|
||||
MuteRole muteRole = MuteRole
|
||||
.builder()
|
||||
.role(role)
|
||||
.roleServer(server)
|
||||
.build();
|
||||
return muteRoleRepository.save(muteRole);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MuteRole> retrieveMuteRolesForServer(AServer server) {
|
||||
return muteRoleRepository.findAllByRoleServer(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MuteRole setMuteRoleForServer(AServer server, ARole role) {
|
||||
log.info("Setting muted role for server {} to role {}", server.getId(), role.getId());
|
||||
if(!muteRoleForServerExists(server)) {
|
||||
log.debug("Mute role did not exist yet, updating for server {}.", server.getId());
|
||||
return createMuteRoleForServer(server, role);
|
||||
} else {
|
||||
MuteRole existing = retrieveMuteRoleForServer(server);
|
||||
log.debug("Updating mute role for server {} to be role {} instead.", server.getId(), role.getId());
|
||||
existing.setRole(role);
|
||||
return existing;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean muteRoleForServerExists(AServer server) {
|
||||
return muteRoleRepository.existsByRoleServer(server);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@@ -30,7 +31,8 @@ public class ReactionReportManagementServiceBean implements ReactionReportManage
|
||||
@Override
|
||||
public Optional<ReactionReport> findRecentReactionReportAboutUser(AUserInAServer aUserInAServer, Duration maxAge) {
|
||||
Instant maxCreation = Instant.now().minus(maxAge);
|
||||
return repository.findByReportedUserAndCreatedLessThan(aUserInAServer, maxCreation);
|
||||
List<ReactionReport> foundReports = repository.findByReportedUserAndCreatedLessThan(aUserInAServer, maxCreation);
|
||||
return foundReports.isEmpty() ? Optional.empty() : Optional.of(foundReports.get(0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -104,5 +104,10 @@ public class WarnManagementServiceBean implements WarnManagementService {
|
||||
warnRepository.delete(warning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Warning> findWarnByInfraction(Long infractionId) {
|
||||
return warnRepository.findByInfraction_Id(infractionId);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="moderationModule" value="(SELECT id FROM module WHERE name = 'moderation')"/>
|
||||
<property name="infractionsFeature" value="(SELECT id FROM feature WHERE key = 'infractions')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="moderation_infraction-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="infractions"/>
|
||||
<column name="module_id" valueComputed="${moderationModule}"/>
|
||||
<column name="feature_id" valueComputed="${infractionsFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="editInfraction"/>
|
||||
<column name="module_id" valueComputed="${moderationModule}"/>
|
||||
<column name="feature_id" valueComputed="${infractionsFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="Sheldan" id="moderation_setMuteRole-cleanup">
|
||||
<delete tableName="command_in_server_allowed_role">
|
||||
<where>command_in_server_id in (select cs.command_in_server_id from command_in_server cs inner join command c on c.id = cs.command_id and c.name = 'setMuteRole') </where>
|
||||
</delete>
|
||||
<delete tableName="command_in_server_alias">
|
||||
<where>command_in_server_id in (select cs.command_in_server_id from command_in_server cs inner join command c on c.id = cs.command_id and c.name = 'setMuteRole') </where>
|
||||
</delete>
|
||||
<delete tableName="command_in_server">
|
||||
<where>command_id=(select id from command where name = 'setMuteRole')</where>
|
||||
</delete>
|
||||
<delete tableName="command">
|
||||
<where>name='setMuteRole'</where>
|
||||
</delete>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="moderationFeature" value="(SELECT id FROM feature WHERE key = 'moderation')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="moderation_context_command">
|
||||
<insert tableName="context_command">
|
||||
<column name="name" value="report_message"/>
|
||||
<column name="type" value="MESSAGE"/>
|
||||
<column name="feature_id" valueComputed="${moderationFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="context_command">
|
||||
<column name="name" value="report_message_context"/>
|
||||
<column name="type" value="MESSAGE"/>
|
||||
<column name="feature_id" valueComputed="${moderationFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="context_command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="feature_mode.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
|
||||
<changeSet author="Sheldan" id="delete_manual_unmuting_log_feature_mode">
|
||||
<delete tableName="feature_mode">
|
||||
<where>feature_mode='manualUnMuteLogging'</where>
|
||||
</delete>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="infraction-type-description">
|
||||
<addColumn tableName="infraction">
|
||||
<column name="type" type="VARCHAR(32)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(2048)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="log_message_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="log_channel_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="infraction_creator_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<addNotNullConstraint columnName="decayed"
|
||||
tableName="infraction"
|
||||
validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_creator_user_in_server_id" baseTableName="infraction" constraintName="fk_infraction_creator_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="log_channel_id" baseTableName="infraction" constraintName="fk_infraction_log_channel"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="channel" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="infraction_parameter-table">
|
||||
<createTable tableName="infraction_parameter">
|
||||
<column name="key" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="value" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="infraction_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<addPrimaryKey columnNames="infraction_id, key" tableName="infraction_parameter" constraintName="pk_infraction_parameter" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_id" baseTableName="infraction_parameter" constraintName="fk_infraction_parameter_infraction"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="infraction" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="mute-infraction_id">
|
||||
<addColumn tableName="mute">
|
||||
<column name="infraction_id" type="BIGINT" />
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_id" baseTableName="mute" constraintName="fk_mute_infraction"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="infraction" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="infraction.xml" relativeToChangelogFile="true"/>
|
||||
<include file="infraction_parameter.xml" relativeToChangelogFile="true"/>
|
||||
<include file="mute.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -13,4 +13,5 @@
|
||||
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.10/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.0/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -49,6 +49,14 @@ abstracto.featureModes.infractionReporting.featureName=infractions
|
||||
abstracto.featureModes.infractionReporting.mode=infractionReporting
|
||||
abstracto.featureModes.infractionReporting.enabled=true
|
||||
|
||||
abstracto.featureModes.anonymousReportReactions.featureName=reportReactions
|
||||
abstracto.featureModes.anonymousReportReactions.mode=anonymousReportReactions
|
||||
abstracto.featureModes.anonymousReportReactions.enabled=false
|
||||
|
||||
abstracto.featureModes.singularReportReactions.featureName=reportReactions
|
||||
abstracto.featureModes.singularReportReactions.mode=singularReportReactions
|
||||
abstracto.featureModes.singularReportReactions.enabled=false
|
||||
|
||||
abstracto.systemConfigs.infractionLvl1.name=infractionLvl1
|
||||
abstracto.systemConfigs.infractionLvl1.longValue=10
|
||||
|
||||
@@ -68,7 +76,16 @@ abstracto.systemConfigs.infractionLevels.name=infractionLevels
|
||||
abstracto.systemConfigs.infractionLevels.longValue=5
|
||||
|
||||
abstracto.systemConfigs.warnInfractionPoints.name=warnInfractionPoints
|
||||
abstracto.systemConfigs.warnInfractionPoints.longValue=0
|
||||
abstracto.systemConfigs.warnInfractionPoints.longValue=50
|
||||
|
||||
abstracto.systemConfigs.banInfractionPoints.name=banInfractionPoints
|
||||
abstracto.systemConfigs.banInfractionPoints.longValue=150
|
||||
|
||||
abstracto.systemConfigs.kickInfractionPoints.name=kickInfractionPoints
|
||||
abstracto.systemConfigs.kickInfractionPoints.longValue=20
|
||||
|
||||
abstracto.systemConfigs.muteInfractionPoints.name=muteInfractionPoints
|
||||
abstracto.systemConfigs.muteInfractionPoints.longValue=10
|
||||
|
||||
abstracto.featureModes.automaticWarnDecayLogging.featureName=warnDecay
|
||||
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
||||
@@ -78,6 +95,3 @@ abstracto.featureModes.notifyMemberWarningDecays.featureName=warnDecay
|
||||
abstracto.featureModes.notifyMemberWarningDecays.mode=notifyMemberWarningDecays
|
||||
abstracto.featureModes.notifyMemberWarningDecays.enabled=true
|
||||
|
||||
abstracto.featureModes.manualUnMuteLogging.featureName=muting
|
||||
abstracto.featureModes.manualUnMuteLogging.mode=manualUnMuteLogging
|
||||
abstracto.featureModes.manualUnMuteLogging.enabled=true
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.command.mute;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.moderation.command.SetMuteRole;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteRoleManagementService;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SetMuteRoleTest {
|
||||
|
||||
@InjectMocks
|
||||
private SetMuteRole testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteRoleManagementService muteRoleManagementService;
|
||||
|
||||
@Mock
|
||||
private RoleManagementService roleManagementService;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Test
|
||||
public void testExecuteCommand() {
|
||||
Role role = Mockito.mock(Role.class);
|
||||
Long roleId = 5L;
|
||||
when(role.getIdLong()).thenReturn(roleId);
|
||||
ARole aRole = Mockito.mock(ARole.class);
|
||||
when(roleManagementService.findRole(roleId)).thenReturn(aRole);
|
||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(role));
|
||||
when(role.getGuild()).thenReturn(parameters.getGuild());
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(serverManagementService.loadServer(parameters.getGuild())).thenReturn(server);
|
||||
CommandResult result = testUnit.execute(parameters);
|
||||
verify(muteRoleManagementService, times(1)).setMuteRoleForServer(server, aRole);
|
||||
CommandTestUtilities.checkSuccessfulCompletion(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.command.mute;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.moderation.command.UnMute;
|
||||
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UnMuteTest {
|
||||
|
||||
@InjectMocks
|
||||
private UnMute testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteService muteService;
|
||||
|
||||
@Mock
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Mock
|
||||
private Member memberToUnMute;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Test
|
||||
public void testUnMuteCommand() {
|
||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(memberToUnMute));
|
||||
when(memberToUnMute.getGuild()).thenReturn(parameters.getGuild());
|
||||
AUserInAServer user = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(memberToUnMute)).thenReturn(user);
|
||||
when(muteService.unMuteUser(user)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
}
|
||||
|
||||
@Test(expected = NoMuteFoundException.class)
|
||||
public void testUnMuteCommandWithoutExistingMute() {
|
||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(memberToUnMute));
|
||||
when(memberToUnMute.getGuild()).thenReturn(parameters.getGuild());
|
||||
AUserInAServer user = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(memberToUnMute)).thenReturn(user);
|
||||
when(muteService.unMuteUser(user)).thenThrow(new NoMuteFoundException());
|
||||
testUnit.executeAsync(parameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberJoinModel;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.MuteService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class JoinMuteListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private JoinMuteListener testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Mock
|
||||
private MuteService muteService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer joiningUser;
|
||||
|
||||
@Mock
|
||||
private ServerUser serverUser;
|
||||
|
||||
@Mock
|
||||
private MemberJoinModel model;
|
||||
|
||||
private static final Long SERVER_ID = 3L;
|
||||
private static final Long USER_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testNonMutedUserJoins() {
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(joiningUser);
|
||||
when(muteManagementService.hasActiveMute(joiningUser)).thenReturn(false);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(model.getJoiningUser()).thenReturn(serverUser);
|
||||
testUnit.execute(model);
|
||||
verify(muteService, times(0)).applyMuteRole(joiningUser);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMutedUserJoins() {
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(serverUser.getUserId()).thenReturn(USER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(joiningUser);
|
||||
when(muteManagementService.hasActiveMute(joiningUser)).thenReturn(true);
|
||||
when(model.getJoiningUser()).thenReturn(serverUser);
|
||||
testUnit.execute(model);
|
||||
verify(muteService, times(1)).applyMuteRole(joiningUser);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.KickLogModel;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KickServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private KickServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
|
||||
@Test
|
||||
public void testKickMemberWithLog() {
|
||||
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_ID);
|
||||
when(member.getGuild()).thenReturn(mockedGuild);
|
||||
String reason = "reason";
|
||||
AuditableRestAction<Void> 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);
|
||||
testUnit.kickMember(member, reason, model);
|
||||
verify(postTargetService, times(0)).sendEmbedInPostTarget(any(MessageToSend.class), eq(ModerationPostTarget.KICK_LOG), eq(SERVER_ID));
|
||||
verify(templateService, times(1)).renderEmbedTemplate(KickServiceBean.KICK_LOG_TEMPLATE, model, SERVER_ID);
|
||||
}
|
||||
}
|
||||
@@ -1,458 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FullUserInServer;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
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.posttarget.MutingPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.exception.MuteRoleNotSetupException;
|
||||
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.model.database.MuteRole;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteContext;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteRoleManagementService;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageChannel;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import static dev.sheldan.abstracto.moderation.service.MuteServiceBean.MUTE_NOTIFICATION_TEMPLATE;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MuteServiceBeanTest {
|
||||
@InjectMocks
|
||||
private MuteServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteRoleManagementService muteRoleManagementService;
|
||||
|
||||
@Mock
|
||||
private RoleService roleService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
@Mock
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private GuildService guildService;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Mock
|
||||
private MuteServiceBean self;
|
||||
|
||||
@Mock
|
||||
private ScheduledExecutorService executorService;
|
||||
|
||||
@Mock
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userBeingMuted;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer userMuting;
|
||||
|
||||
@Mock
|
||||
private User jdaUserBeingMuted;
|
||||
|
||||
@Mock
|
||||
private Member memberBeingMuted;
|
||||
|
||||
@Mock
|
||||
private Member memberMuting;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AChannel aChannel;
|
||||
|
||||
@Mock
|
||||
private MessageChannel channel;
|
||||
|
||||
@Mock
|
||||
private ServerChannelMessage cause;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@Mock
|
||||
private ARole aRole;
|
||||
|
||||
@Mock
|
||||
private MuteRole muteRole;
|
||||
|
||||
@Mock
|
||||
private MessageToSend messageToSend;
|
||||
|
||||
@Mock
|
||||
private AUser user;
|
||||
|
||||
@Mock
|
||||
private Mute mute;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@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";
|
||||
private static final String TRIGGER = "trigger";
|
||||
public static final Long MUTE_ID = 6L;
|
||||
public static final Long SERVER_ID = 7L;
|
||||
public static final Long USER_MUTING_ID = 4L;
|
||||
public static final Long USER_BEING_MUTED_ID = 3L;
|
||||
|
||||
@Test
|
||||
public void testMuteUserWithScheduler() {
|
||||
Instant unMuteDate = longerMute();
|
||||
when(cause.getServerId()).thenReturn(SERVER_ID);
|
||||
FullUserInServer mutedUser = Mockito.mock(FullUserInServer.class);
|
||||
FullUserInServer mutingUser = Mockito.mock(FullUserInServer.class);
|
||||
setupFullUsers(mutedUser, mutingUser);
|
||||
when(muteRole.getRole()).thenReturn(aRole);
|
||||
when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted);
|
||||
when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(true);
|
||||
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
|
||||
when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class), eq(SERVER_ID))).thenReturn(NOTIFICATION_TEXT);
|
||||
|
||||
when(messageService.sendMessageToUser(jdaUserBeingMuted, NOTIFICATION_TEXT)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToUserAsync(userBeingMuted, aRole)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
|
||||
CompletableFuture<Void> future = testUnit.muteUserInServer(mutedUser, mutingUser, REASON, unMuteDate, cause);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
}
|
||||
|
||||
private void setupFullUsers(FullUserInServer mutedUser, FullUserInServer mutingUser) {
|
||||
when(memberBeingMuted.getGuild()).thenReturn(guild);
|
||||
when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted);
|
||||
when(mutedUser.getAUserInAServer()).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(mutedUser.getMember()).thenReturn(memberBeingMuted);
|
||||
when(mutingUser.getMember()).thenReturn(memberMuting);
|
||||
when(memberBeingMuted.getGuild()).thenReturn(guild);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMuteWithDirectUnMute() {
|
||||
when(memberBeingMuted.getGuild()).thenReturn(guild);
|
||||
when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted);
|
||||
FullUserInServer mutedUser = Mockito.mock(FullUserInServer.class);
|
||||
FullUserInServer mutingUser = Mockito.mock(FullUserInServer.class);
|
||||
setupFullUsers(mutedUser, mutingUser);
|
||||
Instant unMuteDate = shorterMute();
|
||||
when(cause.getServerId()).thenReturn(SERVER_ID);
|
||||
when(memberBeingMuted.getGuild()).thenReturn(guild);
|
||||
when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted);
|
||||
when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(true);
|
||||
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
|
||||
when(muteRole.getRole()).thenReturn(aRole);
|
||||
String notificationText = "text";
|
||||
when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class), eq(SERVER_ID))).thenReturn(notificationText);
|
||||
when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToUserAsync(userBeingMuted, muteRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<Void> future = testUnit.muteUserInServer(mutedUser, mutingUser, REASON, unMuteDate, cause);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally() );
|
||||
verifyDirectMute();
|
||||
}
|
||||
|
||||
@Test(expected = MuteRoleNotSetupException.class)
|
||||
public void testMuteUserWithoutMuteRole() {
|
||||
FullUserInServer mutedUser = Mockito.mock(FullUserInServer.class);
|
||||
when(mutedUser.getAUserInAServer()).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(false);
|
||||
FullUserInServer mutingUser = Mockito.mock(FullUserInServer.class);
|
||||
ServerChannelMessage serverChannelMessage = mock(ServerChannelMessage.class);
|
||||
testUnit.muteUserInServer(mutedUser, mutingUser, REASON, longerMute(), serverChannelMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelUnMuteJob() {
|
||||
when(mute.getTriggerKey()).thenReturn(TRIGGER);
|
||||
testUnit.cancelUnMuteJob(mute);
|
||||
verify(schedulerService, times(1)).stopTrigger(TRIGGER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCancelNotExistingJob() {
|
||||
testUnit.cancelUnMuteJob(mute);
|
||||
verify(schedulerService, times(0)).stopTrigger(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMuteMember() {
|
||||
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(userInServerManagementService.loadOrCreateUser(memberMuting)).thenReturn(userMuting);
|
||||
Instant unMuteDate = shorterMute();
|
||||
when(cause.getServerId()).thenReturn(SERVER_ID);
|
||||
when(memberBeingMuted.getGuild()).thenReturn(guild);
|
||||
when(memberBeingMuted.getUser()).thenReturn(jdaUserBeingMuted);
|
||||
when(muteRoleManagementService.muteRoleForServerExists(server)).thenReturn(true);
|
||||
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
|
||||
|
||||
String notificationText = "text";
|
||||
when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class), eq(SERVER_ID))).thenReturn(notificationText);
|
||||
when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToUserAsync(userBeingMuted, muteRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.muteMember(memberBeingMuted, memberMuting, REASON, unMuteDate, cause);
|
||||
verifyDirectMute();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMuteMemberWithLog() {
|
||||
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(userInServerManagementService.loadOrCreateUser(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(server.getId()).thenReturn(SERVER_ID);
|
||||
when(serverManagementService.loadOrCreate(SERVER_ID)).thenReturn(server);
|
||||
String notificationText = "text";
|
||||
when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class), eq(SERVER_ID))).thenReturn(notificationText);
|
||||
when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(templateService.renderEmbedTemplate(eq(MuteServiceBean.MUTE_LOG_TEMPLATE), any(MuteContext.class), eq(SERVER_ID))).thenReturn(messageToSend);
|
||||
when(roleService.addRoleToUserAsync(userBeingMuted, muteRole.getRole())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.muteMemberWithLog(muteLog);
|
||||
verifyDirectMute();
|
||||
verify(templateService, times(1)).renderEmbedTemplate(eq(MuteServiceBean.MUTE_LOG_TEMPLATE), any(MuteContext.class), eq(SERVER_ID));
|
||||
verify(postTargetService, times(1)).sendEmbedInPostTarget(messageToSend, MutingPostTarget.MUTE_LOG, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMuteMemberWithoutLog() {
|
||||
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(userInServerManagementService.loadOrCreateUser(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);
|
||||
String notificationText = "text";
|
||||
when(templateService.renderTemplate(eq(MUTE_NOTIFICATION_TEMPLATE), any(MuteNotification.class), eq(SERVER_ID))).thenReturn(notificationText);
|
||||
when(messageService.sendMessageToUser(memberBeingMuted.getUser(), notificationText)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(roleService.addRoleToUserAsync(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));
|
||||
when(guildService.getGuildById(SERVER_ID)).thenReturn(guild);
|
||||
testUnit.unMuteUser(userBeingMuted);
|
||||
verifyNoUnMuteHappened();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEndMute() {
|
||||
setupUnMuteMocks();
|
||||
when(mute.getMutedUser()).thenReturn(userBeingMuted);
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(mute.getMutingUser()).thenReturn(userMuting);
|
||||
when(mute.getServer()).thenReturn(server);
|
||||
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
|
||||
when(muteRole.getRole()).thenReturn(aRole);
|
||||
when(muteManagementService.findMuteOptional(MUTE_ID, SERVER_ID)).thenReturn(Optional.of(mute));
|
||||
when(roleService.removeRoleFromUserAsync(userBeingMuted, aRole)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(memberService.getMemberInServerAsync(userBeingMuted)).thenReturn(CompletableFuture.completedFuture(memberBeingMuted));
|
||||
when(memberService.getMemberInServerAsync(userMuting)).thenReturn(CompletableFuture.completedFuture(memberMuting));
|
||||
testUnit.endMute(MUTE_ID, SERVER_ID);
|
||||
verify(self, times(1)).sendUnmuteLog(eq(MUTE_ID), any(Guild.class), any(CompletableFuture.class), any(CompletableFuture.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendUnmuteLog() {
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(muteManagementService.findMute(MUTE_ID, SERVER_ID)).thenReturn(mute);
|
||||
when(mute.getMuteId()).thenReturn(new ServerSpecificId(SERVER_ID, MUTE_ID));
|
||||
when(serverManagementService.loadServer(SERVER_ID)).thenReturn(server);
|
||||
testUnit.sendUnmuteLog(MUTE_ID, guild, CompletableFuture.completedFuture(memberMuting), CompletableFuture.completedFuture(memberBeingMuted));
|
||||
verify(self, times(1)).endMuteInDatabase(MUTE_ID, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test(expected = NoMuteFoundException.class)
|
||||
public void testEndNonExistingMute() {
|
||||
when(muteManagementService.findMuteOptional(MUTE_ID, SERVER_ID)).thenReturn(Optional.empty());
|
||||
testUnit.endMute(MUTE_ID, SERVER_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnMuteMemberInGuild() {
|
||||
executeUnMuteWithLogTest();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompletelyUnMuteNotMutedUser() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList());
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(0)).saveMute(any(Mute.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompletelyUnMuteNotScheduledMuteUser() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
verify(schedulerService, times(0)).stopTrigger(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompletelyUnMuteScheduledMuteUser() {
|
||||
when(mute.getTriggerKey()).thenReturn(TRIGGER);
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
verify(schedulerService, times(1)).stopTrigger(TRIGGER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompletelyUnMuteMember() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(mute.getTriggerKey()).thenReturn(TRIGGER);
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
|
||||
testUnit.completelyUnMuteMember(memberBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
verify(schedulerService, times(1)).stopTrigger(TRIGGER);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyScheduling() {
|
||||
Instant unMuteDate = shorterMute();
|
||||
MuteContext muteLog = Mockito.mock(MuteContext.class);
|
||||
when(muteLog.getMuteTargetDate()).thenReturn(unMuteDate);
|
||||
when(muteLog.getMuteId()).thenReturn(MUTE_ID);
|
||||
ServerChannelMessage serverContext = Mockito.mock(ServerChannelMessage.class);
|
||||
when(serverContext.getServerId()).thenReturn(SERVER_ID);
|
||||
when(serverContext.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(channelManagementService.loadChannel(CHANNEL_ID)).thenReturn(aChannel);
|
||||
when(muteLog.getContext()).thenReturn(serverContext);
|
||||
testUnit.persistMute(muteLog);
|
||||
verify(executorService, times(1)).schedule(any(Runnable.class), anyLong(), any());
|
||||
}
|
||||
|
||||
private void verifyNoUnMuteHappened() {
|
||||
verify(muteManagementService, times(0)).saveMute(any(Mute.class));
|
||||
verify(roleService, times(0)).removeRoleFromUser(eq(userBeingMuted), any(ARole.class));
|
||||
verify(postTargetService, times(0)).sendEmbedInPostTarget(any(MessageToSend.class), eq(MutingPostTarget.MUTE_LOG), eq(SERVER_ID));
|
||||
}
|
||||
|
||||
private void executeUnMuteWithLogTest() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(mute.getMutedUser()).thenReturn(userBeingMuted);
|
||||
when(mute.getMutingUser()).thenReturn(userMuting);
|
||||
when(mute.getServer()).thenReturn(server);
|
||||
when(muteRoleManagementService.retrieveMuteRoleForServer(server)).thenReturn(muteRole);
|
||||
when(muteRole.getRole()).thenReturn(aRole);
|
||||
setupUnMuteMocks();
|
||||
when(roleService.removeRoleFromUserAsync(userBeingMuted, aRole)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(memberService.getMemberInServerAsync(userBeingMuted)).thenReturn(CompletableFuture.completedFuture(memberBeingMuted));
|
||||
when(memberService.getMemberInServerAsync(userMuting)).thenReturn(CompletableFuture.completedFuture(memberMuting));
|
||||
testUnit.unMuteUser(userBeingMuted);
|
||||
|
||||
}
|
||||
|
||||
private void setupUnMuteMocks() {
|
||||
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(guildService.getGuildById(server.getId())).thenReturn(guild);
|
||||
}
|
||||
|
||||
private void verifyDirectMute() {
|
||||
verify(messageService, times(1)).sendMessageToUser(jdaUserBeingMuted, NOTIFICATION_TEXT);
|
||||
}
|
||||
|
||||
private Instant longerMute() {
|
||||
return Instant.now().plus(Duration.ofHours(1));
|
||||
}
|
||||
|
||||
private Instant shorterMute() {
|
||||
return Instant.now().plus(Duration.ofSeconds(4));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningDecayFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarnDecayMode;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarningMode;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarningPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnContext;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnNotification;
|
||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayLogModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.moderation.service.WarnServiceBean.WARNINGS_COUNTER_KEY;
|
||||
import static dev.sheldan.abstracto.moderation.service.WarnServiceBean.WARN_LOG_TEMPLATE;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WarnServiceBeanTest {
|
||||
|
||||
public static final long WARN_ID = 8L;
|
||||
@InjectMocks
|
||||
private WarnServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@Mock
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private ConfigService configService;
|
||||
|
||||
@Mock
|
||||
private WarnServiceBean self;
|
||||
|
||||
@Mock
|
||||
private Member warnedMember;
|
||||
|
||||
@Mock
|
||||
private Member warningMember;
|
||||
|
||||
@Mock
|
||||
private Member secondWarnedMember;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@Mock
|
||||
private MessageToSend messageToSend;
|
||||
|
||||
@Mock
|
||||
private User warnedSimpleUser;
|
||||
|
||||
@Mock
|
||||
private WarnContext context;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<WarnDecayLogModel> warnDecayLogModelArgumentCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<WarnNotification> notificationCaptor;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer warningUser;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer firstWarnedUser;
|
||||
|
||||
@Mock
|
||||
private AUserInAServer secondWarnedUser;
|
||||
|
||||
@Mock
|
||||
private AUser firstAUser;
|
||||
|
||||
@Mock
|
||||
private AUser secondAUser;
|
||||
|
||||
@Mock
|
||||
private AUser thirdAUser;
|
||||
|
||||
@Mock
|
||||
private Warning firstWarning;
|
||||
|
||||
@Mock
|
||||
private Warning secondWarning;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Mock
|
||||
private CounterService counterService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Mock
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Mock
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
private static final String NOTIFICATION_TEXT = "text";
|
||||
private static final String GUILD_NAME = "guild";
|
||||
private static final Long SERVER_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testDecayWarning() {
|
||||
Instant date = Instant.now();
|
||||
when(firstWarning.getWarnId()).thenReturn(new ServerSpecificId(SERVER_ID, 4L));
|
||||
testUnit.decayWarning(firstWarning, date);
|
||||
verify(firstWarning, times(1)).setDecayed(true);
|
||||
verify(firstWarning, times(1)).setDecayDate(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDecayWarningsForServer() {
|
||||
setupWarnDecay();
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.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 testDecayWarningsForServerWithoutLog() {
|
||||
setupWarnDecay();
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.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(ModerationFeatureDefinition.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();
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.WARNING, server, WarningMode.WARN_DECAY_LOG)).thenReturn(false);
|
||||
testUnit.decayAllWarningsForServer(server);
|
||||
verify(self, times(0)).renderAndSendWarnDecayLogs(eq(SERVER_ID), any());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testDecayAllWarningsWithoutWarningsWithoutLog() {
|
||||
List<Warning> warnings = Collections.emptyList();
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(warnManagementService.getActiveWarningsInServerOlderThan(eq(server), any(Instant.class))).thenReturn(warnings);
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.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<Warning> warnings = Collections.emptyList();
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(warnManagementService.getActiveWarningsInServerOlderThan(eq(server), any(Instant.class))).thenReturn(warnings);
|
||||
when(featureModeService.featureModeActive(ModerationFeatureDefinition.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();
|
||||
setupMocksForWarning();
|
||||
when(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, SERVER_ID)).thenReturn(false);
|
||||
CompletableFuture<Void> future = testUnit.notifyAndLogFullUserWarning(context);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
}
|
||||
|
||||
private void setupWarnContext() {
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(context.getGuild()).thenReturn(guild);
|
||||
when(context.getWarnedMember()).thenReturn(warnedMember);
|
||||
when(context.getMember()).thenReturn(warningMember);
|
||||
when(counterService.getNextCounterValue(server, WARNINGS_COUNTER_KEY)).thenReturn(WARN_ID);
|
||||
}
|
||||
|
||||
|
||||
private void setupMocksForWarning() {
|
||||
setupWarnings();
|
||||
when(warnedMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getName()).thenReturn(GUILD_NAME);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(warnedMember.getUser()).thenReturn(warnedSimpleUser);
|
||||
when(templateService.renderEmbedTemplate(eq(WARN_LOG_TEMPLATE), warnDecayLogModelArgumentCaptor.capture(), eq(SERVER_ID))).thenReturn(messageToSend);
|
||||
when(messageService.sendMessageToUser(eq(warnedMember.getUser()), any())).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(postTargetService.sendEmbedInPostTarget(messageToSend, WarningPostTarget.WARN_LOG, SERVER_ID)).thenReturn(CommandTestUtilities.messageFutureList());
|
||||
when(templateService.renderTemplate(eq(WarnServiceBean.WARN_NOTIFICATION_TEMPLATE), notificationCaptor.capture(), eq(SERVER_ID))).thenReturn(NOTIFICATION_TEXT);
|
||||
when(serverManagementService.loadOrCreate(SERVER_ID)).thenReturn(server);
|
||||
}
|
||||
|
||||
private void setupWarnings() {
|
||||
when(firstWarning.getWarningUser()).thenReturn(warningUser);
|
||||
when(secondWarning.getWarningUser()).thenReturn(warningUser);
|
||||
when(warningUser.getServerReference()).thenReturn(server);
|
||||
when(warningUser.getUserReference()).thenReturn(thirdAUser);
|
||||
|
||||
when(firstWarning.getWarnedUser()).thenReturn(firstWarnedUser);
|
||||
when(firstWarnedUser.getServerReference()).thenReturn(server);
|
||||
when(firstWarnedUser.getUserReference()).thenReturn(firstAUser);
|
||||
when(secondWarning.getWarnedUser()).thenReturn(secondWarnedUser);
|
||||
when(secondWarnedUser.getServerReference()).thenReturn(server);
|
||||
when(secondWarnedUser.getUserReference()).thenReturn(secondAUser);
|
||||
when(firstWarning.getWarnId()).thenReturn(new ServerSpecificId(SERVER_ID, WARN_ID));
|
||||
when(secondWarning.getWarnId()).thenReturn(new ServerSpecificId(SERVER_ID, 9L));
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
}
|
||||
|
||||
private void setupWarnDecay() {
|
||||
setupWarnings();
|
||||
SystemConfigProperty defaultDecayDays = Mockito.mock(SystemConfigProperty.class);
|
||||
Long defaultDayCount = 4L;
|
||||
when(defaultDecayDays.getLongValue()).thenReturn(defaultDayCount);
|
||||
when(defaultConfigManagementService.getDefaultConfig(WarningDecayFeatureConfig.DECAY_DAYS_KEY)).thenReturn(defaultDecayDays);
|
||||
when(configService.getLongValue(WarningDecayFeatureConfig.DECAY_DAYS_KEY, SERVER_ID, defaultDayCount)).thenReturn(5L);
|
||||
List<Warning> warnings = Arrays.asList(firstWarning, secondWarning);
|
||||
when(memberService.getMemberInServerAsync(warningUser)).thenReturn(CompletableFuture.completedFuture(warningMember));
|
||||
when(memberService.getMemberInServerAsync(firstWarnedUser)).thenReturn(CompletableFuture.completedFuture(warnedMember));
|
||||
when(memberService.getMemberInServerAsync(secondWarnedUser)).thenReturn(CompletableFuture.completedFuture(secondWarnedMember));
|
||||
when(warnManagementService.getActiveWarningsInServerOlderThan(eq(server), any(Instant.class))).thenReturn(warnings);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.repository.MuteRepository;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MuteManagementServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private MuteManagementServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteRepository muteRepository;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Mute> muteArgumentCaptor;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
private static final Long MUTE_ID = 2L;
|
||||
|
||||
@Test
|
||||
public void testCreateMute() {
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
long messageId = 9L;
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
AUserInAServer mutingUser = Mockito.mock(AUserInAServer.class);
|
||||
AUserInAServer mutedUser = Mockito.mock(AUserInAServer.class);
|
||||
AUser user = Mockito.mock(AUser.class);
|
||||
when(mutedUser.getUserReference()).thenReturn(user);
|
||||
when(mutedUser.getServerReference()).thenReturn(server);
|
||||
AUser secondUser = Mockito.mock(AUser.class);
|
||||
when(mutingUser.getUserReference()).thenReturn(secondUser);
|
||||
String reason = "reason";
|
||||
String triggerKey = "key";
|
||||
Instant unMuteDate = Instant.now();
|
||||
AServerAChannelMessage muteMessage = Mockito.mock(AServerAChannelMessage.class);
|
||||
when(muteMessage.getMessageId()).thenReturn(messageId);
|
||||
when(muteMessage.getServer()).thenReturn(server);
|
||||
when(muteMessage.getChannel()).thenReturn(channel);
|
||||
|
||||
testUnit.createMute(mutedUser, mutingUser, reason, unMuteDate, muteMessage, triggerKey, 8L);
|
||||
verify(muteRepository, times(1)).save(muteArgumentCaptor.capture());
|
||||
Mute createdMute = muteArgumentCaptor.getValue();
|
||||
Assert.assertEquals(reason, createdMute.getReason());
|
||||
Assert.assertEquals(mutingUser, createdMute.getMutingUser());
|
||||
Assert.assertEquals(mutedUser, createdMute.getMutedUser());
|
||||
Assert.assertEquals(server, createdMute.getServer());
|
||||
Assert.assertFalse(createdMute.getMuteEnded());
|
||||
Assert.assertEquals(messageId, createdMute.getMessageId().longValue());
|
||||
Assert.assertEquals(channel, createdMute.getMutingChannel());
|
||||
Assert.assertEquals(unMuteDate, createdMute.getMuteTargetDate());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindMute() {
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
ServerSpecificId muteId = Mockito.mock(ServerSpecificId.class);
|
||||
when(mute.getMuteId()).thenReturn(muteId);
|
||||
when(muteId.getId()).thenReturn(MUTE_ID);
|
||||
when(muteRepository.findByMuteId_IdAndMuteId_ServerId(MUTE_ID, SERVER_ID)).thenReturn(Optional.of(mute));
|
||||
Optional<Mute> foundMuteOptional = testUnit.findMuteOptional(MUTE_ID, SERVER_ID);
|
||||
Assert.assertTrue(foundMuteOptional.isPresent());
|
||||
foundMuteOptional.ifPresent(foundMute -> Assert.assertEquals(MUTE_ID, foundMute.getMuteId().getId()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindNonExistingMute() {
|
||||
when(muteRepository.findByMuteId_IdAndMuteId_ServerId(MUTE_ID, SERVER_ID)).thenReturn(Optional.empty());
|
||||
Optional<Mute> foundMuteOptional = testUnit.findMuteOptional(MUTE_ID, SERVER_ID);
|
||||
Assert.assertFalse(foundMuteOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveMute() {
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
testUnit.saveMute(mute);
|
||||
verify(muteRepository, times(1)).save(mute);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMuteOfUser() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
when(muteRepository.findTopByMutedUserAndMuteEndedFalse(userInAServer)).thenReturn(mute);
|
||||
Mute aMuteOf = testUnit.getAMuteOf(userInAServer);
|
||||
Assert.assertEquals(mute, aMuteOf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMuteOfMember() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
Member member = Mockito.mock(Member.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(member)).thenReturn(userInAServer);
|
||||
when(muteRepository.findTopByMutedUserAndMuteEndedFalse(userInAServer)).thenReturn(mute);
|
||||
Mute aMuteOf = testUnit.getAMuteOf(member);
|
||||
Assert.assertEquals(mute, aMuteOf);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAllMutesOf() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
Mute mute2 = Mockito.mock(Mute.class);
|
||||
when(muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(userInAServer)).thenReturn(Arrays.asList(mute, mute2));
|
||||
List<Mute> allMutesOf = testUnit.getAllActiveMutesOf(userInAServer);
|
||||
Assert.assertEquals(2, allMutesOf.size());
|
||||
Assert.assertEquals(mute, allMutesOf.get(0));
|
||||
Assert.assertEquals(mute2, allMutesOf.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasActiveMute() {
|
||||
checkExist(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasNoActiveMute() {
|
||||
checkExist(false);
|
||||
}
|
||||
|
||||
private void checkExist(boolean value) {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(muteRepository.existsByMutedUserAndMuteEndedFalse(userInAServer)).thenReturn(value);
|
||||
boolean result = testUnit.hasActiveMute(userInAServer);
|
||||
Assert.assertEquals(value, result);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.MuteRole;
|
||||
import dev.sheldan.abstracto.moderation.repository.MuteRoleRepository;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class MuteRoleManagementServiceBeanTest {
|
||||
|
||||
@InjectMocks
|
||||
private MuteRoleManagementServiceBean testUnit;
|
||||
|
||||
@Mock
|
||||
private MuteRoleRepository muteRoleRepository;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Test
|
||||
public void testRetrieveMuteRoleForServer() {
|
||||
MuteRole role = Mockito.mock(MuteRole.class);
|
||||
when(muteRoleRepository.findByRoleServer(server)).thenReturn(role);
|
||||
MuteRole muteRole = testUnit.retrieveMuteRoleForServer(server);
|
||||
Assert.assertEquals(role, muteRole);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServeHasMuteRole() {
|
||||
when(muteRoleRepository.existsByRoleServer(server)).thenReturn(true);
|
||||
Assert.assertTrue(testUnit.muteRoleForServerExists(server));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMuteRoleForServer() {
|
||||
ARole role = Mockito.mock(ARole.class);
|
||||
ArgumentCaptor<MuteRole> muteRoleCaptor = ArgumentCaptor.forClass(MuteRole.class);
|
||||
MuteRole savedRole = Mockito.mock(MuteRole.class);
|
||||
when(muteRoleRepository.save(muteRoleCaptor.capture())).thenReturn(savedRole);
|
||||
MuteRole muteRoleForServer = testUnit.createMuteRoleForServer(server, role);
|
||||
Assert.assertEquals(savedRole, muteRoleForServer);
|
||||
Assert.assertEquals(role, muteRoleCaptor.getValue().getRole());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveRolesForServer() {
|
||||
List<MuteRole> existingRoles = Arrays.asList(Mockito.mock(MuteRole.class), Mockito.mock(MuteRole.class));
|
||||
when(muteRoleRepository.findAllByRoleServer(server)).thenReturn(existingRoles);
|
||||
List<MuteRole> foundRoles = testUnit.retrieveMuteRolesForServer(server);
|
||||
Assert.assertEquals(existingRoles.size(), foundRoles.size());
|
||||
for (int i = 0; i < existingRoles.size(); i++) {
|
||||
MuteRole existingRole = existingRoles.get(i);
|
||||
MuteRole foundRole = foundRoles.get(i);
|
||||
Assert.assertEquals(existingRole, foundRole);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMuteRoleWithoutPrevious() {
|
||||
ARole role = Mockito.mock(ARole.class);
|
||||
when(muteRoleRepository.existsByRoleServer(server)).thenReturn(false);
|
||||
ArgumentCaptor<MuteRole> muteRoleCaptor = ArgumentCaptor.forClass(MuteRole.class);
|
||||
MuteRole savedRole = Mockito.mock(MuteRole.class);
|
||||
when(muteRoleRepository.save(muteRoleCaptor.capture())).thenReturn(savedRole);
|
||||
MuteRole muteRole = testUnit.setMuteRoleForServer(server, role);
|
||||
Assert.assertEquals(savedRole, muteRole);
|
||||
Assert.assertEquals(role, muteRoleCaptor.getValue().getRole());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetMuteRoleWithPrevious() {
|
||||
ARole role = Mockito.mock(ARole.class);
|
||||
when(muteRoleRepository.existsByRoleServer(server)).thenReturn(true);
|
||||
MuteRole existingRole = Mockito.mock(MuteRole.class);
|
||||
when(muteRoleRepository.findByRoleServer(server)).thenReturn(existingRole);
|
||||
testUnit.setMuteRoleForServer(server, role);
|
||||
verify(existingRole, times(1)).setRole(role);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user