mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-21 23:31:57 +00:00
Compare commits
40 Commits
abstracto-
...
abstracto-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91a23f870c | ||
|
|
b047d3eb49 | ||
|
|
db5b420f0a | ||
|
|
a7e60f6338 | ||
|
|
eed90c1406 | ||
|
|
78027ee980 | ||
|
|
e35071d8d5 | ||
|
|
14865a32f2 | ||
|
|
ae3c66384f | ||
|
|
986b65a1e4 | ||
|
|
cc898b27bb | ||
|
|
9ce07a1a4a | ||
|
|
ee01a3f07c | ||
|
|
9230a13218 | ||
|
|
c248351721 | ||
|
|
b0376778fe | ||
|
|
7f5d17e4dc | ||
|
|
0e7ea25aef | ||
|
|
f2aa7035aa | ||
|
|
c10296251c | ||
|
|
15fb9d95a8 | ||
|
|
79633d7a8e | ||
|
|
cef46737c5 | ||
|
|
c7076795a2 | ||
|
|
9e1527ccd1 | ||
|
|
326d488059 | ||
|
|
a39b6695a6 | ||
|
|
362d87778e | ||
|
|
0514d355c7 | ||
|
|
8909e8ebe5 | ||
|
|
36ca9b11e4 | ||
|
|
4a66b7fc67 | ||
|
|
b2a94059e2 | ||
|
|
16e6caa1f0 | ||
|
|
da1a71ecdc | ||
|
|
0646efe33d | ||
|
|
db856f2647 | ||
|
|
1d85eb1e7e | ||
|
|
5e6999cd45 | ||
|
|
9659a3487a |
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 Sheldan
|
||||
Copyright (c) 2022 Sheldan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ConditionService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.SystemCondition;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
@@ -34,6 +35,7 @@ public class MassPingServiceBean implements MassPingService {
|
||||
private static final String LEVEL_CONDITION_NAME = "HAS_LEVEL";
|
||||
private static final String LEVEL_CONDITION_USER_ID_PARAMETER = "userId";
|
||||
private static final String LEVEL_CONDITION_LEVEL_PARAMETER = "level";
|
||||
private static final String LEVEL_CONDITION_SERVER_PARAMETER = "serverId";
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
@@ -85,12 +87,14 @@ public class MassPingServiceBean implements MassPingService {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(message.getMember());
|
||||
parameters.put(LEVEL_CONDITION_USER_ID_PARAMETER, userInAServer.getUserInServerId());
|
||||
parameters.put(LEVEL_CONDITION_LEVEL_PARAMETER, level);
|
||||
parameters.put(LEVEL_CONDITION_SERVER_PARAMETER, message.getGuild().getIdLong());
|
||||
ConditionContextInstance contextInstance = ConditionContextInstance
|
||||
.builder()
|
||||
.conditionName(LEVEL_CONDITION_NAME)
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
return conditionService.checkConditions(contextInstance);
|
||||
SystemCondition.Result result = conditionService.checkConditions(contextInstance);
|
||||
return SystemCondition.Result.consideredSuccessful(result);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ public class DeleteAssignableRolePlace extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.causesReaction(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.models.ConditionContextInstance;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ConditionService;
|
||||
import dev.sheldan.abstracto.core.service.SystemCondition;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -24,6 +25,7 @@ public class AssignableRoleMinimumLevelConditionImpl implements AssignableRoleCo
|
||||
private final String conditionName = "HAS_LEVEL";
|
||||
private final String userIdParameter = "userId";
|
||||
private final String levelParameter = "level";
|
||||
private final String serverParameter = "serverId";
|
||||
|
||||
@Autowired
|
||||
private ConditionService conditionService;
|
||||
@@ -34,13 +36,15 @@ public class AssignableRoleMinimumLevelConditionImpl implements AssignableRoleCo
|
||||
Map<String, Object> parameters = new HashMap<>();
|
||||
parameters.put(userIdParameter, aUserInAServer.getUserInServerId());
|
||||
parameters.put(levelParameter, level);
|
||||
parameters.put(serverParameter, aUserInAServer.getServerReference().getId());
|
||||
|
||||
ConditionContextInstance contextInstance = ConditionContextInstance
|
||||
.builder()
|
||||
.conditionName(conditionName)
|
||||
.parameters(parameters)
|
||||
.build();
|
||||
return conditionService.checkConditions(contextInstance);
|
||||
SystemCondition.Result result = conditionService.checkConditions(contextInstance);
|
||||
return SystemCondition.Result.consideredSuccessful(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -219,7 +219,7 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN);
|
||||
return AssignableRolePlaceServiceBean.ASSIGNABLE_ROLE_COMPONENT_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public class SetExpRole extends AbstractConditionableCommand {
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
|
||||
@@ -52,6 +52,7 @@ public class SyncRoles extends AbstractConditionableCommand {
|
||||
.module(ExperienceModuleDefinition.EXPERIENCE)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -67,6 +67,7 @@ public class UnSetExpRole extends AbstractConditionableCommand {
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -4,8 +4,10 @@ import dev.sheldan.abstracto.core.models.ConditionContext;
|
||||
import dev.sheldan.abstracto.core.models.ConditionContextInstance;
|
||||
import dev.sheldan.abstracto.core.models.ConditionContextVariable;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.SystemCondition;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -26,6 +28,7 @@ public class HasLevelCondition implements SystemCondition {
|
||||
|
||||
public static final String USER_IN_SERVER_ID_VARIABLE_KEY = "userId";
|
||||
public static final String LEVEL_VARIABLE = "level";
|
||||
public static final String SERVER_VARIABLE = "serverId";
|
||||
public static final String HAS_LEVEL_CONDITION_KEY = "HAS_LEVEL";
|
||||
|
||||
@Autowired
|
||||
@@ -34,11 +37,18 @@ public class HasLevelCondition implements SystemCondition {
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Override
|
||||
public boolean checkCondition(ConditionContextInstance conditionContext) {
|
||||
public Result checkCondition(ConditionContextInstance conditionContext) {
|
||||
Map<String, Object> parameters = conditionContext.getParameters();
|
||||
Long userInServerId = (Long) parameters.get(USER_IN_SERVER_ID_VARIABLE_KEY);
|
||||
Long serverId = (Long) parameters.get(SERVER_VARIABLE);
|
||||
Integer level = (Integer) parameters.get(LEVEL_VARIABLE);
|
||||
if(!featureFlagService.getFeatureFlagValue(ExperienceFeatureDefinition.EXPERIENCE, serverId)) {
|
||||
return Result.IGNORED;
|
||||
}
|
||||
Optional<AUserInAServer> userInServerOptional = userInServerManagementService.loadUserOptional(userInServerId);
|
||||
if(userInServerOptional.isPresent()) {
|
||||
AUserInAServer userInServer = userInServerOptional.get();
|
||||
@@ -47,11 +57,11 @@ public class HasLevelCondition implements SystemCondition {
|
||||
AUserExperience user = userExperienceManagementService.findUserInServer(userInServer);
|
||||
boolean conditionResult = user.getCurrentLevel() != null && user.getCurrentLevel().getLevel() >= level;
|
||||
log.info("Condition evaluated to {}", conditionResult);
|
||||
return conditionResult;
|
||||
return Result.fromBoolean(conditionResult);
|
||||
}
|
||||
log.info("No user in server object was found. Evaluating has level to false.");
|
||||
|
||||
return false;
|
||||
return Result.FAILED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,9 +81,14 @@ public class HasLevelCondition implements SystemCondition {
|
||||
.name(LEVEL_VARIABLE)
|
||||
.type(Integer.class)
|
||||
.build();
|
||||
ConditionContextVariable serverVariable = ConditionContextVariable
|
||||
.builder()
|
||||
.name(SERVER_VARIABLE)
|
||||
.type(Long.class)
|
||||
.build();
|
||||
return ConditionContext
|
||||
.builder()
|
||||
.requiredVariables(Arrays.asList(userIdVariable, levelVariable))
|
||||
.requiredVariables(Arrays.asList(userIdVariable, levelVariable, serverVariable))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ public class RemoveTrackedInviteLinks extends AbstractConditionableCommand {
|
||||
.module(InviteFilterModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -13,5 +13,5 @@ public interface AllowedInviteLinkRepository extends JpaRepository<AllowedInvite
|
||||
Optional<AllowedInviteLink> findByTargetServerIdAndServer(Long targetServerId, AServer server);
|
||||
|
||||
Optional<AllowedInviteLink> findByTargetServerIdAndServer_Id(Long targetServerId, Long serverId);
|
||||
Optional<AllowedInviteLink> findByCodeAndServer_Id(String code, Long serverId);
|
||||
Optional<AllowedInviteLink> findByCodeIgnoreCaseAndServer_Id(String code, Long serverId);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvite;
|
||||
import dev.sheldan.abstracto.invitefilter.model.template.listener.DeletedInvitesNotificationModel;
|
||||
import dev.sheldan.abstracto.invitefilter.service.management.AllowedInviteLinkManagement;
|
||||
import dev.sheldan.abstracto.invitefilter.service.management.FilteredInviteLinkManagement;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.entities.Invite;
|
||||
@@ -34,7 +37,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -222,11 +224,11 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
return Invite.resolve(jda, extractCode(code)).submit();
|
||||
}
|
||||
|
||||
private void sendDeletionNotification(List<String> codes, Message message) {
|
||||
private CompletableFuture<Void> sendDeletionNotification(List<InviteToDelete> codes, Message message) {
|
||||
Long serverId = message.getGuild().getIdLong();
|
||||
if(!postTargetService.postTargetDefinedInServer(InviteFilterPostTarget.INVITE_DELETE_LOG, serverId)) {
|
||||
log.info("Post target {} not defined for server {} - not sending invite link deletion notification.", InviteFilterPostTarget.INVITE_DELETE_LOG.getKey(), serverId);
|
||||
return;
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
DeletedInvitesNotificationModel model = DeletedInvitesNotificationModel
|
||||
.builder()
|
||||
@@ -240,21 +242,30 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
codes.size(), serverId, message.getAuthor().getIdLong(), message.getChannel().getIdLong(), message.getIdLong());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(INVITE_LINK_DELETED_NOTIFICATION_EMBED_TEMPLATE_KEY, model, message.getGuild().getIdLong());
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, InviteFilterPostTarget.INVITE_DELETE_LOG, serverId);
|
||||
FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused ->
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused ->
|
||||
log.debug("Successfully send notification about deleted invite link in message {}.", message.getIdLong())
|
||||
).exceptionally(throwable -> {
|
||||
log.error("Failed to send notification about deleted invite link in message {}.", message.getIdLong());
|
||||
return null;
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
private List<DeletedInvite> groupInvites(List<String> codes) {
|
||||
private List<DeletedInvite> groupInvites(List<InviteToDelete> codes) {
|
||||
|
||||
Map<String, String> codeToGuildName = new HashMap<>();
|
||||
for (InviteToDelete invite: codes) {
|
||||
if(!codeToGuildName.containsKey(invite.getInviteCode())) {
|
||||
codeToGuildName.put(invite.getInviteCode(), invite.getGuildName());
|
||||
}
|
||||
}
|
||||
return codes
|
||||
.stream()
|
||||
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
|
||||
.collect(Collectors.groupingBy(InviteToDelete::getInviteCode, Collectors.counting()))
|
||||
.entrySet()
|
||||
.stream()
|
||||
.map(functionLongEntry -> new DeletedInvite(functionLongEntry.getKey(), functionLongEntry.getValue()))
|
||||
.map(functionLongEntry -> DeletedInvite
|
||||
.builder()
|
||||
.code(functionLongEntry.getKey())
|
||||
.guildName(codeToGuildName.get(functionLongEntry.getKey()))
|
||||
.count(functionLongEntry.getValue())
|
||||
.build())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -291,18 +302,23 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
ServerUser author = ServerUser.builder().userId(message.getAuthor().getIdLong()).serverId(message.getGuild().getIdLong()).build();
|
||||
boolean toDelete = false;
|
||||
Map<Long, String> targetServers = new HashMap<>();
|
||||
List<String> deletedInvites = new ArrayList<>();
|
||||
List<InviteToDelete> deletedInvites = new ArrayList<>();
|
||||
for (Invite invite : invites) {
|
||||
if (invite.getType().equals(Invite.InviteType.GUILD)
|
||||
&& isCodeFiltered(invite.getGuild().getIdLong(), author)) {
|
||||
toDelete = true;
|
||||
deletedInvites.add(invite.getCode());
|
||||
InviteToDelete inviteToDelete = InviteToDelete
|
||||
.builder()
|
||||
.inviteCode(invite.getCode())
|
||||
.guildName(invite.getGuild().getName())
|
||||
.build();
|
||||
deletedInvites.add(inviteToDelete);
|
||||
targetServers.put(invite.getGuild().getIdLong(), invite.getGuild().getName());
|
||||
}
|
||||
}
|
||||
List<String> unResolvedInvites = new ArrayList<>();
|
||||
foundInvites.forEach(possibleUnresolvedInvite -> {
|
||||
if(invites.stream().noneMatch(invite -> invite.getCode().equals(possibleUnresolvedInvite))) {
|
||||
if(invites.stream().noneMatch(invite -> invite.getCode().equalsIgnoreCase(possibleUnresolvedInvite))) {
|
||||
unResolvedInvites.add(possibleUnresolvedInvite);
|
||||
}
|
||||
});
|
||||
@@ -310,7 +326,11 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
for(String unresolvedInvite : unResolvedInvites) {
|
||||
if(isCodeFiltered(unresolvedInvite, author)) {
|
||||
toDelete = true;
|
||||
deletedInvites.add(unresolvedInvite);
|
||||
InviteToDelete inviteToDelete = InviteToDelete
|
||||
.builder()
|
||||
.inviteCode(unresolvedInvite)
|
||||
.build();
|
||||
deletedInvites.add(inviteToDelete);
|
||||
}
|
||||
}
|
||||
if(toDelete) {
|
||||
@@ -322,7 +342,11 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
}
|
||||
boolean sendNotification = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.FILTER_NOTIFICATIONS);
|
||||
if(sendNotification) {
|
||||
sendDeletionNotification(deletedInvites, message);
|
||||
sendDeletionNotification(deletedInvites, message)
|
||||
.thenAccept(unused1 -> log.info("Sent invite deletion notification.")).exceptionally(throwable1 -> {
|
||||
log.error("Failed to send invite deletion notification.");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
@@ -336,4 +360,12 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
metricService.registerCounter(MESSAGE_INVITE_FILTERED, "Amount of messages containing an invite filtered");
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
private static class InviteToDelete {
|
||||
private String guildName;
|
||||
private String inviteCode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,12 @@ public class AllowedInviteLinkManagementBean implements AllowedInviteLinkManagem
|
||||
|
||||
@Override
|
||||
public AllowedInviteLink createAllowedInviteLink(AServer server, Long targetServerId, String code) {
|
||||
AllowedInviteLink inviteLink = AllowedInviteLink.builder().targetServerId(targetServerId).code(code).server(server).build();
|
||||
AllowedInviteLink inviteLink = AllowedInviteLink
|
||||
.builder()
|
||||
.targetServerId(targetServerId)
|
||||
.code(code)
|
||||
.server(server)
|
||||
.build();
|
||||
return repository.save(inviteLink);
|
||||
}
|
||||
|
||||
@@ -48,6 +53,6 @@ public class AllowedInviteLinkManagementBean implements AllowedInviteLinkManagem
|
||||
|
||||
@Override
|
||||
public boolean allowedInviteLinkExists(ServerUser serverUser, String code) {
|
||||
return repository.findByCodeAndServer_Id(code, serverUser.getServerId()).isPresent();
|
||||
return repository.findByCodeIgnoreCaseAndServer_Id(code, serverUser.getServerId()).isPresent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package dev.sheldan.abstracto.invitefilter.model.template.listener;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
@Builder
|
||||
public class DeletedInvite {
|
||||
private String code;
|
||||
private String guildName;
|
||||
private Long count;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public class MessageEmbedDeleteButtonClickedListener implements ButtonClickedLis
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(MessageEmbedServiceBean.MESSAGE_EMBED_DELETE_ORIGIN);
|
||||
return MessageEmbedServiceBean.MESSAGE_EMBED_DELETE_ORIGIN.equals(model.getOrigin());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||
import dev.sheldan.abstracto.logging.model.template.MemberJoinLogModel;
|
||||
@@ -43,7 +44,11 @@ public class JoinLogger implements AsyncJoinListener {
|
||||
.build();
|
||||
log.debug("Logging join event for user {} in server {}.", listenerModel.getMember().getIdLong(), 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -46,7 +47,11 @@ public class LeaveLogger implements AsyncLeaveListener {
|
||||
.build();
|
||||
log.debug("Logging leave event for user {} in server {}.", listenerModel.getUser().getIdLong(), 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,10 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
CachedMessage message = model.getCachedMessage();
|
||||
memberService.getMemberInServerAsync(model.getServerId(), message.getAuthor().getAuthorId()).thenAccept(member ->
|
||||
self.executeListener(message, member)
|
||||
);
|
||||
).exceptionally(throwable -> {
|
||||
log.warn("Could not retrieve member {} for message deleted event in guild {}.", message.getAuthor().getAuthorId(), model.getServerId(), throwable);
|
||||
return null;
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@@ -82,7 +85,8 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
.member(authorMember)
|
||||
.build();
|
||||
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);
|
||||
return null;
|
||||
});
|
||||
@@ -99,7 +103,7 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
.build();
|
||||
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, attachmentLogModel, messageFromCache.getServerId());
|
||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId()))
|
||||
.exceptionally(throwable -> {
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Failed to send message deleted log.", throwable);
|
||||
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.templating.model.MessageToSend;
|
||||
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.LoggingPostTarget;
|
||||
import dev.sheldan.abstracto.logging.model.template.MessageDeletedAttachmentLog;
|
||||
@@ -65,7 +66,11 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
||||
.member(messageAfter.getMember())
|
||||
.build();
|
||||
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) {
|
||||
log.info("Attachment count changed. Old {}, new {}.", attachmentCountBefore, attachmentCountAfter);
|
||||
@@ -75,7 +80,7 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
||||
).collect(Collectors.toList());
|
||||
log.debug("Logging deletion of {} attachments.", removedAttachments.size());
|
||||
for (int i = 0; i < removedAttachments.size(); i++) {
|
||||
MessageDeletedAttachmentLog log = MessageDeletedAttachmentLog
|
||||
MessageDeletedAttachmentLog attachmentModel = MessageDeletedAttachmentLog
|
||||
.builder()
|
||||
.imageUrl(removedAttachments.get(i).getProxyUrl())
|
||||
.counter(i + 1)
|
||||
@@ -84,8 +89,12 @@ public class MessageEditedListener implements AsyncMessageUpdatedListener {
|
||||
.member(messageAfter.getMember())
|
||||
.build();
|
||||
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_EDITED_ATTACHMENT_REMOVED_TEMPLATE,
|
||||
log, messageBefore.getServerId());
|
||||
postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageBefore.getServerId());
|
||||
attachmentModel, 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;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class Ban extends AbstractConditionableCommand {
|
||||
User user = (User) parameters.get(0);
|
||||
String reason = (String) parameters.get(1);
|
||||
|
||||
return banService.banUser(user, reason, commandContext.getAuthor(), commandContext.getMessage())
|
||||
return banService.banUserWithNotification(user, reason, commandContext.getAuthor(), 0, commandContext.getMessage())
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import net.dv8tion.jda.api.entities.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -27,7 +26,7 @@ import static dev.sheldan.abstracto.moderation.service.BanService.BAN_EFFECT_KEY
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SoftBan extends AbstractConditionableCommand {
|
||||
public class BanDelete extends AbstractConditionableCommand {
|
||||
|
||||
@Autowired
|
||||
private BanService banService;
|
||||
@@ -36,11 +35,9 @@ public class SoftBan extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
User user = (User) parameters.get(0);
|
||||
Duration delDays = Duration.ofDays(7);
|
||||
if(parameters.size() > 1) {
|
||||
delDays = (Duration) parameters.get(1);
|
||||
}
|
||||
return banService.softBanUser(commandContext.getGuild(), user, delDays)
|
||||
Integer delDays = (Integer) parameters.get(1);
|
||||
String reason = (String) parameters.get(2);
|
||||
return banService.banUserWithNotification(user, reason, commandContext.getAuthor(), delDays, commandContext.getMessage())
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@@ -48,11 +45,12 @@ public class SoftBan extends AbstractConditionableCommand {
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("user").templated(true).type(User.class).build());
|
||||
parameters.add(Parameter.builder().name("delDays").templated(true).type(Duration.class).optional(true).build());
|
||||
parameters.add(Parameter.builder().name("delDays").templated(true).type(Integer.class).build());
|
||||
parameters.add(Parameter.builder().name("reason").templated(true).type(String.class).remainder(true).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
List<EffectConfig> effectConfig = Arrays.asList(EffectConfig.builder().position(0).effectKey(BAN_EFFECT_KEY).build());
|
||||
return CommandConfiguration.builder()
|
||||
.name("softBan")
|
||||
.name("banDelete")
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
@@ -44,6 +44,7 @@ public class DecayAllWarnings extends AbstractConditionableCommand {
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.requiresConfirmation(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
|
||||
@@ -43,6 +43,7 @@ public class DecayWarnings extends AbstractConditionableCommand {
|
||||
.name("decayWarnings")
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.requiresConfirmation(true)
|
||||
.async(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.converter.MuteEntryConverter;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteEntry;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MutesModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class Mutes extends AbstractConditionableCommand {
|
||||
|
||||
private static final String NO_MUTES_TEMPLATE_KEY = "mutes_no_mutes_found";
|
||||
private static final String MUTES_DISPLAY_TEMPLATE_KEY = "mutes_display_response";
|
||||
@Autowired
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private MuteEntryConverter muteEntryConverter;
|
||||
|
||||
@Autowired
|
||||
private Mutes self;
|
||||
|
||||
@Autowired
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<dev.sheldan.abstracto.moderation.model.database.Mute> mutesToDisplay;
|
||||
if(commandContext.getParameters().getParameters().isEmpty()) {
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild().getIdLong());
|
||||
mutesToDisplay = muteManagementService.getAllMutes(server);
|
||||
} else {
|
||||
Member member = (Member) commandContext.getParameters().getParameters().get(0);
|
||||
if(!member.getGuild().equals(commandContext.getGuild())) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
mutesToDisplay = muteManagementService.getAllMutesOf(userInServerManagementService.loadOrCreateUser(member));
|
||||
}
|
||||
if(mutesToDisplay.isEmpty()) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_MUTES_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
} else {
|
||||
return muteEntryConverter.fromMutes(mutesToDisplay)
|
||||
.thenCompose(muteEntries -> self.renderMutes(commandContext, muteEntries)
|
||||
.thenApply(unused -> CommandResult.fromIgnored()));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<Void> renderMutes(CommandContext commandContext, List<MuteEntry> mutes) {
|
||||
MutesModel model = (MutesModel) ContextConverter.slimFromCommandContext(commandContext, MutesModel.class);
|
||||
model.setMutes(mutes);
|
||||
return paginatorService.createPaginatorFromTemplate(MUTES_DISPLAY_TEMPLATE_KEY, model, commandContext.getChannel(), commandContext.getAuthor().getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
List<Parameter> parameters = new ArrayList<>();
|
||||
parameters.add(Parameter.builder().name("member").templated(true).type(Member.class).optional(true).build());
|
||||
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
|
||||
return CommandConfiguration.builder()
|
||||
.name("mutes")
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.async(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationFeatureDefinition.MUTING;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class MyWarnings extends AbstractConditionableCommand {
|
||||
public CommandResult execute(CommandContext commandContext) {
|
||||
MyWarningsModel model = (MyWarningsModel) ContextConverter.fromCommandContext(commandContext, MyWarningsModel.class);
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||
Long currentWarnCount = warnManagementService.getActiveWarnsForUser(userInAServer);
|
||||
Long currentWarnCount = warnManagementService.getActiveWarnCountForUser(userInAServer);
|
||||
model.setCurrentWarnCount(currentWarnCount);
|
||||
Long totalWarnCount = warnManagementService.getTotalWarnsForUser(userInAServer);
|
||||
model.setTotalWarnCount(totalWarnCount);
|
||||
|
||||
@@ -34,7 +34,7 @@ public class UnBan extends AbstractConditionableCommand {
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
User user = (User) parameters.get(0);
|
||||
return banService.unBanUser(user, commandContext.getAuthor())
|
||||
return banService.unBanUserWithNotification(user, commandContext.getAuthor())
|
||||
.thenApply(aVoid -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import com.jagrosh.jdautilities.menu.Paginator;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
@@ -12,9 +10,13 @@ import dev.sheldan.abstracto.core.command.execution.ContextConverter;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.converter.WarnEntryConverter;
|
||||
@@ -34,7 +36,8 @@ import java.util.concurrent.CompletableFuture;
|
||||
@Component
|
||||
public class Warnings extends AbstractConditionableCommand {
|
||||
|
||||
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_response";
|
||||
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_display_response";
|
||||
public static final String NO_WARNINGS_TEMPLATE_KEY = "warnings_no_warnings_found";
|
||||
@Autowired
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@@ -47,15 +50,18 @@ public class Warnings extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
@Autowired
|
||||
private EventWaiter eventWaiter;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private Warnings self;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Warning> warnsToDisplay;
|
||||
@@ -69,21 +75,26 @@ public class Warnings extends AbstractConditionableCommand {
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild());
|
||||
warnsToDisplay = warnManagementService.getAllWarningsOfServer(server);
|
||||
}
|
||||
return warnEntryConverter.fromWarnings(warnsToDisplay).thenApply(warnEntries -> {
|
||||
self.renderWarnings(commandContext, warnEntries);
|
||||
return CommandResult.fromIgnored();
|
||||
});
|
||||
if(warnsToDisplay.isEmpty()) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_WARNINGS_TEMPLATE_KEY, new Object(), commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
|
||||
} else {
|
||||
return warnEntryConverter.fromWarnings(warnsToDisplay)
|
||||
.thenCompose(warnEntries -> self.renderWarnings(commandContext, warnEntries))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void renderWarnings(CommandContext commandContext, List<WarnEntry> warnEntries) {
|
||||
public CompletableFuture<Void> renderWarnings(CommandContext commandContext, List<WarnEntry> warnEntries) {
|
||||
WarningsModel model = (WarningsModel) ContextConverter.slimFromCommandContext(commandContext, WarningsModel.class);
|
||||
model.setWarnings(warnEntries);
|
||||
|
||||
Paginator paginator = paginatorService.createPaginatorFromTemplate(WARNINGS_RESPONSE_TEMPLATE, model, eventWaiter, commandContext.getGuild().getIdLong());
|
||||
paginator.display(commandContext.getChannel());
|
||||
return paginatorService.createPaginatorFromTemplate(WARNINGS_RESPONSE_TEMPLATE, model, commandContext.getChannel(), commandContext.getAuthor().getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +107,7 @@ public class Warnings extends AbstractConditionableCommand {
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.causesReaction(true)
|
||||
.causesReaction(false)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
|
||||
@@ -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,114 @@
|
||||
package dev.sheldan.abstracto.moderation.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteEntry;
|
||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class MuteEntryConverter {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private MuteManagementService muteManagementService;
|
||||
|
||||
@Autowired
|
||||
private MuteEntryConverter self;
|
||||
|
||||
public CompletableFuture<List<MuteEntry>> fromMutes(List<Mute> mutes) {
|
||||
Map<ServerSpecificId, FutureMemberPair> loadedMutes = new HashMap<>();
|
||||
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
|
||||
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
|
||||
mutes.forEach(mute -> {
|
||||
AUserInAServer mutingUser = mute.getMutingUser();
|
||||
AUserInAServer mutedUser = mute.getMutedUser();
|
||||
CompletableFuture<Member> mutedFuture;
|
||||
if(memberCaching.containsKey(mutedUser.getUserInServerId())) {
|
||||
mutedFuture = memberCaching.get(mutedUser.getUserInServerId());
|
||||
} else {
|
||||
mutedFuture = memberService.getMemberInServerAsync(mutedUser);
|
||||
memberCaching.put(mutedUser.getUserInServerId(), mutedFuture);
|
||||
}
|
||||
CompletableFuture<Member> mutingFuture;
|
||||
if(memberCaching.containsKey(mutingUser.getUserInServerId())) {
|
||||
mutingFuture = memberCaching.get(mutingUser.getUserInServerId());
|
||||
} else {
|
||||
mutingFuture = memberService.getMemberInServerAsync(mutingUser);
|
||||
memberCaching.put(mutingUser.getUserInServerId(), mutingFuture);
|
||||
}
|
||||
FutureMemberPair futurePair = FutureMemberPair
|
||||
.builder()
|
||||
.firstMember(mutingFuture)
|
||||
.secondMember(mutedFuture)
|
||||
.build();
|
||||
loadedMutes.put(mute.getMuteId(), futurePair);
|
||||
allFutures.add(mutingFuture);
|
||||
allFutures.add(mutedFuture);
|
||||
});
|
||||
CompletableFuture<List<MuteEntry>> future = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFutureGeneric(allFutures)
|
||||
.whenComplete((unused, throwable) -> future.complete(self.loadFullMuteEntries(loadedMutes)))
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<MuteEntry> loadFullMuteEntries(Map<ServerSpecificId, FutureMemberPair> loadedMuteInfo) {
|
||||
List<MuteEntry> entries = new ArrayList<>();
|
||||
List<ServerSpecificId> muteIds = new ArrayList<>(loadedMuteInfo.keySet());
|
||||
muteIds.sort(Comparator.comparing(ServerSpecificId::getId));
|
||||
muteIds.forEach(muteInfo -> {
|
||||
FutureMemberPair memberPair = loadedMuteInfo.get(muteInfo);
|
||||
Mute mute = muteManagementService.findMute(muteInfo.getId(), muteInfo.getServerId());
|
||||
Member mutedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null;
|
||||
MemberDisplay mutedUser = MemberDisplay
|
||||
.builder()
|
||||
.memberMention(mutedMember != null ? mutedMember.getAsMention() : null)
|
||||
.userId(mute.getMutedUser().getUserReference().getId())
|
||||
.serverId(mute.getServer().getId())
|
||||
.build();
|
||||
|
||||
Member mutingMember = !memberPair.getFirstMember().isCompletedExceptionally() ? memberPair.getFirstMember().join() : null;
|
||||
MemberDisplay mutingUser = MemberDisplay
|
||||
.builder()
|
||||
.memberMention(mutingMember != null ? mutingMember.getAsMention() : null)
|
||||
.userId(mute.getMutingUser().getUserReference().getId())
|
||||
.build();
|
||||
MuteEntry entry = MuteEntry
|
||||
.builder()
|
||||
.mutedUser(mutedUser)
|
||||
.mutingUser(mutingUser)
|
||||
.muteId(mute.getMuteId().getId())
|
||||
.serverId(mute.getMuteId().getServerId())
|
||||
.reason(mute.getReason())
|
||||
.muteDate(mute.getMuteDate())
|
||||
.muteEnded(mute.getMuteEnded())
|
||||
.muteDuration(Duration.between(mute.getMuteDate(), mute.getMuteTargetDate()))
|
||||
.build();
|
||||
entries.add(entry);
|
||||
});
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package dev.sheldan.abstracto.moderation.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FullUserInServer;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
@@ -37,18 +38,30 @@ public class UserNotesConverter {
|
||||
public CompletableFuture<List<NoteEntryModel>> fromNotes(List<UserNote> userNotes){
|
||||
List<CompletableFuture<Member>> memberFutures = new ArrayList<>();
|
||||
HashMap<ServerSpecificId, CompletableFuture<Member>> noteMemberMap = new HashMap<>();
|
||||
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
|
||||
userNotes.forEach(userNote -> {
|
||||
CompletableFuture<Member> memberFuture = memberService.getMemberInServerAsync(userNote.getUser());
|
||||
memberFutures.add(memberFuture);
|
||||
noteMemberMap.put(userNote.getUserNoteId(), memberFuture);
|
||||
AUserInAServer noteUser = userNote.getUser();
|
||||
CompletableFuture<Member> noteFuture;
|
||||
if(memberCaching.containsKey(noteUser.getUserInServerId())) {
|
||||
noteFuture = memberCaching.get(noteUser.getUserInServerId());
|
||||
} else {
|
||||
noteFuture = memberService.getMemberInServerAsync(noteUser);
|
||||
memberCaching.put(noteUser.getUserInServerId(), noteFuture);
|
||||
}
|
||||
memberFutures.add(noteFuture);
|
||||
noteMemberMap.put(userNote.getUserNoteId(), noteFuture);
|
||||
});
|
||||
if(userNotes.isEmpty()) {
|
||||
memberFutures.add(CompletableFuture.completedFuture(null));
|
||||
}
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(memberFutures).thenApply(aVoid ->
|
||||
self.loadFullNotes(noteMemberMap)
|
||||
);
|
||||
CompletableFuture<List<NoteEntryModel>> future = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFutureGeneric(memberFutures)
|
||||
.whenComplete((unused, throwable) -> future.complete(self.loadFullNotes(noteMemberMap)))
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -58,15 +71,19 @@ public class UserNotesConverter {
|
||||
CompletableFuture<Member> memberFuture = futureHashMap.get(serverSpecificId);
|
||||
Member member = !memberFuture.isCompletedExceptionally() ? memberFuture.join() : null;
|
||||
UserNote note = userNoteManagementService.loadNote(serverSpecificId.getServerId(), serverSpecificId.getId());
|
||||
FullUserInServer fullUser = FullUserInServer
|
||||
MemberDisplay display = MemberDisplay
|
||||
.builder()
|
||||
.member(member)
|
||||
.aUserInAServer(note.getUser())
|
||||
.userId(note.getUser().getUserReference().getId())
|
||||
.serverId(note.getServer().getId())
|
||||
.memberMention(member != null ? member.getAsMention() : null)
|
||||
.build();
|
||||
NoteEntryModel entryModel = NoteEntryModel
|
||||
.builder()
|
||||
.note(note)
|
||||
.fullUser(fullUser)
|
||||
.member(display)
|
||||
.serverId(serverSpecificId.getServerId())
|
||||
.note(note.getNote())
|
||||
.noteId(note.getUserNoteId().getId())
|
||||
.created(note.getCreated())
|
||||
.build();
|
||||
entryModels.add(entryModel);
|
||||
});
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package dev.sheldan.abstracto.moderation.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.MemberDisplayModel;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
@@ -14,10 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -38,49 +36,70 @@ public class WarnEntryConverter {
|
||||
public CompletableFuture<List<WarnEntry>> fromWarnings(List<Warning> warnings) {
|
||||
Map<ServerSpecificId, FutureMemberPair> loadedWarnings = new HashMap<>();
|
||||
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
|
||||
// TODO maybe optimize to not need to look into the cache twice
|
||||
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
|
||||
warnings.forEach(warning -> {
|
||||
CompletableFuture<Member> warningMemberFuture = memberService.getMemberInServerAsync(warning.getWarningUser());
|
||||
CompletableFuture<Member> warnedMemberFuture = memberService.getMemberInServerAsync(warning.getWarnedUser());
|
||||
FutureMemberPair futurePair = FutureMemberPair.builder().firstMember(warningMemberFuture).secondMember(warnedMemberFuture).build();
|
||||
AUserInAServer warningUser = warning.getWarningUser();
|
||||
AUserInAServer warnedUser = warning.getWarnedUser();
|
||||
CompletableFuture<Member> warnedFuture;
|
||||
if(memberCaching.containsKey(warnedUser.getUserInServerId())) {
|
||||
warnedFuture = memberCaching.get(warnedUser.getUserInServerId());
|
||||
} else {
|
||||
warnedFuture = memberService.getMemberInServerAsync(warnedUser);
|
||||
memberCaching.put(warnedUser.getUserInServerId(), warnedFuture);
|
||||
}
|
||||
CompletableFuture<Member> warningFuture;
|
||||
if(memberCaching.containsKey(warningUser.getUserInServerId())) {
|
||||
warningFuture = memberCaching.get(warningUser.getUserInServerId());
|
||||
} else {
|
||||
warningFuture = memberService.getMemberInServerAsync(warningUser);
|
||||
memberCaching.put(warningUser.getUserInServerId(), warningFuture);
|
||||
}
|
||||
FutureMemberPair futurePair = FutureMemberPair.builder().firstMember(warningFuture).secondMember(warnedFuture).build();
|
||||
loadedWarnings.put(warning.getWarnId(), futurePair);
|
||||
allFutures.add(warningMemberFuture);
|
||||
allFutures.add(warnedMemberFuture);
|
||||
allFutures.add(warningFuture);
|
||||
allFutures.add(warnedFuture);
|
||||
});
|
||||
CompletableFuture<List<WarnEntry>> future = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFutureGeneric(allFutures)
|
||||
.whenComplete((unused, throwable) -> future.complete(self.loadFullWarnEntries(loadedWarnings)))
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public List<WarnEntry> loadFullWarnEntries(Map<ServerSpecificId, FutureMemberPair> loadedWarnInfo) {
|
||||
List<ServerSpecificId> warnIds = new ArrayList<>(loadedWarnInfo.keySet());
|
||||
warnIds.sort(Comparator.comparing(ServerSpecificId::getId));
|
||||
List<WarnEntry> entries = new ArrayList<>();
|
||||
loadedWarnInfo.keySet().forEach(warning -> {
|
||||
warnIds.forEach(warning -> {
|
||||
Warning warn = warnManagementService.findById(warning.getId(), warning.getServerId());
|
||||
FutureMemberPair memberPair = loadedWarnInfo.get(warning);
|
||||
Member warnedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null;
|
||||
MemberDisplayModel warnedUser = MemberDisplayModel
|
||||
MemberDisplay warnedUser = MemberDisplay
|
||||
.builder()
|
||||
.member(warnedMember)
|
||||
.memberMention(warnedMember != null ? warnedMember.getAsMention() : null)
|
||||
.userId(warn.getWarnedUser().getUserReference().getId())
|
||||
.build();
|
||||
|
||||
Member warningMember = !memberPair.getFirstMember().isCompletedExceptionally() ? memberPair.getFirstMember().join() : null;
|
||||
MemberDisplayModel warningUser = MemberDisplayModel
|
||||
MemberDisplay warningUser = MemberDisplay
|
||||
.builder()
|
||||
.member(warningMember)
|
||||
.memberMention(warningMember != null ? warningMember.getAsMention() : null)
|
||||
.userId(warn.getWarningUser().getUserReference().getId())
|
||||
.build();
|
||||
WarnEntry entry = WarnEntry
|
||||
.builder()
|
||||
.warnedUser(warnedUser)
|
||||
.warningUser(warningUser)
|
||||
.warning(warn)
|
||||
.reason(warn.getReason())
|
||||
.decayDate(warn.getDecayDate())
|
||||
.decayed(warn.getDecayed())
|
||||
.warnId(warn.getWarnId().getId())
|
||||
.warnDate(warn.getWarnDate())
|
||||
.serverId(warn.getWarnId().getServerId())
|
||||
.build();
|
||||
entries.add(entry);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -18,6 +19,10 @@ public interface MuteRepository extends JpaRepository<Mute, ServerSpecificId> {
|
||||
|
||||
List<Mute> findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(AUserInAServer aUserInAServer);
|
||||
|
||||
List<Mute> findAllByMutedUserOrderByMuteId_IdAsc(AUserInAServer aUserInAServer);
|
||||
|
||||
List<Mute> findAllByServerOrderByMuteId_IdAsc(AServer server);
|
||||
|
||||
@NotNull
|
||||
Optional<Mute> findByMuteId_IdAndMuteId_ServerId(Long muteId, Long serverId);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ public interface WarnRepository extends JpaRepository<Warning, ServerSpecificId>
|
||||
Long countByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
List<Warning> findByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
|
||||
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -51,7 +50,7 @@ public class BanServiceBean implements BanService {
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> banMember(Member member, String reason, Member banningMember, Message message) {
|
||||
public CompletableFuture<Void> banMemberWithNotification(Member member, String reason, Member banningMember, Integer deletionDays, Message message) {
|
||||
BanLog banLog = BanLog
|
||||
.builder()
|
||||
.bannedUser(member.getUser())
|
||||
@@ -59,18 +58,19 @@ public class BanServiceBean implements BanService {
|
||||
.commandMessage(message)
|
||||
.reason(reason)
|
||||
.build();
|
||||
CompletableFuture<Void> banFuture = banUser(member.getGuild(), member.getUser(), 0, reason);
|
||||
CompletableFuture<Void> banFuture = banUser(member.getGuild(), member.getUser(), deletionDays, reason);
|
||||
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, member.getGuild().getIdLong(), BAN_LOG_TEMPLATE);
|
||||
return CompletableFuture.allOf(banFuture, messageFuture);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> banUser(User user, String reason, Member banningMember, Message message) {
|
||||
public CompletableFuture<Void> banUserWithNotification(User user, String reason, Member banningMember, Integer deletionDays, Message message) {
|
||||
BanLog banLog = BanLog
|
||||
.builder()
|
||||
.bannedUser(user)
|
||||
.banningMember(banningMember)
|
||||
.commandMessage(message)
|
||||
.deletionDays(deletionDays)
|
||||
.reason(reason)
|
||||
.build();
|
||||
Guild guild = banningMember.getGuild();
|
||||
@@ -82,7 +82,7 @@ public class BanServiceBean implements BanService {
|
||||
.thenAccept(message1 -> log.info("Notified about not being able to send ban notification in server {} and channel {} based on message {} from user {}."
|
||||
, message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong(), message.getAuthor().getIdLong()));
|
||||
}
|
||||
CompletableFuture<Void> banFuture = banUser(guild, user, 0, reason);
|
||||
CompletableFuture<Void> banFuture = banUser(guild, user, deletionDays, reason);
|
||||
CompletableFuture<Void> messageFuture = sendBanLogMessage(banLog, guild.getIdLong(), BAN_LOG_TEMPLATE);
|
||||
CompletableFuture.allOf(banFuture, messageFuture)
|
||||
.thenAccept(unused1 -> returningFuture.complete(null))
|
||||
@@ -108,7 +108,7 @@ public class BanServiceBean implements BanService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> unBanUser(User user, Member unBanningMember) {
|
||||
public CompletableFuture<Void> unBanUserWithNotification(User user, Member unBanningMember) {
|
||||
Guild guild = unBanningMember.getGuild();
|
||||
UnBanLog banLog = UnBanLog
|
||||
.builder()
|
||||
@@ -139,20 +139,14 @@ public class BanServiceBean implements BanService {
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendBanLogMessage(BanLog banLog, Long guildId, String template) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||
log.debug("Sending ban log message in guild {}.", guildId);
|
||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId);
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.BAN_LOG, guildId));
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendUnBanLogMessage(UnBanLog banLog, Long guildId, String template) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend banLogMessage = templateService.renderEmbedTemplate(template, banLog, guildId);
|
||||
log.debug("Sending unban log message in guild {}.", guildId);
|
||||
List<CompletableFuture<Message>> notificationFutures = postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId);
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(notificationFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(banLogMessage, ModerationPostTarget.UN_BAN_LOG, guildId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.InfractionFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.InfractionPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.InfractionLevelChangedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.template.InfractionLevelChangeModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.util.Pair;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class InfractionServiceBean implements InfractionService {
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ConfigManagementService configManagementService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private InfractionServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private InfractionLevelChangedListenerManager infractionLevelChangedListenerManager;
|
||||
|
||||
private static final String INFRACTION_NOTIFICATION_TEMPLATE_KEY = "infraction_level_notification";
|
||||
|
||||
@Override
|
||||
public void decayInfraction(Infraction infraction) {
|
||||
log.info("Decaying infraction {}", infraction.getId());
|
||||
infraction.setDecayed(true);
|
||||
infraction.setDecayedDate(Instant.now());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActiveInfractionPointsForUser(AUserInAServer aUserInAServer) {
|
||||
List<Infraction> infractions = infractionManagementService.getActiveInfractionsForUser(aUserInAServer);
|
||||
log.info("Calculating points for user {} in server {} with {} infractions.",
|
||||
aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId(), infractions.size());
|
||||
return infractions.stream().collect(Collectors.summarizingLong(Infraction::getPoints)).getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Infraction> createInfractionWithNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction createdInfraction = infractionManagementService.createInfraction(aUserInAServer, points);
|
||||
Long infractionId = createdInfraction.getId();
|
||||
return createInfractionNotification(aUserInAServer, points)
|
||||
.thenApply(aBoolean -> self.reloadInfraction(infractionId));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> createInfractionNotification(AUserInAServer aUserInAServer, Long points) {
|
||||
Long serverId = aUserInAServer.getServerReference().getId();
|
||||
Long currentPoints = getActiveInfractionPointsForUser(aUserInAServer);
|
||||
Long newPoints = currentPoints + points;
|
||||
Pair<Integer, Integer> levelChange = infractionLevelChanged(serverId, newPoints, currentPoints);
|
||||
Integer oldLevel = levelChange.getFirst();
|
||||
Integer newLevel = levelChange.getSecond();
|
||||
if(!oldLevel.equals(newLevel)) {
|
||||
InfractionLevelChangeModel model = InfractionLevelChangeModel
|
||||
.builder()
|
||||
.member(MemberDisplay.fromAUserInAServer(aUserInAServer))
|
||||
.newLevel(newLevel)
|
||||
.oldLevel(oldLevel)
|
||||
.oldPoints(currentPoints)
|
||||
.newPoints(newPoints)
|
||||
.build();
|
||||
infractionLevelChangedListenerManager.sendInfractionLevelChangedEvent(newLevel, oldLevel, newPoints, currentPoints, ServerUser.fromAUserInAServer(aUserInAServer));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(INFRACTION_NOTIFICATION_TEMPLATE_KEY, model, serverId);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, InfractionPostTarget.INFRACTION_NOTIFICATION, serverId));
|
||||
} else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Infraction reloadInfraction(Long infractionId) {
|
||||
return infractionManagementService.loadInfraction(infractionId);
|
||||
}
|
||||
|
||||
private Pair<Integer, Integer> infractionLevelChanged(Long serverId, Long newPoints, Long oldPoints) {
|
||||
List<Long> levelConfig = loadInfractionConfig(serverId);
|
||||
Integer newLevel = getInfractionLevel(newPoints, levelConfig);
|
||||
Integer oldLevel = getInfractionLevel(oldPoints, levelConfig);
|
||||
return Pair.of(oldLevel, newLevel);
|
||||
}
|
||||
|
||||
private List<Long> loadInfractionConfig(Long serverId) {
|
||||
Long levelAmount = configService.getLongValueOrConfigDefault(InfractionFeatureConfig.INFRACTION_LEVELS, serverId);
|
||||
List<Long> levelConfig = new ArrayList<>();
|
||||
for (long i = 1; i <= levelAmount; i++) {
|
||||
String levelKey = InfractionFeatureConfig.INFRACTION_LEVEL_PREFIX + i;
|
||||
if(configManagementService.configExists(serverId, levelKey)) {
|
||||
levelConfig.add(configService.getLongValue(levelKey, serverId));
|
||||
}
|
||||
}
|
||||
return levelConfig;
|
||||
}
|
||||
|
||||
private Integer getInfractionLevel(Long points, List<Long> levelConfig) {
|
||||
for (int i = 0; i < levelConfig.size(); i++) {
|
||||
if(points >= levelConfig.get(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -40,10 +40,8 @@ public class KickServiceBean implements KickService {
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendKickLog(KickLogModel kickLogModel) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, kickLogModel.getGuild().getIdLong());
|
||||
log.debug("Sending kick log message in guild {}.", kickLogModel.getGuild().getIdLong());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, kickLogModel.getGuild().getIdLong()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,21 +244,15 @@ public class MuteServiceBean implements MuteService {
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendMuteLog(MuteContext muteLogModel, AServer server) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
log.debug("Sending mute log to the mute post target.");
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, muteLogModel.getContext().getServerId()));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) {
|
||||
CompletableFuture<Void> completableFuture;
|
||||
log.debug("Sending unMute log for mute {} to the mute posttarget in server {}", muteLogModel.getMute().getMuteId().getId(), server.getId());
|
||||
MessageToSend message = templateService.renderEmbedTemplate(UN_MUTE_LOG_TEMPLATE, muteLogModel, server.getId());
|
||||
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId());
|
||||
completableFuture = FutureUtils.toSingleFutureGeneric(completableFutures);
|
||||
return completableFuture;
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,13 +307,16 @@ public class MuteServiceBean implements MuteService {
|
||||
finalFuture.complete(null)
|
||||
).exceptionally(throwable1 -> {
|
||||
log.error("Unmute log failed to send for mute {} in server {}.", muteId, serverId, throwable1);
|
||||
finalFuture.complete(null);
|
||||
finalFuture.completeExceptionally(null);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
finalFuture.complete(null);
|
||||
}
|
||||
return null;
|
||||
}).exceptionally(throwable -> {
|
||||
finalFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return finalFuture;
|
||||
@@ -368,7 +365,7 @@ public class MuteServiceBean implements MuteService {
|
||||
@Override
|
||||
public void completelyUnMuteUser(AUserInAServer aUserInAServer) {
|
||||
log.info("Completely unmuting user {} in server {}.", aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId());
|
||||
List<Mute> allMutesOfUser = muteManagementService.getAllMutesOf(aUserInAServer);
|
||||
List<Mute> allMutesOfUser = muteManagementService.getAllActiveMutesOf(aUserInAServer);
|
||||
allMutesOfUser.forEach(mute -> {
|
||||
mute.setMuteEnded(true);
|
||||
cancelUnMuteJob(mute);
|
||||
|
||||
@@ -100,9 +100,13 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
||||
|
||||
@Transactional
|
||||
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser reporter) {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
if(reportMessage == null) {
|
||||
log.info("Creation reaction report about message {} was not sent - post target might be disabled in server {}.", cachedMessage.getMessageId(), cachedMessage.getServerId());
|
||||
} else {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
@@ -12,16 +13,20 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningDecayFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarnDecayMode;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarningMode;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarnDecayPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarningPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.WarningCreatedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnContext;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnNotification;
|
||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayLogModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayWarning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.listener.WarnDecayMemberNotificationModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
@@ -85,6 +90,18 @@ public class WarnServiceBean implements WarnService {
|
||||
@Autowired
|
||||
private WarnServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private WarningCreatedListenerManager warningCreatedListenerManager;
|
||||
|
||||
public static final String WARN_LOG_TEMPLATE = "warn_log";
|
||||
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
|
||||
public static final String WARNINGS_COUNTER_KEY = "WARNINGS";
|
||||
@@ -100,22 +117,41 @@ public class WarnServiceBean implements WarnService {
|
||||
Member warningMember = context.getMember();
|
||||
Guild guild = warnedMember.getGuild();
|
||||
log.info("User {} is warning {} in server {}", warnedMember.getId(), warningMember.getId(), guild.getIdLong());
|
||||
WarnNotification warnNotification = WarnNotification.builder().reason(context.getReason()).warnId(warningId).serverName(guild.getName()).build();
|
||||
WarnNotification warnNotification = WarnNotification
|
||||
.builder()
|
||||
.reason(context.getReason())
|
||||
.warnId(warningId)
|
||||
.serverName(guild.getName())
|
||||
.build();
|
||||
Long serverId = server.getId();
|
||||
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification, server.getId());
|
||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||
futures.add(messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage));
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
CompletableFuture<Void> notificationFuture = new CompletableFuture<>();
|
||||
messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage).whenComplete((message, throwable) -> {
|
||||
if(throwable != null) {
|
||||
log.warn("Failed to notify user {} of warning {} in guild {}.", warnedMember.getId(), warningId, serverId);
|
||||
}
|
||||
notificationFuture.complete(null);
|
||||
});
|
||||
futures.add(notificationFuture);
|
||||
log.debug("Logging warning for server {}.", server.getId());
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, serverId)) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(WarningFeatureConfig.WARN_INFRACTION_POINTS, serverId);
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(warnedMember);
|
||||
warnedUser.setServerReference(server);
|
||||
futures.add(infractionService.createInfractionWithNotification(warnedUser, infractionPoints)
|
||||
.thenAccept(infraction -> context.setInfractionId(infraction.getId())));
|
||||
}
|
||||
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context, server.getId());
|
||||
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(futures);
|
||||
return FutureUtils.toSingleFuture(futures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> warnUserWithLog(WarnContext context) {
|
||||
return notifyAndLogFullUserWarning(context).thenAccept(aVoid ->
|
||||
self.persistWarning(context)
|
||||
);
|
||||
return notifyAndLogFullUserWarning(context)
|
||||
.thenAccept(aVoid -> self.persistWarning(context));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -124,8 +160,15 @@ public class WarnServiceBean implements WarnService {
|
||||
context.getWarnId(), context.getGuild().getId(), context.getWarnedMember().getId(), context.getMember().getId());
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(context.getWarnedMember());
|
||||
AUserInAServer warningUser = userInServerManagementService.loadOrCreateUser(context.getMember());
|
||||
warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
|
||||
Warning createdWarning = warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
if(context.getInfractionId() != null) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(context.getInfractionId());
|
||||
createdWarning.setInfraction(infraction);
|
||||
}
|
||||
ServerUser warnedServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerUser warningServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerChannelMessage commandMessage = ServerChannelMessage.fromMessage(context.getMessage());
|
||||
warningCreatedListenerManager.sendWarningCreatedEvent(createdWarning.getWarnId(), warnedServerUser, warningServerUser, context.getReason(), commandMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -235,10 +278,13 @@ public class WarnServiceBean implements WarnService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decayWarning(Warning warning, Instant now) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), now);
|
||||
warning.setDecayDate(now);
|
||||
public void decayWarning(Warning warning, Instant decayDate) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), decayDate);
|
||||
warning.setDecayDate(decayDate);
|
||||
warning.setDecayed(true);
|
||||
if(warning.getInfraction() != null) {
|
||||
infractionService.decayInfraction(warning.getInfraction());
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
||||
@@ -269,6 +315,9 @@ public class WarnServiceBean implements WarnService {
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
}).exceptionally(throwable -> {
|
||||
sendingFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return sendingFuture;
|
||||
@@ -304,8 +353,7 @@ public class WarnServiceBean implements WarnService {
|
||||
.warnings(warnDecayWarnings)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WARN_DECAY_LOG_TEMPLATE_KEY, warnDecayLogModel, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.repository.InfractionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class InfractionManagementServiceBean implements InfractionManagementService{
|
||||
|
||||
@Autowired
|
||||
private InfractionRepository infractionRepository;
|
||||
|
||||
@Override
|
||||
public Infraction createInfraction(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction infraction = Infraction
|
||||
.builder()
|
||||
.user(aUserInAServer)
|
||||
.server(aUserInAServer.getServerReference())
|
||||
.points(points)
|
||||
.build();
|
||||
return infractionRepository.save(infraction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Infraction> getActiveInfractionsForUser(AUserInAServer aUserInAServer) {
|
||||
return infractionRepository.findByUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Infraction loadInfraction(Long infraction) {
|
||||
return infractionRepository.getOne(infraction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.moderation.service.management;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||
@@ -84,9 +85,19 @@ public class MuteManagementServiceBean implements MuteManagementService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mute> getAllMutesOf(AUserInAServer aUserInAServer) {
|
||||
public List<Mute> getAllActiveMutesOf(AUserInAServer aUserInAServer) {
|
||||
return muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mute> getAllMutesOf(AUserInAServer aUserInAServer) {
|
||||
return muteRepository.findAllByMutedUserOrderByMuteId_IdAsc(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Mute> getAllMutes(AServer server) {
|
||||
return muteRepository.findAllByServerOrderByMuteId_IdAsc(server);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -70,10 +70,15 @@ public class WarnManagementServiceBean implements WarnManagementService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
public Long getActiveWarnCountForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Warning> getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.findByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Warning> findByIdOptional(Long id, Long serverId) {
|
||||
return warnRepository.findByWarnId_IdAndWarnId_ServerId(id, serverId);
|
||||
|
||||
@@ -0,0 +1,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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="moderationModule" value="(SELECT id FROM module WHERE name = 'moderation')"/>
|
||||
<property name="moderationFeature" value="(SELECT id FROM feature WHERE key = 'moderation')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="mutes-command">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="mutes"/>
|
||||
<column name="module_id" valueComputed="${moderationModule}"/>
|
||||
<column name="feature_id" valueComputed="${moderationFeature}"/>
|
||||
</insert>
|
||||
</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="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="update/update.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>
|
||||
@@ -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="infraction_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="infractions"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="infraction-table">
|
||||
<createTable tableName="infraction">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_infraction"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="points" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="decayed_date" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="decayed" type="BOOLEAN"/>
|
||||
<column name="infraction_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="infraction" constraintName="fk_infraction_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id"
|
||||
referencedTableName="server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_user_in_server_id" baseTableName="infraction" constraintName="fk_infraction_user_in_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS infraction_update_trigger ON infraction;
|
||||
CREATE TRIGGER infraction_update_trigger BEFORE UPDATE ON infraction FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS infraction_insert_trigger ON infraction;
|
||||
CREATE TRIGGER infraction_insert_trigger BEFORE INSERT ON infraction FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="infraction.xml" relativeToChangelogFile="true"/>
|
||||
<include file="warning.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="warning-infraction_id">
|
||||
<addColumn tableName="warning">
|
||||
<column name="infraction_id" type="BIGINT" />
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseColumnNames="infraction_id" baseTableName="warning" constraintName="fk_warning_infraction"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="infraction" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -6,10 +6,10 @@
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="warn-decay-job-update_schedule">
|
||||
<update tableName="scheduler_job">
|
||||
<column name="cron_expression" value="0 0 0 * * ?"/>
|
||||
<where>name='warnDecayJob'</where>
|
||||
<changeSet author="Sheldan" id="command-rename_soft_ban">
|
||||
<update tableName="command">
|
||||
<column name="name" value="banDelete"/>
|
||||
<where>name='softBan'</where>
|
||||
</update>
|
||||
</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="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -11,4 +11,6 @@
|
||||
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.10/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -7,6 +7,9 @@ abstracto.systemConfigs.reactionReportCooldownSeconds.longValue=300
|
||||
abstracto.featureFlags.moderation.featureName=moderation
|
||||
abstracto.featureFlags.moderation.enabled=false
|
||||
|
||||
abstracto.featureFlags.infractions.featureName=infractions
|
||||
abstracto.featureFlags.infractions.enabled=false
|
||||
|
||||
abstracto.featureFlags.reportReactions.featureName=reportReactions
|
||||
abstracto.featureFlags.reportReactions.enabled=false
|
||||
|
||||
@@ -42,6 +45,31 @@ abstracto.featureModes.warnDecayLogging.featureName=warnings
|
||||
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
|
||||
abstracto.featureModes.warnDecayLogging.enabled=true
|
||||
|
||||
abstracto.featureModes.infractionReporting.featureName=infractions
|
||||
abstracto.featureModes.infractionReporting.mode=infractionReporting
|
||||
abstracto.featureModes.infractionReporting.enabled=true
|
||||
|
||||
abstracto.systemConfigs.infractionLvl1.name=infractionLvl1
|
||||
abstracto.systemConfigs.infractionLvl1.longValue=10
|
||||
|
||||
abstracto.systemConfigs.infractionLvl2.name=infractionLvl2
|
||||
abstracto.systemConfigs.infractionLvl2.longValue=20
|
||||
|
||||
abstracto.systemConfigs.infractionLvl3.name=infractionLvl3
|
||||
abstracto.systemConfigs.infractionLvl3.longValue=30
|
||||
|
||||
abstracto.systemConfigs.infractionLvl4.name=infractionLvl4
|
||||
abstracto.systemConfigs.infractionLvl4.longValue=40
|
||||
|
||||
abstracto.systemConfigs.infractionLvl5.name=infractionLvl5
|
||||
abstracto.systemConfigs.infractionLvl5.longValue=50
|
||||
|
||||
abstracto.systemConfigs.infractionLevels.name=infractionLevels
|
||||
abstracto.systemConfigs.infractionLevels.longValue=5
|
||||
|
||||
abstracto.systemConfigs.warnInfractionPoints.name=warnInfractionPoints
|
||||
abstracto.systemConfigs.warnInfractionPoints.longValue=0
|
||||
|
||||
abstracto.featureModes.automaticWarnDecayLogging.featureName=warnDecay
|
||||
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
||||
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
|
||||
|
||||
@@ -5,7 +5,6 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.moderation.service.BanService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
@@ -41,7 +40,7 @@ public class BanTest {
|
||||
public void testBanWithReason() {
|
||||
String customReason = "reason2";
|
||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(bannedMember, customReason));
|
||||
when(banService.banUser(eq(bannedMember), eq(customReason), banLogModelCaptor.capture(), any(Message.class))).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(banService.banUserWithNotification(eq(bannedMember), eq(customReason), banLogModelCaptor.capture(), eq(0), any(Message.class))).thenReturn(CompletableFuture.completedFuture(null));
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
||||
Member banningMember = banLogModelCaptor.getValue();
|
||||
Assert.assertEquals(parameters.getAuthor(), banningMember);
|
||||
|
||||
@@ -49,7 +49,7 @@ public class MyWarningsTest {
|
||||
Long activeWarnCount = 8L;
|
||||
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(userInServerManagementService.loadOrCreateUser(noParameter.getAuthor())).thenReturn(aUserInAServer);
|
||||
when(warnManagementService.getActiveWarnsForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
||||
when(warnManagementService.getActiveWarnCountForUser(aUserInAServer)).thenReturn(activeWarnCount);
|
||||
Long totalWarnCount = 10L;
|
||||
when(warnManagementService.getTotalWarnsForUser(aUserInAServer)).thenReturn(totalWarnCount);
|
||||
CommandResult result = testUnit.execute(noParameter);
|
||||
|
||||
@@ -1,125 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.command;
|
||||
|
||||
import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
|
||||
import com.jagrosh.jdautilities.menu.Paginator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.PaginatorService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandConfigValidator;
|
||||
import dev.sheldan.abstracto.core.test.command.CommandTestUtilities;
|
||||
import dev.sheldan.abstracto.moderation.converter.WarnEntryConverter;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnEntry;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarningsModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WarningsTest {
|
||||
|
||||
@InjectMocks
|
||||
private Warnings testUnit;
|
||||
|
||||
@Mock
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private WarnEntryConverter warnEntryConverter;
|
||||
|
||||
@Mock
|
||||
private PaginatorService paginatorService;
|
||||
|
||||
@Mock
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Mock
|
||||
private EventWaiter eventWaiter;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<WarningsModel> captor;
|
||||
|
||||
@Mock
|
||||
private Warnings self;
|
||||
|
||||
private static final Long SERVER_ID = 1L;
|
||||
|
||||
@Test
|
||||
public void testNoParametersForWarningsCommand(){
|
||||
CommandContext noParams = CommandTestUtilities.getNoParameters();
|
||||
Warning firstWarning = Mockito.mock(Warning.class);
|
||||
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
|
||||
Warning secondWarning = Mockito.mock(Warning.class);
|
||||
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
|
||||
List<Warning> warningsToDisplay = Arrays.asList(firstWarning, secondWarning);
|
||||
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
|
||||
AServer server = Mockito.mock(AServer.class);
|
||||
when(serverManagementService.loadServer(noParams.getGuild())).thenReturn(server);
|
||||
when(warnManagementService.getAllWarningsOfServer(server)).thenReturn(warningsToDisplay);
|
||||
when(warnEntryConverter.fromWarnings(warningsToDisplay)).thenReturn(CompletableFuture.completedFuture(modelWarnings));
|
||||
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(noParams);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
verify(self, times(1)).renderWarnings(noParams, modelWarnings);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWarningsRendering() {
|
||||
CommandContext noParams = CommandTestUtilities.getNoParameters();
|
||||
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
|
||||
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
|
||||
Paginator paginator = Mockito.mock(Paginator.class);
|
||||
when(noParams.getGuild().getIdLong()).thenReturn(SERVER_ID);
|
||||
when(paginatorService.createPaginatorFromTemplate(eq(Warnings.WARNINGS_RESPONSE_TEMPLATE), captor.capture(), eq(eventWaiter), eq(SERVER_ID))).thenReturn(paginator);
|
||||
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
|
||||
testUnit.renderWarnings(noParams, modelWarnings);
|
||||
WarningsModel warningsModel = captor.getValue();
|
||||
Assert.assertEquals(firstModelWarning, warningsModel.getWarnings().get(0));
|
||||
Assert.assertEquals(secondModelWarning, warningsModel.getWarnings().get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecuteWarningsForMember(){
|
||||
Member member = Mockito.mock(Member.class);
|
||||
CommandContext parameters = CommandTestUtilities.getWithParameters(Arrays.asList(member));
|
||||
when(member.getGuild()).thenReturn(parameters.getGuild());
|
||||
AUserInAServer warnedUser = Mockito.mock(AUserInAServer.class);
|
||||
Warning firstWarning = Mockito.mock(Warning.class);
|
||||
WarnEntry firstModelWarning = Mockito.mock(WarnEntry.class);
|
||||
Warning secondWarning = Mockito.mock(Warning.class);
|
||||
WarnEntry secondModelWarning = Mockito.mock(WarnEntry.class);
|
||||
List<Warning> warningsToDisplay = Arrays.asList(firstWarning, secondWarning);
|
||||
List<WarnEntry> modelWarnings = Arrays.asList(firstModelWarning, secondModelWarning);
|
||||
when(userInServerManagementService.loadOrCreateUser(member)).thenReturn(warnedUser);
|
||||
when(warnManagementService.getAllWarnsForUser(warnedUser)).thenReturn(warningsToDisplay);
|
||||
when(warnEntryConverter.fromWarnings(warningsToDisplay)).thenReturn(CompletableFuture.completedFuture(modelWarnings));
|
||||
|
||||
CompletableFuture<CommandResult> result = testUnit.executeAsync(parameters);
|
||||
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
|
||||
verify(self, times(1)).renderWarnings(parameters, modelWarnings);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateCommand() {
|
||||
CommandConfigValidator.validateCommandConfiguration(testUnit.getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.model.database.UserNote;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.NoteEntryModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.UserNoteManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class UserNotesConverterTest {
|
||||
|
||||
@InjectMocks
|
||||
private UserNotesConverter testUnit;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private UserNotesConverter self;
|
||||
|
||||
@Mock
|
||||
private UserNoteManagementService userNoteManagementService;
|
||||
|
||||
private static final Long SERVER_ID = 3L;
|
||||
private static final Long USER_NOTE_ID = 4L;
|
||||
|
||||
@Test
|
||||
public void testWithEmptyList() {
|
||||
CompletableFuture<List<NoteEntryModel>> entryModels = testUnit.fromNotes(Collections.emptyList());
|
||||
Assert.assertEquals(0, entryModels.join().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSomeUserNotes() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Member member = Mockito.mock(Member.class);
|
||||
when(memberService.getMemberInServerAsync(userInAServer)).thenReturn(CompletableFuture.completedFuture(member));
|
||||
UserNote firstNote = Mockito.mock(UserNote.class);
|
||||
when(firstNote.getUser()).thenReturn(userInAServer);
|
||||
UserNote secondNote = Mockito.mock(UserNote.class);
|
||||
when(secondNote.getUser()).thenReturn(userInAServer);
|
||||
testUnit.fromNotes(Arrays.asList(firstNote, secondNote));
|
||||
verify(self, times(1)).loadFullNotes(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadingFullNotes() {
|
||||
AUserInAServer userInAServer = Mockito.mock(AUserInAServer.class);
|
||||
Member member = Mockito.mock(Member.class);
|
||||
UserNote note1 = Mockito.mock(UserNote.class);
|
||||
UserNote note2 = Mockito.mock(UserNote.class);
|
||||
when(note1.getUser()).thenReturn(userInAServer);
|
||||
when(note2.getUser()).thenReturn(userInAServer);
|
||||
ServerSpecificId firstUserNoteId = new ServerSpecificId(SERVER_ID, USER_NOTE_ID);
|
||||
ServerSpecificId secondUserNoteId = new ServerSpecificId(SERVER_ID, USER_NOTE_ID + 1);
|
||||
HashMap<ServerSpecificId, CompletableFuture<Member>> map = new HashMap<>();
|
||||
map.put(firstUserNoteId, CompletableFuture.completedFuture(member));
|
||||
map.put(secondUserNoteId, CompletableFuture.completedFuture(member));
|
||||
when(userNoteManagementService.loadNote(SERVER_ID, USER_NOTE_ID)).thenReturn(note1);
|
||||
when(userNoteManagementService.loadNote(SERVER_ID, USER_NOTE_ID + 1)).thenReturn(note2);
|
||||
List<NoteEntryModel> models = testUnit.loadFullNotes(map);
|
||||
Assert.assertEquals(2, models.size());
|
||||
NoteEntryModel firstEntry = models.get(0);
|
||||
Assert.assertEquals(member, firstEntry.getFullUser().getMember());
|
||||
Assert.assertEquals(userInAServer, firstEntry.getFullUser().getAUserInAServer());
|
||||
NoteEntryModel secondEntry = models.get(1);
|
||||
Assert.assertEquals(member, secondEntry.getFullUser().getMember());
|
||||
Assert.assertEquals(userInAServer, secondEntry.getFullUser().getAUserInAServer());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
package dev.sheldan.abstracto.moderation.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnEntry;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@Slf4j
|
||||
public class WarnEntryConverterTest {
|
||||
|
||||
@InjectMocks
|
||||
private WarnEntryConverter testUnit;
|
||||
|
||||
@Mock
|
||||
private MemberService memberService;
|
||||
|
||||
@Mock
|
||||
private WarnEntryConverter self;
|
||||
|
||||
@Mock
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@Mock
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
private static final Long SERVER_ID = 5L;
|
||||
private static final Long WARN_ID_1 = 6L;
|
||||
private static final Long WARN_ID_2 = 7L;
|
||||
private static final Long USER_ID_1 = 8L;
|
||||
private static final Long USER_ID_2 = 9L;
|
||||
|
||||
@Test
|
||||
public void testWithEmptyList() {
|
||||
CompletableFuture<List<WarnEntry>> entryModels = testUnit.fromWarnings(Collections.emptyList());
|
||||
Assert.assertEquals(0, entryModels.join().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSomeWarnings() {
|
||||
AUserInAServer warnedUser = Mockito.mock(AUserInAServer.class);
|
||||
AUserInAServer warningUser = Mockito.mock(AUserInAServer.class);
|
||||
Member warnedMember = Mockito.mock(Member.class);
|
||||
Member warningMember = Mockito.mock(Member.class);
|
||||
when(memberService.getMemberInServerAsync(warnedUser)).thenReturn(CompletableFuture.completedFuture(warnedMember));
|
||||
when(memberService.getMemberInServerAsync(warningUser)).thenReturn(CompletableFuture.completedFuture(warningMember));
|
||||
Warning firstWarning = Mockito.mock(Warning.class);
|
||||
when(firstWarning.getWarningUser()).thenReturn(warningUser);
|
||||
when(firstWarning.getWarnedUser()).thenReturn(warnedUser);
|
||||
Warning secondWarning = Mockito.mock(Warning.class);
|
||||
when(secondWarning.getWarningUser()).thenReturn(warningUser);
|
||||
when(secondWarning.getWarnedUser()).thenReturn(warnedUser);
|
||||
List<WarnEntry> loaded = new ArrayList<>();
|
||||
when(self.loadFullWarnEntries(any())).thenReturn(loaded);
|
||||
CompletableFuture<List<WarnEntry>> future = testUnit.fromWarnings(Arrays.asList(firstWarning, secondWarning));
|
||||
List<WarnEntry> entries = future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
Assert.assertEquals(loaded, entries);
|
||||
verify(self, times(1)).loadFullWarnEntries(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadingFullWarnings() {
|
||||
AUserInAServer warnedUser = Mockito.mock(AUserInAServer.class);
|
||||
AUserInAServer warningUser = Mockito.mock(AUserInAServer.class);
|
||||
AUser firstUser = Mockito.mock(AUser.class);
|
||||
when(firstUser.getId()).thenReturn(USER_ID_1);
|
||||
when(warnedUser.getUserReference()).thenReturn(firstUser);
|
||||
AUser secondUser = Mockito.mock(AUser.class);
|
||||
when(secondUser.getId()).thenReturn(USER_ID_2);
|
||||
when(warningUser.getUserReference()).thenReturn(secondUser);
|
||||
Member warningMember = Mockito.mock(Member.class);
|
||||
Member warnedMember = Mockito.mock(Member.class);
|
||||
Warning warning1 = Mockito.mock(Warning.class);
|
||||
Warning warning2 = Mockito.mock(Warning.class);
|
||||
ServerSpecificId firstWarnId = new ServerSpecificId(SERVER_ID, WARN_ID_1);
|
||||
when(warning1.getWarnId()).thenReturn(firstWarnId);
|
||||
when(warning1.getWarningUser()).thenReturn(warningUser);
|
||||
when(warning1.getWarnedUser()).thenReturn(warnedUser);
|
||||
ServerSpecificId secondWarnId = new ServerSpecificId(SERVER_ID, WARN_ID_2);
|
||||
when(warning2.getWarnId()).thenReturn(secondWarnId);
|
||||
when(warning2.getWarningUser()).thenReturn(warningUser);
|
||||
when(warning2.getWarnedUser()).thenReturn(warnedUser);
|
||||
HashMap<ServerSpecificId, FutureMemberPair> map = new HashMap<>();
|
||||
FutureMemberPair memberPair = Mockito.mock(FutureMemberPair.class);
|
||||
when(memberPair.getFirstMember()).thenReturn(CompletableFuture.completedFuture(warningMember));
|
||||
when(memberPair.getSecondMember()).thenReturn(CompletableFuture.completedFuture(warnedMember));
|
||||
map.put(firstWarnId, memberPair);
|
||||
map.put(secondWarnId, memberPair);
|
||||
when(warnManagementService.findById(WARN_ID_1, SERVER_ID)).thenReturn(warning1);
|
||||
when(warnManagementService.findById(WARN_ID_2, SERVER_ID)).thenReturn(warning2);
|
||||
List<WarnEntry> models = testUnit.loadFullWarnEntries(map);
|
||||
Assert.assertEquals(2, models.size());
|
||||
WarnEntry firstEntry = models.get(0);
|
||||
Assert.assertEquals(warningMember, firstEntry.getWarningUser().getMember());
|
||||
Assert.assertEquals(warnedMember, firstEntry.getWarnedUser().getMember());
|
||||
Assert.assertEquals(USER_ID_1, firstEntry.getWarnedUser().getUserId());
|
||||
Assert.assertEquals(USER_ID_2, firstEntry.getWarningUser().getUserId());
|
||||
Assert.assertEquals(WARN_ID_1, firstEntry.getWarning().getWarnId().getId());
|
||||
Assert.assertEquals(SERVER_ID, firstEntry.getWarning().getWarnId().getServerId());
|
||||
WarnEntry secondEntry = models.get(1);
|
||||
Assert.assertEquals(warningMember, secondEntry.getWarningUser().getMember());
|
||||
Assert.assertEquals(warnedMember, secondEntry.getWarnedUser().getMember());
|
||||
Assert.assertEquals(USER_ID_1, secondEntry.getWarnedUser().getUserId());
|
||||
Assert.assertEquals(USER_ID_2, secondEntry.getWarningUser().getUserId());
|
||||
Assert.assertEquals(WARN_ID_2, secondEntry.getWarning().getWarnId().getId());
|
||||
Assert.assertEquals(SERVER_ID, secondEntry.getWarning().getWarnId().getServerId());
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class BanServiceBeanTest {
|
||||
when(mockedGuild.ban(user, 0, REASON)).thenReturn(mockedAction);
|
||||
MessageToSend mockedMessage = Mockito.mock(MessageToSend.class);
|
||||
when(templateService.renderEmbedTemplate(eq(BanServiceBean.BAN_LOG_TEMPLATE), any(), eq(SERVER_ID))).thenReturn(mockedMessage);
|
||||
testUnit.banMember(memberToBan, REASON, banningMember, message);
|
||||
testUnit.banMemberWithNotification(memberToBan, REASON, banningMember, 0, message);
|
||||
verify(mockedGuild, times(1)).ban(user, 0, REASON);
|
||||
verify(postTargetService, times(1)).sendEmbedInPostTarget(mockedMessage, ModerationPostTarget.BAN_LOG, SERVER_ID);
|
||||
}
|
||||
|
||||
@@ -361,7 +361,7 @@ public class MuteServiceBeanTest {
|
||||
public void testCompletelyUnMuteNotMutedUser() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList());
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList());
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(0)).saveMute(any(Mute.class));
|
||||
}
|
||||
@@ -370,7 +370,7 @@ public class MuteServiceBeanTest {
|
||||
public void testCompletelyUnMuteNotScheduledMuteUser() {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
verify(schedulerService, times(0)).stopTrigger(anyString());
|
||||
@@ -381,7 +381,7 @@ public class MuteServiceBeanTest {
|
||||
when(mute.getTriggerKey()).thenReturn(TRIGGER);
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
testUnit.completelyUnMuteUser(userBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
verify(schedulerService, times(1)).stopTrigger(TRIGGER);
|
||||
@@ -392,7 +392,7 @@ public class MuteServiceBeanTest {
|
||||
when(userBeingMuted.getUserReference()).thenReturn(user);
|
||||
when(userBeingMuted.getServerReference()).thenReturn(server);
|
||||
when(mute.getTriggerKey()).thenReturn(TRIGGER);
|
||||
when(muteManagementService.getAllMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
when(muteManagementService.getAllActiveMutesOf(userBeingMuted)).thenReturn(Arrays.asList(mute));
|
||||
when(userInServerManagementService.loadOrCreateUser(memberBeingMuted)).thenReturn(userBeingMuted);
|
||||
testUnit.completelyUnMuteMember(memberBeingMuted);
|
||||
verify(muteManagementService, times(1)).saveMute(any(Mute.class));
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
@@ -134,6 +135,9 @@ public class WarnServiceBeanTest {
|
||||
@Mock
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Mock
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
private static final String NOTIFICATION_TEXT = "text";
|
||||
private static final String GUILD_NAME = "guild";
|
||||
private static final Long SERVER_ID = 4L;
|
||||
@@ -204,6 +208,7 @@ public class WarnServiceBeanTest {
|
||||
public void testWarnFullUser() {
|
||||
setupWarnContext();
|
||||
setupMocksForWarning();
|
||||
when(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, SERVER_ID)).thenReturn(false);
|
||||
CompletableFuture<Void> future = testUnit.notifyAndLogFullUserWarning(context);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
|
||||
@@ -126,7 +126,7 @@ public class MuteManagementServiceBeanTest {
|
||||
Mute mute = Mockito.mock(Mute.class);
|
||||
Mute mute2 = Mockito.mock(Mute.class);
|
||||
when(muteRepository.findAllByMutedUserAndMuteEndedFalseOrderByMuteId_IdDesc(userInAServer)).thenReturn(Arrays.asList(mute, mute2));
|
||||
List<Mute> allMutesOf = testUnit.getAllMutesOf(userInAServer);
|
||||
List<Mute> allMutesOf = testUnit.getAllActiveMutesOf(userInAServer);
|
||||
Assert.assertEquals(2, allMutesOf.size());
|
||||
Assert.assertEquals(mute, allMutesOf.get(0));
|
||||
Assert.assertEquals(mute2, allMutesOf.get(1));
|
||||
|
||||
@@ -97,7 +97,7 @@ public class WarnManagementServiceBeanTest {
|
||||
public void testActiveWarnCountOfUser() {
|
||||
Long count = 5L;
|
||||
when(warnRepository.countByWarnedUserAndDecayedFalse(warnedUser)).thenReturn(count);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnsForUser(warnedUser);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnCountForUser(warnedUser);
|
||||
Assert.assertEquals(count, activeWarnsForUserCount);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.3.8</version>
|
||||
<version>1.3.13</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -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"),
|
||||
USER_NOTES("userNotes"),
|
||||
INVITE_FILTER("inviteFilter"),
|
||||
REPORT_REACTIONS("reportReactions")
|
||||
REPORT_REACTIONS("reportReactions"),
|
||||
INFRACTIONS("infractions")
|
||||
;
|
||||
|
||||
private final String key;
|
||||
|
||||
@@ -15,6 +15,8 @@ import java.util.List;
|
||||
@Component
|
||||
public class WarningFeatureConfig implements FeatureConfig {
|
||||
|
||||
public static final String WARN_INFRACTION_POINTS = "warnInfractionPoints";
|
||||
|
||||
@Autowired
|
||||
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> {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user