mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-05 00:53:04 +00:00
[AB-167] adding warning created events and infraction counter
adding disabling of post targets adding some logging for message sending failure consumer
This commit is contained in:
@@ -39,7 +39,7 @@ public class MyWarnings extends AbstractConditionableCommand {
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
MyWarningsModel model = (MyWarningsModel) ContextConverter.fromCommandContext(commandContext, MyWarningsModel.class);
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||
Long currentWarnCount = warnManagementService.getActiveWarnsForUser(userInAServer);
|
||||
Long currentWarnCount = warnManagementService.getActiveWarnCountForUser(userInAServer);
|
||||
model.setCurrentWarnCount(currentWarnCount);
|
||||
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(userInAServer);
|
||||
model.setTotalWarnCount(totalWarnCount);
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package dev.sheldan.abstracto.moderation.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ExecutorService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
|
||||
@Configuration
|
||||
public class ModerationListenerConfig {
|
||||
@Autowired
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Bean(name = "infractionLevelChangedExecutor")
|
||||
public TaskExecutor infractionLevelChangedExecutor() {
|
||||
return executorService.setupExecutorFor("infractionLevelChangedListener");
|
||||
}
|
||||
|
||||
@Bean(name = "warningCreatedExecutor")
|
||||
public TaskExecutor warningCreatedExecutor() {
|
||||
return executorService.setupExecutorFor("warningCreatedListener");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.manager;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.moderation.listener.InfractionLevelChangedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.InfractionLevelChangedEventModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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
|
||||
@Slf4j
|
||||
public class InfractionLevelChangedListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<InfractionLevelChangedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("infractionLevelChangedExecutor")
|
||||
private TaskExecutor infractionLevelChangedExecutor;
|
||||
|
||||
public void sendInfractionLevelChangedEvent(Integer newLevel, Integer oldLevel, Long newPoints, Long oldPoints, ServerUser serverUser) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
InfractionLevelChangedEventModel model = createInfractionChangedModel(newLevel, oldLevel, oldPoints, newPoints, serverUser);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model, infractionLevelChangedExecutor));
|
||||
}
|
||||
|
||||
private InfractionLevelChangedEventModel createInfractionChangedModel(Integer newLevel, Integer oldLevel, Long oldPoints, Long newPoints, ServerUser serverUser) {
|
||||
return InfractionLevelChangedEventModel
|
||||
.builder()
|
||||
.newLevel(newLevel)
|
||||
.oldLevel(oldLevel)
|
||||
.oldPoints(oldPoints)
|
||||
.newPoints(newPoints)
|
||||
.userId(serverUser.getUserId())
|
||||
.serverId(serverUser.getServerId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
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.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.moderation.listener.WarningCreatedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.WarningCreatedEventModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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
|
||||
@Slf4j
|
||||
public class WarningCreatedListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<WarningCreatedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("warningCreatedExecutor")
|
||||
private TaskExecutor warningCreatedExecutor;
|
||||
|
||||
public void sendWarningCreatedEvent(ServerSpecificId warnId, ServerUser warnedUser, ServerUser warningUser,
|
||||
String reason, ServerChannelMessage warnCommand) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
WarningCreatedEventModel model = createWarningCreatedEventModel(warnId, warnedUser, warningUser, reason, warnCommand);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model, warningCreatedExecutor));
|
||||
}
|
||||
|
||||
private WarningCreatedEventModel createWarningCreatedEventModel(ServerSpecificId warnId, ServerUser warnedUser,
|
||||
ServerUser warningUser, String reason, ServerChannelMessage warnCommandMessage) {
|
||||
return WarningCreatedEventModel
|
||||
.builder()
|
||||
.warningId(warnId.getId())
|
||||
.serverId(warnId.getServerId())
|
||||
.warningUserId(warningUser.getUserId())
|
||||
.warnedUserId(warnedUser.getUserId())
|
||||
.reason(reason)
|
||||
.warningChannelId(warnCommandMessage.getChannelId())
|
||||
.warningMessageId(warnCommandMessage.getMessageId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface InfractionRepository extends JpaRepository<Infraction, Long> {
|
||||
List<Infraction> findByUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public interface WarnRepository extends JpaRepository<Warning, ServerSpecificId>
|
||||
Long countByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
List<Warning> findByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
|
||||
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -139,20 +138,14 @@ public class BanServiceBean implements BanService {
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||
log.debug("Sending ban log message in guild {}.", guildId);
|
||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId);
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId));
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendUnBanLogMessage(UnBanLog banLog, Long guildId, String template) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||
log.debug("Sending unban log message in guild {}.", guildId);
|
||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId);
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
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.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.manager.InfractionLevelChangedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.template.InfractionLevelChangeModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
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.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class InfractionServiceBean implements InfractionService {
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ConfigManagementService configManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private InfractionServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private InfractionLevelChangedListenerManager infractionLevelChangedListenerManager;
|
||||
|
||||
private static final String INFRACTION_NOTIFICATION_TEMPLATE_KEY = "infraction_level_notification";
|
||||
|
||||
@Override
|
||||
public void decayInfraction(Infraction infraction) {
|
||||
log.info("Decaying infraction {}", infraction.getId());
|
||||
infraction.setDecayed(true);
|
||||
infraction.setDecayedDate(Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActiveInfractionPointsForUser(AUserInAServer aUserInAServer) {
|
||||
List<Infraction> infractions = infractionManagementService.getActiveInfractionsForUser(aUserInAServer);
|
||||
log.info("Calculating points for user {} in server {} with {} infractions.",
|
||||
aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId(), infractions.size());
|
||||
return infractions.stream().collect(Collectors.summarizingLong(Infraction::getPoints)).getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction createdInfraction = infractionManagementService.createInfraction(aUserInAServer, points);
|
||||
Long infractionId = createdInfraction.getId();
|
||||
return createInfractionNotification(aUserInAServer, points)
|
||||
.thenApply(aBoolean -> self.reloadInfraction(infractionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createInfractionNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
Long serverId = aUserInAServer.getServerReference().getId();
|
||||
Long currentPoints = getActiveInfractionPointsForUser(aUserInAServer);
|
||||
Long newPoints = currentPoints + points;
|
||||
Pair<Integer, Integer> levelChange = infractionLevelChanged(serverId, newPoints, currentPoints);
|
||||
Integer oldLevel = levelChange.getFirst();
|
||||
Integer newLevel = levelChange.getSecond();
|
||||
if(!oldLevel.equals(newLevel)) {
|
||||
InfractionLevelChangeModel model = InfractionLevelChangeModel
|
||||
.builder()
|
||||
.member(MemberDisplay.fromAUserInAServer(aUserInAServer))
|
||||
.newLevel(newLevel)
|
||||
.oldLevel(oldLevel)
|
||||
.oldPoints(currentPoints)
|
||||
.newPoints(newPoints)
|
||||
.build();
|
||||
infractionLevelChangedListenerManager.sendInfractionLevelChangedEvent(newLevel, oldLevel, newPoints, currentPoints, ServerUser.fromAUserInAServer(aUserInAServer));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(INFRACTION_NOTIFICATION_TEMPLATE_KEY, model, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, InfractionPostTarget.INFRACTION_NOTIFICATION, serverId));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Infraction reloadInfraction(Long infractionId) {
|
||||
return infractionManagementService.loadInfraction(infractionId);
|
||||
}
|
||||
|
||||
private Pair<Integer, Integer> infractionLevelChanged(Long serverId, Long newPoints, Long oldPoints) {
|
||||
List<Long> levelConfig = loadInfractionConfig(serverId);
|
||||
Integer newLevel = getInfractionLevel(newPoints, levelConfig);
|
||||
Integer oldLevel = getInfractionLevel(oldPoints, levelConfig);
|
||||
return Pair.of(oldLevel, newLevel);
|
||||
}
|
||||
|
||||
private List<Long> loadInfractionConfig(Long serverId) {
|
||||
Long levelAmount = configService.getLongValueOrConfigDefault(InfractionFeatureConfig.INFRACTION_LEVELS, serverId);
|
||||
List<Long> levelConfig = new ArrayList<>();
|
||||
for (long i = 1; i <= levelAmount; i++) {
|
||||
String levelKey = InfractionFeatureConfig.INFRACTION_LEVEL_PREFIX + i;
|
||||
if(configManagementService.configExists(serverId, levelKey)) {
|
||||
levelConfig.add(configService.getLongValue(levelKey, serverId));
|
||||
}
|
||||
}
|
||||
return levelConfig;
|
||||
}
|
||||
|
||||
private Integer getInfractionLevel(Long points, List<Long> levelConfig) {
|
||||
for (int i = 0; i < levelConfig.size(); i++) {
|
||||
if(points >= levelConfig.get(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,10 +40,8 @@ public class KickServiceBean implements KickService {
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendKickLog(KickLogModel kickLogModel) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, kickLogModel.getGuild().getIdLong());
|
||||
log.debug("Sending kick log message in guild {}.", kickLogModel.getGuild().getIdLong());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,21 +244,15 @@ public class MuteServiceBean implements MuteService {
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendMuteLog(MuteContext muteLogModel, AServer server) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
log.debug("Sending mute log to the mute post target.");
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
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());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -100,9 +100,13 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
||||
|
||||
@Transactional
|
||||
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser reporter) {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
if(reportMessage == null) {
|
||||
log.info("Creation reaction report about message {} was not sent - post target might be disabled in server {}.", cachedMessage.getMessageId(), cachedMessage.getServerId());
|
||||
} else {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
@@ -12,16 +13,20 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningDecayFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningFeatureConfig;
|
||||
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.WarnDecayPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarningPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.WarningCreatedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
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.model.template.job.WarnDecayWarning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.listener.WarnDecayMemberNotificationModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
@@ -85,6 +90,18 @@ public class WarnServiceBean implements WarnService {
|
||||
@Autowired
|
||||
private WarnServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private WarningCreatedListenerManager warningCreatedListenerManager;
|
||||
|
||||
public static final String WARN_LOG_TEMPLATE = "warn_log";
|
||||
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
|
||||
public static final String WARNINGS_COUNTER_KEY = "WARNINGS";
|
||||
@@ -100,22 +117,34 @@ public class WarnServiceBean implements WarnService {
|
||||
Member warningMember = context.getMember();
|
||||
Guild guild = warnedMember.getGuild();
|
||||
log.info("User {} is warning {} in server {}", warnedMember.getId(), warningMember.getId(), guild.getIdLong());
|
||||
WarnNotification warnNotification = WarnNotification.builder().reason(context.getReason()).warnId(warningId).serverName(guild.getName()).build();
|
||||
WarnNotification warnNotification = WarnNotification
|
||||
.builder()
|
||||
.reason(context.getReason())
|
||||
.warnId(warningId)
|
||||
.serverName(guild.getName())
|
||||
.build();
|
||||
Long serverId = server.getId();
|
||||
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification, server.getId());
|
||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
futures.add(messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage));
|
||||
log.debug("Logging warning for server {}.", server.getId());
|
||||
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())));
|
||||
}
|
||||
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context, server.getId());
|
||||
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(futures);
|
||||
return FutureUtils.toSingleFuture(futures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> warnUserWithLog(WarnContext context) {
|
||||
return notifyAndLogFullUserWarning(context).thenAccept(aVoid ->
|
||||
self.persistWarning(context)
|
||||
);
|
||||
return notifyAndLogFullUserWarning(context)
|
||||
.thenAccept(aVoid -> self.persistWarning(context));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -124,8 +153,15 @@ public class WarnServiceBean implements WarnService {
|
||||
context.getWarnId(), context.getGuild().getId(), context.getWarnedMember().getId(), context.getMember().getId());
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(context.getWarnedMember());
|
||||
AUserInAServer warningUser = userInServerManagementService.loadOrCreateUser(context.getMember());
|
||||
warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
|
||||
Warning createdWarning = warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
if(context.getInfractionId() != null) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(context.getInfractionId());
|
||||
createdWarning.setInfraction(infraction);
|
||||
}
|
||||
ServerUser warnedServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerUser warningServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerChannelMessage commandMessage = ServerChannelMessage.fromMessage(context.getMessage());
|
||||
warningCreatedListenerManager.sendWarningCreatedEvent(createdWarning.getWarnId(), warnedServerUser, warningServerUser, context.getReason(), commandMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -235,10 +271,13 @@ public class WarnServiceBean implements WarnService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decayWarning(Warning warning, Instant now) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), now);
|
||||
warning.setDecayDate(now);
|
||||
public void decayWarning(Warning warning, Instant decayDate) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), decayDate);
|
||||
warning.setDecayDate(decayDate);
|
||||
warning.setDecayed(true);
|
||||
if(warning.getInfraction() != null) {
|
||||
infractionService.decayInfraction(warning.getInfraction());
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
||||
@@ -307,8 +346,7 @@ public class WarnServiceBean implements WarnService {
|
||||
.warnings(warnDecayWarnings)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WARN_DECAY_LOG_TEMPLATE_KEY, warnDecayLogModel, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.repository.InfractionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class InfractionManagementServiceBean implements InfractionManagementService{
|
||||
|
||||
@Autowired
|
||||
private InfractionRepository infractionRepository;
|
||||
|
||||
@Override
|
||||
public Infraction createInfraction(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction infraction = Infraction
|
||||
.builder()
|
||||
.user(aUserInAServer)
|
||||
.server(aUserInAServer.getServerReference())
|
||||
.points(points)
|
||||
.build();
|
||||
return infractionRepository.save(infraction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Infraction> getActiveInfractionsForUser(AUserInAServer aUserInAServer) {
|
||||
return infractionRepository.findByUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Infraction loadInfraction(Long infraction) {
|
||||
return infractionRepository.getOne(infraction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,10 +70,15 @@ public class WarnManagementServiceBean implements WarnManagementService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
public Long getActiveWarnCountForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Warning> getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.findByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Warning> findByIdOptional(Long id, Long serverId) {
|
||||
return warnRepository.findByWarnId_IdAndWarnId_ServerId(id, serverId);
|
||||
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?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="feature.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -6,10 +6,9 @@
|
||||
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="warn-decay-job-update_schedule">
|
||||
<update tableName="scheduler_job">
|
||||
<column name="cron_expression" value="0 0 0 * * ?"/>
|
||||
<where>name='warnDecayJob'</where>
|
||||
</update>
|
||||
<changeSet author="Sheldan" id="infraction_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="infractions"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?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-table">
|
||||
<createTable tableName="infraction">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_infraction"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="points" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="decayed_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="decayed" type="BOOLEAN"/>
|
||||
<column name="infraction_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="infraction" constraintName="fk_infraction_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_user_in_server_id" baseTableName="infraction" constraintName="fk_infraction_user_in_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS infraction_update_trigger ON infraction;
|
||||
CREATE TRIGGER infraction_update_trigger BEFORE UPDATE ON infraction FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS infraction_insert_trigger ON infraction;
|
||||
CREATE TRIGGER infraction_insert_trigger BEFORE INSERT ON infraction FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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="infraction.xml" relativeToChangelogFile="true"/>
|
||||
<include file="warning.xml" relativeToChangelogFile="true"/>
|
||||
</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="warning-infraction_id">
|
||||
<addColumn tableName="warning">
|
||||
<column name="infraction_id" type="BIGINT" />
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_id" baseTableName="warning" constraintName="fk_warning_infraction"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="infraction" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -11,4 +11,5 @@
|
||||
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -7,6 +7,9 @@ abstracto.systemConfigs.reactionReportCooldownSeconds.longValue=300
|
||||
abstracto.featureFlags.moderation.featureName=moderation
|
||||
abstracto.featureFlags.moderation.enabled=false
|
||||
|
||||
abstracto.featureFlags.infractions.featureName=infractions
|
||||
abstracto.featureFlags.infractions.enabled=false
|
||||
|
||||
abstracto.featureFlags.reportReactions.featureName=reportReactions
|
||||
abstracto.featureFlags.reportReactions.enabled=false
|
||||
|
||||
@@ -42,6 +45,31 @@ abstracto.featureModes.warnDecayLogging.featureName=warnings
|
||||
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
|
||||
abstracto.featureModes.warnDecayLogging.enabled=true
|
||||
|
||||
abstracto.featureModes.infractionReporting.featureName=infractions
|
||||
abstracto.featureModes.infractionReporting.mode=infractionReporting
|
||||
abstracto.featureModes.infractionReporting.enabled=true
|
||||
|
||||
abstracto.systemConfigs.infractionLvl1.name=infractionLvl1
|
||||
abstracto.systemConfigs.infractionLvl1.longValue=10
|
||||
|
||||
abstracto.systemConfigs.infractionLvl2.name=infractionLvl2
|
||||
abstracto.systemConfigs.infractionLvl2.longValue=20
|
||||
|
||||
abstracto.systemConfigs.infractionLvl3.name=infractionLvl3
|
||||
abstracto.systemConfigs.infractionLvl3.longValue=30
|
||||
|
||||
abstracto.systemConfigs.infractionLvl4.name=infractionLvl4
|
||||
abstracto.systemConfigs.infractionLvl4.longValue=40
|
||||
|
||||
abstracto.systemConfigs.infractionLvl5.name=infractionLvl5
|
||||
abstracto.systemConfigs.infractionLvl5.longValue=50
|
||||
|
||||
abstracto.systemConfigs.infractionLevels.name=infractionLevels
|
||||
abstracto.systemConfigs.infractionLevels.longValue=5
|
||||
|
||||
abstracto.systemConfigs.warnInfractionPoints.name=warnInfractionPoints
|
||||
abstracto.systemConfigs.warnInfractionPoints.longValue=0
|
||||
|
||||
abstracto.featureModes.automaticWarnDecayLogging.featureName=warnDecay
|
||||
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
||||
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
|
||||
|
||||
@@ -49,7 +49,7 @@ public class MyWarningsTest {
|
||||
Long activeWarnCount = 8L;
|
||||
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(noParameter.getAuthor())).thenReturn(aUserInAServer);
|
||||
when(warnManagementService.getActiveWarnsForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
||||
when(warnManagementService.getActiveWarnCountForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
||||
Long totalWarnCount = 10L;
|
||||
when(warnManagementService.getTotalWarnsForUser(aUserInAServer)).thenReturn(totalWarnCount);
|
||||
CommandResult result = testUnit.execute(noParameter);
|
||||
|
||||
@@ -29,6 +29,7 @@ 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;
|
||||
@@ -134,6 +135,9 @@ public class WarnServiceBeanTest {
|
||||
@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;
|
||||
@@ -204,6 +208,7 @@ public class WarnServiceBeanTest {
|
||||
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());
|
||||
|
||||
@@ -97,7 +97,7 @@ public class WarnManagementServiceBeanTest {
|
||||
public void testActiveWarnCountOfUser() {
|
||||
Long count = 5L;
|
||||
when(warnRepository.countByWarnedUserAndDecayedFalse(warnedUser)).thenReturn(count);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnsForUser(warnedUser);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnCountForUser(warnedUser);
|
||||
Assert.assertEquals(count, activeWarnsForUserCount);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user