mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-19 21:17:43 +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:
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
|||||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||||
import dev.sheldan.abstracto.logging.model.template.MemberJoinLogModel;
|
import dev.sheldan.abstracto.logging.model.template.MemberJoinLogModel;
|
||||||
@@ -43,7 +44,11 @@ public class JoinLogger implements AsyncJoinListener {
|
|||||||
.build();
|
.build();
|
||||||
log.debug("Logging join event for user {} in server {}.", listenerModel.getMember().getIdLong(), listenerModel.getServerId());
|
log.debug("Logging join event for user {} in server {}.", listenerModel.getMember().getIdLong(), listenerModel.getServerId());
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_JOIN_TEMPLATE, model, listenerModel.getServerId());
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_JOIN_TEMPLATE, model, listenerModel.getServerId());
|
||||||
postTargetService.sendEmbedInPostTarget(messageToSend, LoggingPostTarget.JOIN_LOG, listenerModel.getServerId());
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, LoggingPostTarget.JOIN_LOG, listenerModel.getServerId()))
|
||||||
|
.exceptionally(throwable -> {
|
||||||
|
log.error("Failed to send member joining log.", throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
return DefaultListenerResult.PROCESSED;
|
return DefaultListenerResult.PROCESSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
|||||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@@ -46,7 +47,11 @@ public class LeaveLogger implements AsyncLeaveListener {
|
|||||||
.build();
|
.build();
|
||||||
log.debug("Logging leave event for user {} in server {}.", listenerModel.getUser().getIdLong(), listenerModel.getServerId());
|
log.debug("Logging leave event for user {} in server {}.", listenerModel.getUser().getIdLong(), listenerModel.getServerId());
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_LEAVE_TEMPLATE, model, listenerModel.getServerId());
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_LEAVE_TEMPLATE, model, listenerModel.getServerId());
|
||||||
postTargetService.sendEmbedInPostTarget(messageToSend, LoggingPostTarget.LEAVE_LOG, listenerModel.getServerId());
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, LoggingPostTarget.LEAVE_LOG, listenerModel.getServerId()))
|
||||||
|
.exceptionally(throwable -> {
|
||||||
|
log.error("Failed to send member leaving log.", throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
return DefaultListenerResult.PROCESSED;
|
return DefaultListenerResult.PROCESSED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,8 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
|||||||
.member(authorMember)
|
.member(authorMember)
|
||||||
.build();
|
.build();
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_DELETED_TEMPLATE, logModel, messageFromCache.getServerId());
|
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_DELETED_TEMPLATE, logModel, messageFromCache.getServerId());
|
||||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId())).exceptionally(throwable -> {
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId()))
|
||||||
|
.exceptionally(throwable -> {
|
||||||
log.error("Failed to send message deleted log.", throwable);
|
log.error("Failed to send message deleted log.", throwable);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
|||||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||||
import dev.sheldan.abstracto.logging.model.template.MessageDeletedAttachmentLog;
|
import dev.sheldan.abstracto.logging.model.template.MessageDeletedAttachmentLog;
|
||||||
@@ -65,7 +66,11 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
|||||||
.member(messageAfter.getMember())
|
.member(messageAfter.getMember())
|
||||||
.build();
|
.build();
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, lodModel, model.getServerId());
|
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, lodModel, model.getServerId());
|
||||||
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.EDIT_LOG, model.getServerId());
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.EDIT_LOG, model.getServerId()))
|
||||||
|
.exceptionally(throwable -> {
|
||||||
|
log.error("Failed to send message edited log.", throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
if(attachmentWasRemoved) {
|
if(attachmentWasRemoved) {
|
||||||
log.info("Attachment count changed. Old {}, new {}.", attachmentCountBefore, attachmentCountAfter);
|
log.info("Attachment count changed. Old {}, new {}.", attachmentCountBefore, attachmentCountAfter);
|
||||||
@@ -75,7 +80,7 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
|||||||
).collect(Collectors.toList());
|
).collect(Collectors.toList());
|
||||||
log.debug("Logging deletion of {} attachments.", removedAttachments.size());
|
log.debug("Logging deletion of {} attachments.", removedAttachments.size());
|
||||||
for (int i = 0; i < removedAttachments.size(); i++) {
|
for (int i = 0; i < removedAttachments.size(); i++) {
|
||||||
MessageDeletedAttachmentLog log = MessageDeletedAttachmentLog
|
MessageDeletedAttachmentLog attachmentModel = MessageDeletedAttachmentLog
|
||||||
.builder()
|
.builder()
|
||||||
.imageUrl(removedAttachments.get(i).getProxyUrl())
|
.imageUrl(removedAttachments.get(i).getProxyUrl())
|
||||||
.counter(i + 1)
|
.counter(i + 1)
|
||||||
@@ -84,8 +89,12 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
|||||||
.member(messageAfter.getMember())
|
.member(messageAfter.getMember())
|
||||||
.build();
|
.build();
|
||||||
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_EDITED_ATTACHMENT_REMOVED_TEMPLATE,
|
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_EDITED_ATTACHMENT_REMOVED_TEMPLATE,
|
||||||
log, messageBefore.getServerId());
|
attachmentModel, messageBefore.getServerId());
|
||||||
postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageBefore.getServerId());
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageBefore.getServerId()))
|
||||||
|
.exceptionally(throwable -> {
|
||||||
|
log.error("Failed to send message edited attachment log.", throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return DefaultListenerResult.PROCESSED;
|
return DefaultListenerResult.PROCESSED;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public class MyWarnings extends AbstractConditionableCommand {
|
|||||||
public CommandResult execute(CommandContext commandContext) {
|
public CommandResult execute(CommandContext commandContext) {
|
||||||
MyWarningsModel model = (MyWarningsModel) ContextConverter.fromCommandContext(commandContext, MyWarningsModel.class);
|
MyWarningsModel model = (MyWarningsModel) ContextConverter.fromCommandContext(commandContext, MyWarningsModel.class);
|
||||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||||
Long currentWarnCount = warnManagementService.getActiveWarnsForUser(userInAServer);
|
Long currentWarnCount = warnManagementService.getActiveWarnCountForUser(userInAServer);
|
||||||
model.setCurrentWarnCount(currentWarnCount);
|
model.setCurrentWarnCount(currentWarnCount);
|
||||||
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(userInAServer);
|
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(userInAServer);
|
||||||
model.setTotalWarnCount(totalWarnCount);
|
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 countByWarnedUser(AUserInAServer aUserInAServer);
|
||||||
|
|
||||||
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||||
|
List<Warning> findByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||||
|
|
||||||
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@@ -139,20 +138,14 @@ public class BanServiceBean implements BanService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
||||||
CompletableFuture<Void> completableFuture;
|
|
||||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||||
log.debug("Sending ban log message in guild {}.", guildId);
|
log.debug("Sending ban log message in guild {}.", guildId);
|
||||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId);
|
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId));
|
||||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public CompletableFuture<Void> sendUnBanLogMessage(UnBanLog banLog, Long guildId, String template) {
|
public CompletableFuture<Void> sendUnBanLogMessage(UnBanLog banLog, Long guildId, String template) {
|
||||||
CompletableFuture<Void> completableFuture;
|
|
||||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||||
log.debug("Sending unban log message in guild {}.", guildId);
|
log.debug("Sending unban log message in guild {}.", guildId);
|
||||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId);
|
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId));
|
||||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
private CompletableFuture<Void> sendKickLog(KickLogModel kickLogModel) {
|
||||||
CompletableFuture<Void> completableFuture;
|
|
||||||
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, kickLogModel.getGuild().getIdLong());
|
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, kickLogModel.getGuild().getIdLong());
|
||||||
log.debug("Sending kick log message in guild {}.", 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 FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -244,21 +244,15 @@ public class MuteServiceBean implements MuteService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> sendMuteLog(MuteContext muteLogModel, AServer server) {
|
private CompletableFuture<Void> sendMuteLog(MuteContext muteLogModel, AServer server) {
|
||||||
CompletableFuture<Void> completableFuture;
|
|
||||||
log.debug("Sending mute log to the mute post target.");
|
log.debug("Sending mute log to the mute post target.");
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId());
|
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()));
|
||||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) {
|
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());
|
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());
|
MessageToSend message = templateService.renderEmbedTemplate(UN_MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId());
|
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId()));
|
||||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
|
||||||
return completableFuture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -100,10 +100,14 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser reporter) {
|
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser 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());
|
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||||
updateModerationUserReportCooldown(reporter);
|
updateModerationUserReportCooldown(reporter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void updateModerationUserReportCooldown(ServerUser reporter) {
|
public void updateModerationUserReportCooldown(ServerUser reporter) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package dev.sheldan.abstracto.moderation.service;
|
package dev.sheldan.abstracto.moderation.service;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
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.ServerSpecificId;
|
||||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
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.core.utils.FutureUtils;
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.WarningDecayFeatureConfig;
|
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.WarnDecayMode;
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarningMode;
|
import dev.sheldan.abstracto.moderation.config.feature.mode.WarningMode;
|
||||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarnDecayPostTarget;
|
import dev.sheldan.abstracto.moderation.config.posttarget.WarnDecayPostTarget;
|
||||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarningPostTarget;
|
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.database.Warning;
|
||||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnContext;
|
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.command.WarnNotification;
|
||||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayLogModel;
|
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.job.WarnDecayWarning;
|
||||||
import dev.sheldan.abstracto.moderation.model.template.listener.WarnDecayMemberNotificationModel;
|
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.moderation.service.management.WarnManagementService;
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
@@ -85,6 +90,18 @@ public class WarnServiceBean implements WarnService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private WarnServiceBean self;
|
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_LOG_TEMPLATE = "warn_log";
|
||||||
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
|
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
|
||||||
public static final String WARNINGS_COUNTER_KEY = "WARNINGS";
|
public static final String WARNINGS_COUNTER_KEY = "WARNINGS";
|
||||||
@@ -100,22 +117,34 @@ public class WarnServiceBean implements WarnService {
|
|||||||
Member warningMember = context.getMember();
|
Member warningMember = context.getMember();
|
||||||
Guild guild = warnedMember.getGuild();
|
Guild guild = warnedMember.getGuild();
|
||||||
log.info("User {} is warning {} in server {}", warnedMember.getId(), warningMember.getId(), guild.getIdLong());
|
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());
|
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));
|
futures.add(messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage));
|
||||||
log.debug("Logging warning for server {}.", server.getId());
|
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());
|
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context, server.getId());
|
||||||
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
||||||
|
|
||||||
return FutureUtils.toSingleFutureGeneric(futures);
|
return FutureUtils.toSingleFuture(futures);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> warnUserWithLog(WarnContext context) {
|
public CompletableFuture<Void> warnUserWithLog(WarnContext context) {
|
||||||
return notifyAndLogFullUserWarning(context).thenAccept(aVoid ->
|
return notifyAndLogFullUserWarning(context)
|
||||||
self.persistWarning(context)
|
.thenAccept(aVoid -> self.persistWarning(context));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
@@ -124,8 +153,15 @@ public class WarnServiceBean implements WarnService {
|
|||||||
context.getWarnId(), context.getGuild().getId(), context.getWarnedMember().getId(), context.getMember().getId());
|
context.getWarnId(), context.getGuild().getId(), context.getWarnedMember().getId(), context.getMember().getId());
|
||||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(context.getWarnedMember());
|
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(context.getWarnedMember());
|
||||||
AUserInAServer warningUser = userInServerManagementService.loadOrCreateUser(context.getMember());
|
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
|
@Override
|
||||||
@@ -235,10 +271,13 @@ public class WarnServiceBean implements WarnService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void decayWarning(Warning warning, Instant now) {
|
public void decayWarning(Warning warning, Instant decayDate) {
|
||||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), now);
|
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), decayDate);
|
||||||
warning.setDecayDate(now);
|
warning.setDecayDate(decayDate);
|
||||||
warning.setDecayed(true);
|
warning.setDecayed(true);
|
||||||
|
if(warning.getInfraction() != null) {
|
||||||
|
infractionService.decayInfraction(warning.getInfraction());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
||||||
@@ -307,8 +346,7 @@ public class WarnServiceBean implements WarnService {
|
|||||||
.warnings(warnDecayWarnings)
|
.warnings(warnDecayWarnings)
|
||||||
.build();
|
.build();
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WARN_DECAY_LOG_TEMPLATE_KEY, warnDecayLogModel, serverId);
|
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(postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId()));
|
||||||
return FutureUtils.toSingleFutureGeneric(messageFutures);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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
|
@Override
|
||||||
public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
public Long getActiveWarnCountForUser(AUserInAServer aUserInAServer) {
|
||||||
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);
|
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Warning> getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||||
|
return warnRepository.findByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<Warning> findByIdOptional(Long id, Long serverId) {
|
public Optional<Warning> findByIdOptional(Long id, Long serverId) {
|
||||||
return warnRepository.findByWarnId_IdAndWarnId_ServerId(id, 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
|
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/dbchangelog-ext dbchangelog.xsd
|
||||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
<changeSet author="Sheldan" id="warn-decay-job-update_schedule">
|
<changeSet author="Sheldan" id="infraction_feature-insertion">
|
||||||
<update tableName="scheduler_job">
|
<insert tableName="feature">
|
||||||
<column name="cron_expression" value="0 0 0 * * ?"/>
|
<column name="key" value="infractions"/>
|
||||||
<where>name='warnDecayJob'</where>
|
</insert>
|
||||||
</update>
|
|
||||||
</changeSet>
|
</changeSet>
|
||||||
</databaseChangeLog>
|
</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.15/collection.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="1.2.16/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.4/collection.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -7,6 +7,9 @@ abstracto.systemConfigs.reactionReportCooldownSeconds.longValue=300
|
|||||||
abstracto.featureFlags.moderation.featureName=moderation
|
abstracto.featureFlags.moderation.featureName=moderation
|
||||||
abstracto.featureFlags.moderation.enabled=false
|
abstracto.featureFlags.moderation.enabled=false
|
||||||
|
|
||||||
|
abstracto.featureFlags.infractions.featureName=infractions
|
||||||
|
abstracto.featureFlags.infractions.enabled=false
|
||||||
|
|
||||||
abstracto.featureFlags.reportReactions.featureName=reportReactions
|
abstracto.featureFlags.reportReactions.featureName=reportReactions
|
||||||
abstracto.featureFlags.reportReactions.enabled=false
|
abstracto.featureFlags.reportReactions.enabled=false
|
||||||
|
|
||||||
@@ -42,6 +45,31 @@ abstracto.featureModes.warnDecayLogging.featureName=warnings
|
|||||||
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
|
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
|
||||||
abstracto.featureModes.warnDecayLogging.enabled=true
|
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.featureName=warnDecay
|
||||||
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
||||||
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
|
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class MyWarningsTest {
|
|||||||
Long activeWarnCount = 8L;
|
Long activeWarnCount = 8L;
|
||||||
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
|
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||||
when(userInServerManagementService.loadOrCreateUser(noParameter.getAuthor())).thenReturn(aUserInAServer);
|
when(userInServerManagementService.loadOrCreateUser(noParameter.getAuthor())).thenReturn(aUserInAServer);
|
||||||
when(warnManagementService.getActiveWarnsForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
when(warnManagementService.getActiveWarnCountForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
||||||
Long totalWarnCount = 10L;
|
Long totalWarnCount = 10L;
|
||||||
when(warnManagementService.getTotalWarnsForUser(aUserInAServer)).thenReturn(totalWarnCount);
|
when(warnManagementService.getTotalWarnsForUser(aUserInAServer)).thenReturn(totalWarnCount);
|
||||||
CommandResult result = testUnit.execute(noParameter);
|
CommandResult result = testUnit.execute(noParameter);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.*;
|
import org.mockito.*;
|
||||||
import org.mockito.junit.MockitoJUnitRunner;
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -134,6 +135,9 @@ public class WarnServiceBeanTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private DefaultConfigManagementService defaultConfigManagementService;
|
private DefaultConfigManagementService defaultConfigManagementService;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private FeatureFlagService featureFlagService;
|
||||||
|
|
||||||
private static final String NOTIFICATION_TEXT = "text";
|
private static final String NOTIFICATION_TEXT = "text";
|
||||||
private static final String GUILD_NAME = "guild";
|
private static final String GUILD_NAME = "guild";
|
||||||
private static final Long SERVER_ID = 4L;
|
private static final Long SERVER_ID = 4L;
|
||||||
@@ -204,6 +208,7 @@ public class WarnServiceBeanTest {
|
|||||||
public void testWarnFullUser() {
|
public void testWarnFullUser() {
|
||||||
setupWarnContext();
|
setupWarnContext();
|
||||||
setupMocksForWarning();
|
setupMocksForWarning();
|
||||||
|
when(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, SERVER_ID)).thenReturn(false);
|
||||||
CompletableFuture<Void> future = testUnit.notifyAndLogFullUserWarning(context);
|
CompletableFuture<Void> future = testUnit.notifyAndLogFullUserWarning(context);
|
||||||
future.join();
|
future.join();
|
||||||
Assert.assertFalse(future.isCompletedExceptionally());
|
Assert.assertFalse(future.isCompletedExceptionally());
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public class WarnManagementServiceBeanTest {
|
|||||||
public void testActiveWarnCountOfUser() {
|
public void testActiveWarnCountOfUser() {
|
||||||
Long count = 5L;
|
Long count = 5L;
|
||||||
when(warnRepository.countByWarnedUserAndDecayedFalse(warnedUser)).thenReturn(count);
|
when(warnRepository.countByWarnedUserAndDecayedFalse(warnedUser)).thenReturn(count);
|
||||||
Long activeWarnsForUserCount = testUnit.getActiveWarnsForUser(warnedUser);
|
Long activeWarnsForUserCount = testUnit.getActiveWarnCountForUser(warnedUser);
|
||||||
Assert.assertEquals(count, activeWarnsForUserCount);
|
Assert.assertEquals(count, activeWarnsForUserCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.config.feature;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||||
|
import dev.sheldan.abstracto.moderation.config.posttarget.InfractionPostTarget;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class InfractionFeatureConfig implements FeatureConfig {
|
||||||
|
|
||||||
|
public static final String INFRACTION_LEVELS = "infractionLevels";
|
||||||
|
public static final String INFRACTION_LEVEL_PREFIX = "infractionLevel";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return ModerationFeatureDefinition.INFRACTIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getRequiredSystemConfigKeys() {
|
||||||
|
return Arrays.asList(INFRACTION_LEVELS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||||
|
return Arrays.asList(InfractionPostTarget.INFRACTION_NOTIFICATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,8 @@ public enum ModerationFeatureDefinition implements FeatureDefinition {
|
|||||||
AUTOMATIC_WARN_DECAY("warnDecay"),
|
AUTOMATIC_WARN_DECAY("warnDecay"),
|
||||||
USER_NOTES("userNotes"),
|
USER_NOTES("userNotes"),
|
||||||
INVITE_FILTER("inviteFilter"),
|
INVITE_FILTER("inviteFilter"),
|
||||||
REPORT_REACTIONS("reportReactions")
|
REPORT_REACTIONS("reportReactions"),
|
||||||
|
INFRACTIONS("infractions")
|
||||||
;
|
;
|
||||||
|
|
||||||
private final String key;
|
private final String key;
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import java.util.List;
|
|||||||
@Component
|
@Component
|
||||||
public class WarningFeatureConfig implements FeatureConfig {
|
public class WarningFeatureConfig implements FeatureConfig {
|
||||||
|
|
||||||
|
public static final String WARN_INFRACTION_POINTS = "warnInfractionPoints";
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WarningDecayFeatureConfig warningDecayFeatureConfig;
|
private WarningDecayFeatureConfig warningDecayFeatureConfig;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.config.posttarget;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum InfractionPostTarget implements PostTargetEnum {
|
||||||
|
INFRACTION_NOTIFICATION("infractionNotification");
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
InfractionPostTarget(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.listener;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||||
|
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
|
||||||
|
import dev.sheldan.abstracto.moderation.model.listener.InfractionLevelChangedEventModel;
|
||||||
|
|
||||||
|
public interface InfractionLevelChangedListener extends FeatureAwareListener<InfractionLevelChangedEventModel, DefaultListenerResult> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.listener;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||||
|
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
|
||||||
|
import dev.sheldan.abstracto.moderation.model.listener.WarningCreatedEventModel;
|
||||||
|
|
||||||
|
public interface WarningCreatedListener extends FeatureAwareListener<WarningCreatedEventModel, DefaultListenerResult> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.model.database;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="infraction")
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class Infraction {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
@Column(name = "id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "infraction_user_in_server_id", nullable = false)
|
||||||
|
private AUserInAServer user;
|
||||||
|
|
||||||
|
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||||
|
private AServer server;
|
||||||
|
|
||||||
|
@Column(name = "points")
|
||||||
|
private Long points;
|
||||||
|
|
||||||
|
@Column(name = "decayed")
|
||||||
|
private Boolean decayed;
|
||||||
|
|
||||||
|
@Column(name = "decayed_date")
|
||||||
|
private Instant decayedDate;
|
||||||
|
|
||||||
|
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||||
|
private Instant created;
|
||||||
|
|
||||||
|
@Column(name = "updated", insertable = false, updatable = false)
|
||||||
|
private Instant updated;
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ public class Warning implements Serializable {
|
|||||||
@Setter
|
@Setter
|
||||||
private ServerSpecificId warnId;
|
private ServerSpecificId warnId;
|
||||||
|
|
||||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||||
@MapsId("serverId")
|
@MapsId("serverId")
|
||||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||||
private AServer server;
|
private AServer server;
|
||||||
@@ -90,4 +90,10 @@ public class Warning implements Serializable {
|
|||||||
@Column(name = "updated", insertable = false, updatable = false)
|
@Column(name = "updated", insertable = false, updatable = false)
|
||||||
private Instant updated;
|
private Instant updated;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@OneToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "infraction_id")
|
||||||
|
private Infraction infraction;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.model.listener;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class InfractionLevelChangedEventModel implements FeatureAwareListenerModel {
|
||||||
|
private Integer oldLevel;
|
||||||
|
private Long oldPoints;
|
||||||
|
private Integer newLevel;
|
||||||
|
private Long newPoints;
|
||||||
|
private Long userId;
|
||||||
|
private Long serverId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.model.listener;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class WarningCreatedEventModel implements FeatureAwareListenerModel {
|
||||||
|
private Long warningId;
|
||||||
|
private Long warnedUserId;
|
||||||
|
private Long serverId;
|
||||||
|
private Long warningUserId;
|
||||||
|
private Long warningChannelId;
|
||||||
|
private Long warningMessageId;
|
||||||
|
private String reason;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.model.template;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
public class InfractionLevelChangeModel {
|
||||||
|
private Long newPoints;
|
||||||
|
private Long oldPoints;
|
||||||
|
private Integer newLevel;
|
||||||
|
private Integer oldLevel;
|
||||||
|
private MemberDisplay member;
|
||||||
|
}
|
||||||
@@ -26,4 +26,5 @@ public class WarnContext extends SlimUserInitiatedServerContext {
|
|||||||
* The persisted {@link Warning} object from the database containing the information about the warning
|
* The persisted {@link Warning} object from the database containing the information about the warning
|
||||||
*/
|
*/
|
||||||
private Long warnId;
|
private Long warnId;
|
||||||
|
private Long infractionId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.service;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public interface InfractionService {
|
||||||
|
void decayInfraction(Infraction infraction);
|
||||||
|
Long getActiveInfractionPointsForUser(AUserInAServer aUserInAServer);
|
||||||
|
CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer aUserInAServer, Long points);
|
||||||
|
CompletableFuture<Void> createInfractionNotification(AUserInAServer aUserInAServer, Long points);
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.service.management;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface InfractionManagementService {
|
||||||
|
Infraction createInfraction(AUserInAServer aUserInAServer, Long points);
|
||||||
|
List<Infraction> getActiveInfractionsForUser(AUserInAServer aUserInAServer);
|
||||||
|
Infraction loadInfraction(Long infraction);
|
||||||
|
}
|
||||||
@@ -16,7 +16,8 @@ public interface WarnManagementService {
|
|||||||
Long getTotalWarnsForUser(AUserInAServer aUserInAServer);
|
Long getTotalWarnsForUser(AUserInAServer aUserInAServer);
|
||||||
List<Warning> getAllWarnsForUser(AUserInAServer aUserInAServer);
|
List<Warning> getAllWarnsForUser(AUserInAServer aUserInAServer);
|
||||||
List<Warning> getAllWarningsOfServer(AServer server);
|
List<Warning> getAllWarningsOfServer(AServer server);
|
||||||
Long getActiveWarnsForUser(AUserInAServer aUserInAServer);
|
Long getActiveWarnCountForUser(AUserInAServer aUserInAServer);
|
||||||
|
List<Warning> getActiveWarnsForUser(AUserInAServer aUserInAServer);
|
||||||
Optional<Warning> findByIdOptional(Long id, Long serverId);
|
Optional<Warning> findByIdOptional(Long id, Long serverId);
|
||||||
Warning findById(Long id, Long serverId);
|
Warning findById(Long id, Long serverId);
|
||||||
List<Warning> getWarningsViaId(List<Long> warnIds, Long serverId);
|
List<Warning> getWarningsViaId(List<Long> warnIds, Long serverId);
|
||||||
|
|||||||
@@ -286,8 +286,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
.channel(channel)
|
.channel(channel)
|
||||||
.build();
|
.build();
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_notification_message", modMailNotificationModel, channel.getGuild().getIdLong());
|
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_notification_message", modMailNotificationModel, channel.getGuild().getIdLong());
|
||||||
List<CompletableFuture<Message>> modmailping = postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_PING, serverId);
|
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_PING, serverId));
|
||||||
return CompletableFuture.allOf(modmailping.toArray(new CompletableFuture[0]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -660,7 +659,9 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
.thenCompose(list -> list.getMainFuture().thenCompose(unused -> {
|
.thenCompose(list -> list.getMainFuture().thenCompose(unused -> {
|
||||||
list.getFutures().forEach(messageCompletableFuture -> {
|
list.getFutures().forEach(messageCompletableFuture -> {
|
||||||
Message message = messageCompletableFuture.join();
|
Message message = messageCompletableFuture.join();
|
||||||
|
if(message != null) {
|
||||||
undoActions.add(UndoActionInstance.getMessageDeleteAction(message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong()));
|
undoActions.add(UndoActionInstance.getMessageDeleteAction(message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong()));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return memberService.getMemberInServerAsync(serverId, userId).thenCompose(member ->
|
return memberService.getMemberInServerAsync(serverId, userId).thenCompose(member ->
|
||||||
self.afterSuccessfulLog(modMailThreadId, closingContext.getNotifyUser(), member, undoActions)
|
self.afterSuccessfulLog(modMailThreadId, closingContext.getNotifyUser(), member, undoActions)
|
||||||
|
|||||||
@@ -115,7 +115,12 @@ public class ProfanityFilterServiceBean implements ProfanityFilterService {
|
|||||||
Long profanityRegexId = foundProfanityRegex.getId();
|
Long profanityRegexId = foundProfanityRegex.getId();
|
||||||
return FutureUtils.toSingleFutureGeneric(messageFutures).thenCompose(aVoid -> {
|
return FutureUtils.toSingleFutureGeneric(messageFutures).thenCompose(aVoid -> {
|
||||||
Message createdMessage = messageFutures.get(0).join();
|
Message createdMessage = messageFutures.get(0).join();
|
||||||
|
if(createdMessage != null) {
|
||||||
return self.afterReportCreation(message, serverId, profanityRegexId, createdMessage);
|
return self.afterReportCreation(message, serverId, profanityRegexId, createdMessage);
|
||||||
|
} else {
|
||||||
|
log.warn("No profanity report message created about message {} in server {} - possibly post target disabled.", message.getIdLong(), message.getGuild().getIdLong());
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package dev.sheldan.abstracto.starboard.service;
|
package dev.sheldan.abstracto.starboard.listener.manager;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
|
||||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
|
||||||
import dev.sheldan.abstracto.starboard.listener.StarboardPostCreatedListener;
|
import dev.sheldan.abstracto.starboard.listener.StarboardPostCreatedListener;
|
||||||
import dev.sheldan.abstracto.starboard.model.StarboardPostCreatedModel;
|
import dev.sheldan.abstracto.starboard.model.StarboardPostCreatedModel;
|
||||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||||
@@ -28,15 +26,6 @@ public class StarboardPostCreatedListenerManager {
|
|||||||
@Qualifier("starboardCreatedListenerExecutor")
|
@Qualifier("starboardCreatedListenerExecutor")
|
||||||
private TaskExecutor starboardCreatedExecutor;
|
private TaskExecutor starboardCreatedExecutor;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private StarboardPostCreatedListenerManager self;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FeatureConfigService featureConfigService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FeatureFlagService featureFlagService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ListenerService listenerService;
|
private ListenerService listenerService;
|
||||||
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
package dev.sheldan.abstracto.starboard.service;
|
package dev.sheldan.abstracto.starboard.listener.manager;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
|
||||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
|
||||||
import dev.sheldan.abstracto.starboard.listener.StarboardPostDeletedListener;
|
import dev.sheldan.abstracto.starboard.listener.StarboardPostDeletedListener;
|
||||||
import dev.sheldan.abstracto.starboard.model.StarboardPostDeletedModel;
|
import dev.sheldan.abstracto.starboard.model.StarboardPostDeletedModel;
|
||||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||||
@@ -28,15 +26,6 @@ public class StarboardPostDeletedListenerManager {
|
|||||||
@Qualifier("starboardDeletedListenerExecutor")
|
@Qualifier("starboardDeletedListenerExecutor")
|
||||||
private TaskExecutor starboardDeletedExecutor;
|
private TaskExecutor starboardDeletedExecutor;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private StarboardPostDeletedListenerManager self;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FeatureConfigService featureConfigService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private FeatureFlagService featureFlagService;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ListenerService listenerService;
|
private ListenerService listenerService;
|
||||||
|
|
||||||
@@ -18,6 +18,8 @@ import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
|||||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureConfig;
|
import dev.sheldan.abstracto.starboard.config.StarboardFeatureConfig;
|
||||||
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
||||||
|
import dev.sheldan.abstracto.starboard.listener.manager.StarboardPostCreatedListenerManager;
|
||||||
|
import dev.sheldan.abstracto.starboard.listener.manager.StarboardPostDeletedListenerManager;
|
||||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||||
import dev.sheldan.abstracto.starboard.model.template.*;
|
import dev.sheldan.abstracto.starboard.model.template.*;
|
||||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||||
@@ -102,6 +104,7 @@ public class StarboardServiceBean implements StarboardService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
|
public CompletableFuture<Void> createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
|
||||||
|
postTargetService.validatePostTarget(StarboardPostTarget.STARBOARD, message.getServerId());
|
||||||
Long starredUserId = starredUser.getUserInServerId();
|
Long starredUserId = starredUser.getUserInServerId();
|
||||||
List<Long> userExceptAuthorIds = userExceptAuthor.stream().map(AUserInAServer::getUserInServerId).collect(Collectors.toList());
|
List<Long> userExceptAuthorIds = userExceptAuthor.stream().map(AUserInAServer::getUserInServerId).collect(Collectors.toList());
|
||||||
Long userReactingId = userReacting.getUserReference().getId();
|
Long userReactingId = userReacting.getUserReference().getId();
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
|||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
import dev.sheldan.abstracto.starboard.config.StarboardFeatureConfig;
|
import dev.sheldan.abstracto.starboard.config.StarboardFeatureConfig;
|
||||||
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
import dev.sheldan.abstracto.starboard.config.StarboardPostTarget;
|
||||||
|
import dev.sheldan.abstracto.starboard.listener.manager.StarboardPostCreatedListenerManager;
|
||||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
import dev.sheldan.abstracto.starboard.model.database.StarboardPost;
|
||||||
import dev.sheldan.abstracto.starboard.model.database.StarboardPostReaction;
|
|
||||||
import dev.sheldan.abstracto.starboard.model.template.*;
|
import dev.sheldan.abstracto.starboard.model.template.*;
|
||||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
import dev.sheldan.abstracto.starboard.service.management.StarboardPostManagementService;
|
||||||
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
import dev.sheldan.abstracto.starboard.service.management.StarboardPostReactorManagementService;
|
||||||
|
|||||||
@@ -114,13 +114,14 @@ public class SuggestionServiceBean implements SuggestionService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Void> createSuggestionMessage(Message commandMessage, String text) {
|
public CompletableFuture<Void> createSuggestionMessage(Message commandMessage, String text) {
|
||||||
// it is done that way, because we cannot always be sure, that the message containsn the member
|
// it is done that way, because we cannot always be sure, that the message contains the member
|
||||||
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
return memberService.getMemberInServerAsync(commandMessage.getGuild().getIdLong(), commandMessage.getAuthor().getIdLong())
|
||||||
.thenCompose(suggester -> self.createMessageWithSuggester(commandMessage, text, suggester));
|
.thenCompose(suggester -> self.createMessageWithSuggester(commandMessage, text, suggester));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> createMessageWithSuggester(Message commandMessage, String text, Member suggester) {
|
public CompletableFuture<Void> createMessageWithSuggester(Message commandMessage, String text, Member suggester) {
|
||||||
|
postTargetService.validatePostTarget(SuggestionPostTarget.SUGGESTION, suggester.getGuild().getIdLong());
|
||||||
Long serverId = suggester.getGuild().getIdLong();
|
Long serverId = suggester.getGuild().getIdLong();
|
||||||
AServer server = serverManagementService.loadServer(serverId);
|
AServer server = serverManagementService.loadServer(serverId);
|
||||||
AUserInAServer userSuggester = userInServerManagementService.loadOrCreateUser(suggester);
|
AUserInAServer userSuggester = userInServerManagementService.loadOrCreateUser(suggester);
|
||||||
@@ -223,6 +224,7 @@ public class SuggestionServiceBean implements SuggestionService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> setSuggestionToFinalState(Member executingMember, Long suggestionId, Message commandMessage, String text, SuggestionState state) {
|
public CompletableFuture<Void> setSuggestionToFinalState(Member executingMember, Long suggestionId, Message commandMessage, String text, SuggestionState state) {
|
||||||
Long serverId = commandMessage.getGuild().getIdLong();
|
Long serverId = commandMessage.getGuild().getIdLong();
|
||||||
|
postTargetService.validatePostTarget(SuggestionPostTarget.SUGGESTION, serverId);
|
||||||
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId);
|
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId);
|
||||||
suggestionManagementService.setSuggestionState(suggestion, state);
|
suggestionManagementService.setSuggestionState(suggestion, state);
|
||||||
cancelSuggestionReminder(suggestion);
|
cancelSuggestionReminder(suggestion);
|
||||||
@@ -340,6 +342,7 @@ public class SuggestionServiceBean implements SuggestionService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> remindAboutSuggestion(ServerSpecificId suggestionId) {
|
public CompletableFuture<Void> remindAboutSuggestion(ServerSpecificId suggestionId) {
|
||||||
Long serverId = suggestionId.getServerId();
|
Long serverId = suggestionId.getServerId();
|
||||||
|
postTargetService.validatePostTarget(SuggestionPostTarget.SUGGESTION_REMINDER, serverId);
|
||||||
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId.getId());
|
Suggestion suggestion = suggestionManagementService.getSuggestion(serverId, suggestionId.getId());
|
||||||
ServerChannelMessage suggestionServerChannelMessage = ServerChannelMessage
|
ServerChannelMessage suggestionServerChannelMessage = ServerChannelMessage
|
||||||
.builder()
|
.builder()
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package dev.sheldan.abstracto.core.commands.channels;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||||
|
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.PostTargetNotValidException;
|
||||||
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class DisablePostTarget extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PostTargetService postTargetService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(CommandContext commandContext) {
|
||||||
|
String targetName = (String) commandContext.getParameters().getParameters().get(0);
|
||||||
|
if(!postTargetService.validPostTarget(targetName)) {
|
||||||
|
throw new PostTargetNotValidException(targetName, postTargetService.getAvailablePostTargets());
|
||||||
|
}
|
||||||
|
postTargetService.disablePostTarget(targetName, commandContext.getGuild().getIdLong());
|
||||||
|
return CommandResult.fromSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
Parameter postTargetName = Parameter
|
||||||
|
.builder()
|
||||||
|
.name("name")
|
||||||
|
.type(String.class)
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
List<Parameter> parameters = Arrays.asList(postTargetName);
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name("disablePosttarget")
|
||||||
|
.module(ChannelsModuleDefinition.CHANNELS)
|
||||||
|
.parameters(parameters)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.help(helpInfo)
|
||||||
|
.templated(true)
|
||||||
|
.causesReaction(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return CoreFeatureDefinition.CORE_FEATURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package dev.sheldan.abstracto.core.commands.channels;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||||
|
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||||
|
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.PostTargetNotValidException;
|
||||||
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class EnablePostTarget extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PostTargetService postTargetService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandResult execute(CommandContext commandContext) {
|
||||||
|
String targetName = (String) commandContext.getParameters().getParameters().get(0);
|
||||||
|
if(!postTargetService.validPostTarget(targetName)) {
|
||||||
|
throw new PostTargetNotValidException(targetName, postTargetService.getAvailablePostTargets());
|
||||||
|
}
|
||||||
|
postTargetService.enablePostTarget(targetName, commandContext.getGuild().getIdLong());
|
||||||
|
return CommandResult.fromSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
Parameter postTargetName = Parameter
|
||||||
|
.builder()
|
||||||
|
.name("name")
|
||||||
|
.type(String.class)
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
List<Parameter> parameters = Arrays.asList(postTargetName);
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name("enablePosttarget")
|
||||||
|
.module(ChannelsModuleDefinition.CHANNELS)
|
||||||
|
.parameters(parameters)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.help(helpInfo)
|
||||||
|
.templated(true)
|
||||||
|
.causesReaction(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return CoreFeatureDefinition.CORE_FEATURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,14 +62,25 @@ public class PostTargetCommand extends AbstractConditionableCommand {
|
|||||||
List<PostTargetModelEntry> postTargetEntries = posttargetDisplayModel.getPostTargets();
|
List<PostTargetModelEntry> postTargetEntries = posttargetDisplayModel.getPostTargets();
|
||||||
postTargets.forEach(target -> {
|
postTargets.forEach(target -> {
|
||||||
Optional<TextChannel> channelFromAChannel = channelService.getChannelFromAChannel(target.getChannelReference());
|
Optional<TextChannel> channelFromAChannel = channelService.getChannelFromAChannel(target.getChannelReference());
|
||||||
PostTargetModelEntry targetEntry = PostTargetModelEntry.builder().channel(channelFromAChannel.orElse(null)).postTarget(target).build();
|
PostTargetModelEntry targetEntry = PostTargetModelEntry
|
||||||
|
.builder()
|
||||||
|
.channel(channelFromAChannel.orElse(null))
|
||||||
|
.disabled(target.getDisabled())
|
||||||
|
.postTarget(target).build();
|
||||||
postTargetEntries.add(targetEntry);
|
postTargetEntries.add(targetEntry);
|
||||||
});
|
});
|
||||||
List<String> postTargetConfigs = postTargetService.getPostTargetsOfEnabledFeatures(server);
|
List<String> postTargetConfigs = postTargetService.getPostTargetsOfEnabledFeatures(server);
|
||||||
postTargetConfigs.forEach(postTargetName -> {
|
postTargetConfigs.forEach(postTargetName -> {
|
||||||
if(postTargetEntries.stream().noneMatch(postTargetModelEntry -> postTargetModelEntry.getPostTarget().getName().equalsIgnoreCase(postTargetName))) {
|
if(postTargetEntries.stream().noneMatch(postTargetModelEntry -> postTargetModelEntry.getPostTarget().getName().equalsIgnoreCase(postTargetName))) {
|
||||||
PostTarget fakeEntry = PostTarget.builder().name(postTargetName).build();
|
PostTarget fakeEntry = PostTarget
|
||||||
PostTargetModelEntry postTargetEntry = PostTargetModelEntry.builder().postTarget(fakeEntry).build();
|
.builder()
|
||||||
|
.name(postTargetName)
|
||||||
|
.build();
|
||||||
|
PostTargetModelEntry postTargetEntry = PostTargetModelEntry
|
||||||
|
.builder()
|
||||||
|
.postTarget(fakeEntry)
|
||||||
|
.disabled(false)
|
||||||
|
.build();
|
||||||
postTargetEntries.add(postTargetEntry);
|
postTargetEntries.add(postTargetEntry);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.config.FeatureConfig;
|
|||||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||||
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
import dev.sheldan.abstracto.core.exception.ChannelNotInGuildException;
|
||||||
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
import dev.sheldan.abstracto.core.exception.GuildNotFoundException;
|
||||||
|
import dev.sheldan.abstracto.core.exception.PostTargetNotUsableException;
|
||||||
import dev.sheldan.abstracto.core.exception.PostTargetNotValidException;
|
import dev.sheldan.abstracto.core.exception.PostTargetNotValidException;
|
||||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||||
@@ -22,6 +23,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
|
||||||
@@ -52,16 +54,26 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendTextInPostTarget(String text, PostTarget target) {
|
public CompletableFuture<Message> sendTextInPostTarget(String text, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
} else {
|
||||||
log.debug("Sending text to post target {}.", target.getName());
|
log.debug("Sending text to post target {}.", target.getName());
|
||||||
return channelService.sendTextToAChannel(text, target.getChannelReference());
|
return channelService.sendTextToAChannel(text, target.getChannelReference());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendEmbedInPostTarget(MessageEmbed embed, PostTarget target) {
|
public CompletableFuture<Message> sendEmbedInPostTarget(MessageEmbed embed, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
} else {
|
||||||
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
||||||
log.debug("Sending message embed to post target {}.", target.getName());
|
log.debug("Sending message embed to post target {}.", target.getName());
|
||||||
return channelService.sendEmbedToChannel(embed, textChannelForPostTarget);
|
return channelService.sendEmbedToChannel(embed, textChannelForPostTarget);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private TextChannel getTextChannelForPostTarget(PostTarget target) {
|
private TextChannel getTextChannelForPostTarget(PostTarget target) {
|
||||||
Guild guild = botService.getInstance().getGuildById(target.getServerReference().getId());
|
Guild guild = botService.getInstance().getGuildById(target.getServerReference().getId());
|
||||||
@@ -81,43 +93,69 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendTextInPostTarget(String text, PostTargetEnum postTargetEnum, Long serverId) {
|
public CompletableFuture<Message> sendTextInPostTarget(String text, PostTargetEnum postTargetEnum, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetEnum, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetEnum, serverId);
|
||||||
return this.sendTextInPostTarget(text, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
return this.sendTextInPostTarget(text, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendEmbedInPostTarget(MessageEmbed embed, PostTargetEnum postTargetName, Long serverId) {
|
public CompletableFuture<Message> sendEmbedInPostTarget(MessageEmbed embed, PostTargetEnum postTargetName, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetName, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetName, serverId);
|
||||||
return this.sendEmbedInPostTarget(embed, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
return this.sendEmbedInPostTarget(embed, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendMessageInPostTarget(Message message, PostTargetEnum postTargetName, Long serverId) {
|
public CompletableFuture<Message> sendMessageInPostTarget(Message message, PostTargetEnum postTargetName, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetName, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetName, serverId);
|
||||||
return sendMessageInPostTarget(message, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
return sendMessageInPostTarget(message, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletableFuture<Message> sendMessageInPostTarget(Message message, PostTarget target) {
|
public CompletableFuture<Message> sendMessageInPostTarget(Message message, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
} else {
|
||||||
log.debug("Send message {} towards post target {}.", message.getId(), target.getName());
|
log.debug("Send message {} towards post target {}.", message.getId(), target.getName());
|
||||||
return channelService.sendMessageToAChannel(message, target.getChannelReference());
|
return channelService.sendMessageToAChannel(message, target.getChannelReference());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> sendEmbedInPostTarget(MessageToSend message, PostTargetEnum postTargetName, Long serverId) {
|
public List<CompletableFuture<Message>> sendEmbedInPostTarget(MessageToSend message, PostTargetEnum postTargetName, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetName, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetName, serverId);
|
||||||
return this.sendEmbedInPostTarget(message, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
}
|
||||||
|
return this.sendEmbedInPostTarget(message, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> sendEmbedInPostTarget(MessageToSend message, PostTarget target) {
|
public List<CompletableFuture<Message>> sendEmbedInPostTarget(MessageToSend message, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
} else {
|
||||||
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
||||||
log.debug("Send messageToSend towards post target {}.", target.getName());
|
log.debug("Send messageToSend towards post target {}.", target.getName());
|
||||||
return channelService.sendMessageToSendToChannel(message, textChannelForPostTarget);
|
return channelService.sendMessageToSendToChannel(message, textChannelForPostTarget);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> editEmbedInPostTarget(Long messageId, MessageToSend message, PostTarget target) {
|
public List<CompletableFuture<Message>> editEmbedInPostTarget(Long messageId, MessageToSend message, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
} else {
|
||||||
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
||||||
// always takes the first one, only applicable for this scenario
|
// always takes the first one, only applicable for this scenario
|
||||||
String messageText = message.getMessages().get(0);
|
String messageText = message.getMessages().get(0);
|
||||||
@@ -129,14 +167,19 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
return Arrays.asList(channelService.editTextMessageInAChannel(messageText, message.getEmbeds().get(0), textChannelForPostTarget, messageId));
|
return Arrays.asList(channelService.editTextMessageInAChannel(messageText, message.getEmbeds().get(0), textChannelForPostTarget, messageId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> editOrCreatedInPostTarget(Long messageId, MessageToSend messageToSend, PostTarget target) {
|
public List<CompletableFuture<Message>> editOrCreatedInPostTarget(Long messageId, MessageToSend messageToSend, PostTarget target) {
|
||||||
|
if(target.getDisabled()) {
|
||||||
|
log.info("Post target {} has been disabled in server {} - not sending message.", target.getName(), target.getServerReference().getId());
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
} else {
|
||||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||||
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
TextChannel textChannelForPostTarget = getTextChannelForPostTarget(target);
|
||||||
CompletableFuture<Message> messageEditFuture = new CompletableFuture<>();
|
CompletableFuture<Message> messageEditFuture = new CompletableFuture<>();
|
||||||
futures.add(messageEditFuture);
|
futures.add(messageEditFuture);
|
||||||
if(StringUtils.isBlank(messageToSend.getMessages().get(0).trim())) {
|
if (StringUtils.isBlank(messageToSend.getMessages().get(0).trim())) {
|
||||||
channelService.retrieveMessageInChannel(textChannelForPostTarget, messageId).thenAccept(message -> {
|
channelService.retrieveMessageInChannel(textChannelForPostTarget, messageId).thenAccept(message -> {
|
||||||
log.debug("Editing existing message {} when upserting message embeds in channel {} in server {}.",
|
log.debug("Editing existing message {} when upserting message embeds in channel {} in server {}.",
|
||||||
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
messageId, textChannelForPostTarget.getIdLong(), textChannelForPostTarget.getGuild().getId());
|
||||||
@@ -174,17 +217,21 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
|
|
||||||
return futures;
|
return futures;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> editOrCreatedInPostTarget(Long messageId, MessageToSend messageToSend, PostTargetEnum postTargetName, Long serverId) {
|
public List<CompletableFuture<Message>> editOrCreatedInPostTarget(Long messageId, MessageToSend messageToSend, PostTargetEnum postTargetName, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetName, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetName, serverId);
|
||||||
return this.editOrCreatedInPostTarget(messageId, messageToSend, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
}
|
||||||
|
return this.editOrCreatedInPostTarget(messageId, messageToSend, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void throwIfPostTargetIsNotDefined(PostTargetEnum name, Long serverId) {
|
public void throwIfPostTargetIsNotDefined(PostTargetEnum name, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(name, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(name, serverId);
|
||||||
if(postTarget == null) {
|
if(!postTargetOptional.isPresent()) {
|
||||||
throw new PostTargetNotValidException(name.getKey(), defaultPostTargetManagementService.getDefaultPostTargetKeys());
|
throw new PostTargetNotValidException(name.getKey(), defaultPostTargetManagementService.getDefaultPostTargetKeys());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,12 +243,15 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<CompletableFuture<Message>> editEmbedInPostTarget(Long messageId, MessageToSend message, PostTargetEnum postTargetName, Long serverId) {
|
public List<CompletableFuture<Message>> editEmbedInPostTarget(Long messageId, MessageToSend message, PostTargetEnum postTargetName, Long serverId) {
|
||||||
PostTarget postTarget = getPostTarget(postTargetName, serverId);
|
Optional<PostTarget> postTargetOptional = getPostTarget(postTargetName, serverId);
|
||||||
return editEmbedInPostTarget(messageId, message, postTarget);
|
if(!postTargetOptional.isPresent()) {
|
||||||
|
return Arrays.asList(CompletableFuture.completedFuture(null));
|
||||||
|
}
|
||||||
|
return editEmbedInPostTarget(messageId, message, postTargetOptional.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PostTarget getPostTarget(PostTargetEnum postTargetEnum, Long serverId) {
|
private Optional<PostTarget> getPostTarget(PostTargetEnum postTargetEnum, Long serverId) {
|
||||||
return postTargetManagement.getPostTarget(postTargetEnum.getKey(), serverId);
|
return postTargetManagement.getPostTargetOptional(postTargetEnum.getKey(), serverId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -210,6 +260,19 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
return possiblePostTargets.contains(name);
|
return possiblePostTargets.contains(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void validatePostTarget(PostTargetEnum name, Long serverId) {
|
||||||
|
if(!postTargetUsableInServer(name, serverId)) {
|
||||||
|
throw new PostTargetNotUsableException(name.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean postTargetUsableInServer(PostTargetEnum name, Long serverId) {
|
||||||
|
Optional<PostTarget> postTargetOptional = getPostTarget(name, serverId);
|
||||||
|
return postTargetOptional.isPresent() && !postTargetOptional.get().getDisabled();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<PostTarget> getPostTargets(AServer server) {
|
public List<PostTarget> getPostTargets(AServer server) {
|
||||||
return postTargetManagement.getPostTargetsInServer(server);
|
return postTargetManagement.getPostTargetsInServer(server);
|
||||||
@@ -231,4 +294,16 @@ public class PostTargetServiceBean implements PostTargetService {
|
|||||||
});
|
});
|
||||||
return postTargets;
|
return postTargets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disablePostTarget(String name, Long serverId) {
|
||||||
|
PostTarget postTarget = postTargetManagement.getPostTarget(name, serverId);
|
||||||
|
postTarget.setDisabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enablePostTarget(String name, Long serverId) {
|
||||||
|
PostTarget postTarget = postTargetManagement.getPostTarget(name, serverId);
|
||||||
|
postTarget.setDisabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,13 @@ public class PostTargetManagementBean implements PostTargetManagement {
|
|||||||
throw new PostTargetNotValidException(name, defaultPostTargetManagementService.getDefaultPostTargetKeys());
|
throw new PostTargetNotValidException(name, defaultPostTargetManagementService.getDefaultPostTargetKeys());
|
||||||
}
|
}
|
||||||
log.info("Creating post target {} pointing towards {} on server {}.", name, targetChannel.getId(), targetChannel.getServer().getId());
|
log.info("Creating post target {} pointing towards {} on server {}.", name, targetChannel.getId(), targetChannel.getServer().getId());
|
||||||
PostTarget createdPostTarget = PostTarget.builder().name(name).channelReference(targetChannel).serverReference(targetChannel.getServer()).build();
|
PostTarget createdPostTarget = PostTarget
|
||||||
|
.builder()
|
||||||
|
.name(name)
|
||||||
|
.channelReference(targetChannel)
|
||||||
|
.serverReference(targetChannel.getServer())
|
||||||
|
.disabled(false)
|
||||||
|
.build();
|
||||||
return postTargetRepository.save(createdPostTarget);
|
return postTargetRepository.save(createdPostTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +81,8 @@ public class PostTargetManagementBean implements PostTargetManagement {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PostTarget getPostTarget(String name, AServer server) {
|
public PostTarget getPostTarget(String name, AServer server) {
|
||||||
return postTargetRepository.findPostTargetByNameAndServerReference(name, server).orElseThrow(() -> new PostTargetNotFoundException(name));
|
return postTargetRepository.findPostTargetByNameAndServerReference(name, server)
|
||||||
|
.orElseThrow(() -> new PostTargetNotFoundException(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -7,4 +7,5 @@
|
|||||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd">
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd">
|
||||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?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="coreFeature" value="(SELECT id FROM feature WHERE key = 'core')"/>
|
||||||
|
<property name="channelsModule" value="(SELECT id FROM module WHERE name = 'channels')"/>
|
||||||
|
<changeSet author="Sheldan" id="disable_posttarget-command" >
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="disablePosttarget"/>
|
||||||
|
<column name="module_id" valueComputed="${channelsModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="enablePosttarget"/>
|
||||||
|
<column name="module_id" valueComputed="${channelsModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${coreFeature}"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -7,4 +7,5 @@
|
|||||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
<include file="confirmationCleanupJob.xml" relativeToChangelogFile="true"/>
|
<include file="confirmationCleanupJob.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?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="post_target-addDisabled">
|
||||||
|
<addColumn tableName="posttarget">
|
||||||
|
<column name="disabled" type="BOOLEAN" defaultValueBoolean="false"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</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="post_target.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package dev.sheldan.abstracto.core.exception;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.exception.PostTargetNotValidExceptionModel;
|
||||||
|
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||||
|
|
||||||
|
public class PostTargetNotUsableException extends AbstractoRunTimeException implements Templatable {
|
||||||
|
|
||||||
|
private final PostTargetNotValidExceptionModel model;
|
||||||
|
|
||||||
|
public PostTargetNotUsableException(String key) {
|
||||||
|
super("The post target is not setup or has been disabled.");
|
||||||
|
this.model = PostTargetNotValidExceptionModel
|
||||||
|
.builder()
|
||||||
|
.postTargetKey(key)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTemplateName() {
|
||||||
|
return "post_target_not_usable_exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTemplateModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,6 +36,11 @@ public class PostTarget implements Serializable {
|
|||||||
@Setter
|
@Setter
|
||||||
private AServer serverReference;
|
private AServer serverReference;
|
||||||
|
|
||||||
|
@Column(name = "disabled")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Boolean disabled;
|
||||||
|
|
||||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||||
private Instant created;
|
private Instant created;
|
||||||
|
|
||||||
|
|||||||
@@ -12,4 +12,5 @@ import net.dv8tion.jda.api.entities.TextChannel;
|
|||||||
public class PostTargetModelEntry {
|
public class PostTargetModelEntry {
|
||||||
private PostTarget postTarget;
|
private PostTarget postTarget;
|
||||||
private TextChannel channel;
|
private TextChannel channel;
|
||||||
|
private Boolean disabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package dev.sheldan.abstracto.core.models.template.display;
|
package dev.sheldan.abstracto.core.models.template.display;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.core.utils.MemberUtils;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@@ -21,4 +23,13 @@ public class MemberDisplay {
|
|||||||
.userId(member.getIdLong())
|
.userId(member.getIdLong())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MemberDisplay fromAUserInAServer(AUserInAServer aUserInAServer) {
|
||||||
|
return MemberDisplay
|
||||||
|
.builder()
|
||||||
|
.memberMention(MemberUtils.getAUserInAServerAsMention(aUserInAServer))
|
||||||
|
.serverId(aUserInAServer.getServerReference().getId())
|
||||||
|
.userId(aUserInAServer.getUserReference().getId())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ public interface PostTargetService {
|
|||||||
void throwIfPostTargetIsNotDefined(PostTargetEnum name, Long serverId);
|
void throwIfPostTargetIsNotDefined(PostTargetEnum name, Long serverId);
|
||||||
boolean postTargetDefinedInServer(PostTargetEnum name, Long serverId);
|
boolean postTargetDefinedInServer(PostTargetEnum name, Long serverId);
|
||||||
boolean validPostTarget(String name);
|
boolean validPostTarget(String name);
|
||||||
|
void validatePostTarget(PostTargetEnum name, Long serverId);
|
||||||
|
boolean postTargetUsableInServer(PostTargetEnum name, Long serverId);
|
||||||
List<PostTarget> getPostTargets(AServer server);
|
List<PostTarget> getPostTargets(AServer server);
|
||||||
List<String> getAvailablePostTargets();
|
List<String> getAvailablePostTargets();
|
||||||
List<String> getPostTargetsOfEnabledFeatures(AServer server);
|
List<String> getPostTargetsOfEnabledFeatures(AServer server);
|
||||||
|
void disablePostTarget(String name, Long serverId);
|
||||||
|
void enablePostTarget(String name, Long serverId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package dev.sheldan.abstracto.core.utils;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
|
||||||
|
public class MemberUtils {
|
||||||
|
public static String getAUserInAServerAsMention(AUserInAServer aUserInAServer) {
|
||||||
|
return "<@" + aUserInAServer.getUserReference().getId() + ">";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,6 +49,12 @@ Changing a post target::
|
|||||||
* Description: Changes the given post target identified by `key` to `channel`. All messages using this post target will be sent to this channel from now on.
|
* Description: Changes the given post target identified by `key` to `channel`. All messages using this post target will be sent to this channel from now on.
|
||||||
If neither `key` nor `channel` is given, this will print the currently available post targets and the channels they point to, if set.
|
If neither `key` nor `channel` is given, this will print the currently available post targets and the channels they point to, if set.
|
||||||
* Example: `posttarget banLog #general` to log the bans in the #general channel.
|
* Example: `posttarget banLog #general` to log the bans in the #general channel.
|
||||||
|
Disabling a post target::
|
||||||
|
* Usage: `disablePostTarget <key>`
|
||||||
|
* Description: Disables the post target identified by `key` to not send any messages towards. Some features require a post target to be enabled, and have the option to throw an exception, others might just ignore it.
|
||||||
|
Enabling a post target::
|
||||||
|
* Usage: `enablePostTarget <key>`
|
||||||
|
* Description: Enables the post target identified by `key` to not send any messages towards.
|
||||||
Changing admin mode::
|
Changing admin mode::
|
||||||
* Usage: `setAdminMode <true/false>`
|
* Usage: `setAdminMode <true/false>`
|
||||||
* Description: Changes the admin modes on this server to the given value. Admin mode means, that **all** commands in the current server, can only be executed by members who have the ADMINISTRATOR permission.
|
* Description: Changes the admin modes on this server to the given value. Admin mode means, that **all** commands in the current server, can only be executed by members who have the ADMINISTRATOR permission.
|
||||||
|
|||||||
@@ -252,3 +252,16 @@ This functionality will automatically mute a member who mentions more than a con
|
|||||||
|
|
||||||
==== Relevant system configuration
|
==== Relevant system configuration
|
||||||
`massPingMinLevel`:: The level at which members are allowed to mass ping and not get muted.
|
`massPingMinLevel`:: The level at which members are allowed to mass ping and not get muted.
|
||||||
|
|
||||||
|
=== Tracking general infractions
|
||||||
|
|
||||||
|
Feature key `infractions`
|
||||||
|
|
||||||
|
This functionality just behaves to track general infractions of users, be it through the means of warnings or mutes. Currently, its very limited and only can be used to configure levels of infractions and certain points for various infractions, which will be tracked and stored.
|
||||||
|
|
||||||
|
==== Post targets
|
||||||
|
`infractionNotification`:: target for notifications of infraction level changes
|
||||||
|
|
||||||
|
==== Relevant system configuration
|
||||||
|
`infractionLevels`:: The amount of infraction levels which should be possible to configure
|
||||||
|
`infractionLevel`:: This system config key acts as a prefix up until the amount of infraction levels. With this you can configure the amount of points necessary to reach the given level: For example `infractionLevel2` would be the amount of points necessary to reach level 2. These levels are not enforced to be ordered nor if all levels have a value assigned to it. Any level evaluation will stop at the first level not defined.
|
||||||
Reference in New Issue
Block a user