mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-20 06:48:20 +00:00
Compare commits
29 Commits
abstracto-
...
abstracto-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a39b6695a6 | ||
|
|
362d87778e | ||
|
|
0514d355c7 | ||
|
|
8909e8ebe5 | ||
|
|
36ca9b11e4 | ||
|
|
4a66b7fc67 | ||
|
|
b2a94059e2 | ||
|
|
16e6caa1f0 | ||
|
|
da1a71ecdc | ||
|
|
0646efe33d | ||
|
|
db856f2647 | ||
|
|
1d85eb1e7e | ||
|
|
5e6999cd45 | ||
|
|
9659a3487a | ||
|
|
6d27c487f2 | ||
|
|
8ac3b327e4 | ||
|
|
448332f24f | ||
|
|
d7f889971d | ||
|
|
69abff77fb | ||
|
|
2c31fa1c1e | ||
|
|
19a4858da1 | ||
|
|
3ed1f0c54a | ||
|
|
d01e46a9a6 | ||
|
|
222250b795 | ||
|
|
9a87b75998 | ||
|
|
b16cef0d3c | ||
|
|
cc55934ff2 | ||
|
|
168b4a52c8 | ||
|
|
73b5684a7e |
@@ -14,7 +14,7 @@ An example implementation of this bot can be seen [here](https://github.com/Shel
|
||||
|
||||
|
||||
## Technologies
|
||||
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 4.3.0_284
|
||||
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 4.3.0_315
|
||||
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more)
|
||||
* [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA.
|
||||
* [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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)
|
||||
|
||||
@@ -149,6 +149,9 @@ public class AssignableRoleButtonClickedListener implements ButtonClickedListene
|
||||
self.persistAssignableUser(member, payload, false);
|
||||
});
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to perform role change in assignable role place.", throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
assignableRoleService.removeAssignableRoleFromUser(roleById, member)
|
||||
|
||||
@@ -205,16 +205,15 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
|
||||
if (throwable != null) {
|
||||
log.warn("Not able to delete old messages of assignable role place {} in server {}.", assignablePlaceId, serverId);
|
||||
}
|
||||
try {
|
||||
self.createAssignableRolePlacePost(serverId, assignablePlaceId)
|
||||
.thenAccept(unused1 -> postingFuture.complete(null))
|
||||
.exceptionally(innerThrowable -> {
|
||||
postingFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
postingFuture.completeExceptionally(ex);
|
||||
}
|
||||
self.createAssignableRolePlacePost(serverId, assignablePlaceId)
|
||||
.thenAccept(unused1 -> postingFuture.complete(null))
|
||||
.exceptionally(innerThrowable -> {
|
||||
postingFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
}).exceptionally(throwable -> {
|
||||
postingFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return postingFuture;
|
||||
}
|
||||
@@ -361,17 +360,16 @@ public class AssignableRolePlaceServiceBean implements AssignableRolePlaceServic
|
||||
if (throwable != null) {
|
||||
log.warn("Not able to delete old messages of assignable role place {} in server {}.", assignablePlaceId, serverId);
|
||||
}
|
||||
try {
|
||||
self.setupAssignableRolePlaceInChannel(serverId, assignablePlaceId, newChannel)
|
||||
.thenAccept(unused1 -> self.updateAssignableRolePlaceChannel(name, newChannel))
|
||||
.thenAccept(unused1 -> returnFuture.complete(null))
|
||||
.exceptionally(innerThrowable -> {
|
||||
returnFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
returnFuture.completeExceptionally(ex);
|
||||
}
|
||||
self.setupAssignableRolePlaceInChannel(serverId, assignablePlaceId, newChannel)
|
||||
.thenAccept(unused1 -> self.updateAssignableRolePlaceChannel(name, newChannel))
|
||||
.thenAccept(unused1 -> returnFuture.complete(null))
|
||||
.exceptionally(innerThrowable -> {
|
||||
returnFuture.completeExceptionally(innerThrowable);
|
||||
return null;
|
||||
});
|
||||
}).exceptionally(throwable -> {
|
||||
returnFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return returnFuture;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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)
|
||||
|
||||
@@ -37,16 +37,18 @@ public class JoiningUserRoleListener implements AsyncJoinListener {
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MemberJoinModel model) {
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(model.getServerId(), model.getJoiningUser().getUserId());
|
||||
Optional<AUserExperience> userExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(userInAServer.getUserInServerId());
|
||||
if(userExperienceOptional.isPresent()) {
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
userExperienceService.syncForSingleUser(userExperienceOptional.get()).thenAccept(result ->
|
||||
log.info("Finished re-assigning experience for re-joining user {} in server {}.", model.getJoiningUser().getUserId(), model.getServerId())
|
||||
);
|
||||
} else {
|
||||
log.info("Joined user {} in server {} does not have any previous experience. Not setting up anything.", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
}
|
||||
Optional<AUserInAServer> userInAServerOptional = userInServerManagementService.loadUserOptional(model.getServerId(), model.getJoiningUser().getUserId());
|
||||
userInAServerOptional.ifPresent(aUserInAServer -> {
|
||||
Optional<AUserExperience> userExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(aUserInAServer.getUserInServerId());
|
||||
if(userExperienceOptional.isPresent()) {
|
||||
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
userExperienceService.syncForSingleUser(userExperienceOptional.get()).thenAccept(result ->
|
||||
log.info("Finished re-assigning experience for re-joining user {} in server {}.", model.getJoiningUser().getUserId(), model.getServerId())
|
||||
);
|
||||
} else {
|
||||
log.info("Joined user {} in server {} does not have any previous experience. Not setting up anything.", model.getJoiningUser().getUserId(), model.getServerId());
|
||||
}
|
||||
});
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@@ -166,6 +166,9 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
FutureUtils.toSingleFutureGeneric(memberFutures).whenComplete((unused, throwable) -> {
|
||||
self.updateFoundMembers(memberFutures, serverExp.getServerId(), resultFutures, futures);
|
||||
experienceFuture.complete(null);
|
||||
}).exceptionally(throwable -> {
|
||||
experienceFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
return experienceFuture
|
||||
|
||||
@@ -39,7 +39,6 @@ public class HasLevelCondition implements SystemCondition {
|
||||
Map<String, Object> parameters = conditionContext.getParameters();
|
||||
Long userInServerId = (Long) parameters.get(USER_IN_SERVER_ID_VARIABLE_KEY);
|
||||
Integer level = (Integer) parameters.get(LEVEL_VARIABLE);
|
||||
log.info("Evaluating has level condition.");
|
||||
Optional<AUserInAServer> userInServerOptional = userInServerManagementService.loadUserOptional(userInServerId);
|
||||
if(userInServerOptional.isPresent()) {
|
||||
AUserInAServer userInServer = userInServerOptional.get();
|
||||
@@ -50,7 +49,7 @@ public class HasLevelCondition implements SystemCondition {
|
||||
log.info("Condition evaluated to {}", conditionResult);
|
||||
return conditionResult;
|
||||
}
|
||||
log.info("No user in server object was found. Evaluating to false.");
|
||||
log.info("No user in server object was found. Evaluating has level to false.");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class JoiningUserRoleListenerTest {
|
||||
when(model.getJoiningUser()).thenReturn(serverUser);
|
||||
when(model.getServerId()).thenReturn(SERVER_ID);
|
||||
when(aUserInAServer.getUserInServerId()).thenReturn(USER_IN_SERVER_ID);
|
||||
when(userInServerManagementService.loadOrCreateUser(SERVER_ID, USER_ID)).thenReturn(aUserInAServer);
|
||||
when(userInServerManagementService.loadUserOptional(SERVER_ID, USER_ID)).thenReturn(Optional.of(aUserInAServer));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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,9 +342,16 @@ 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 -> {
|
||||
log.error("Invite matching failed.", throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -333,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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ public class MessageEmbedListener implements MessageReceivedListener {
|
||||
log.debug("We found {} links to embed in message {} in channel {} in guild {}.", links.size(), message.getId(), message.getChannel().getId(), message.getGuild().getId());
|
||||
Long userEmbeddingUserInServerId = userInServerManagementService.loadOrCreateUser(message.getMember()).getUserInServerId();
|
||||
for (MessageEmbedLink messageEmbedLink : links) {
|
||||
// potentially support foreign linked servers
|
||||
if(!messageEmbedLink.getServerId().equals(message.getGuild().getIdLong())) {
|
||||
log.info("Link for message {} was from a foreign server {}. Do not embed.", messageEmbedLink.getMessageId(), messageEmbedLink.getServerId());
|
||||
continue;
|
||||
|
||||
@@ -168,6 +168,12 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
||||
.stream()
|
||||
.map(EmbeddedMessage::getEmbeddingMessageId)
|
||||
.collect(Collectors.toList());
|
||||
List<String> componentPayloadsToDelete = embeddedMessages
|
||||
.stream()
|
||||
.map(EmbeddedMessage::getDeletionComponentId)
|
||||
.filter(Objects::nonNull)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<CompletableFuture<Message>> reactionMessageFutures = messageService.retrieveMessages(reactionChannelMessages);
|
||||
List<CompletableFuture<Message>> buttonMessageFutures = messageService.retrieveMessages(buttonChannelMessages);
|
||||
CompletableFutureList<Message> reactionFutureList = new CompletableFutureList<>(reactionMessageFutures);
|
||||
@@ -193,7 +199,7 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
||||
if(throwable != null) {
|
||||
log.warn("Embedded message button clearing failed.", throwable);
|
||||
}
|
||||
self.deleteEmbeddedMessages(embeddedMessagesHandled);
|
||||
self.deleteEmbeddedMessages(embeddedMessagesHandled, componentPayloadsToDelete);
|
||||
})
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Failed to clean up embedded messages.", throwable);
|
||||
@@ -231,8 +237,9 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteEmbeddedMessages(List<Long> embeddedMessagesToDelete) {
|
||||
public void deleteEmbeddedMessages(List<Long> embeddedMessagesToDelete, List<String> componentPayloadsToDelete) {
|
||||
messageEmbedPostManagementService.deleteEmbeddedMessagesViaId(embeddedMessagesToDelete);
|
||||
componentPayloadManagementService.deletePayloads(componentPayloadsToDelete);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -309,6 +316,9 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
||||
.builder()
|
||||
.buttonId(deletionButtonEnabled ? componentServiceBean.generateComponentId() : null)
|
||||
.build();
|
||||
|
||||
Long referencedMessageId = message.getReferencedMessage() != null ? message.getReferencedMessage().getIdLong() : null;
|
||||
Boolean shouldMentionReferencedAuthor = shouldMentionReferencedAuthor(message);
|
||||
return MessageEmbeddedModel
|
||||
.builder()
|
||||
.member(message.getMember())
|
||||
@@ -319,7 +329,16 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
|
||||
.guild(message.getGuild())
|
||||
.useButton(deletionButtonEnabled)
|
||||
.embeddedMessage(embeddedMessage)
|
||||
.referencedMessageId(referencedMessageId)
|
||||
.mentionsReferencedMessage(shouldMentionReferencedAuthor)
|
||||
.buttonConfigModel(buttonConfigModel)
|
||||
.build();
|
||||
}
|
||||
|
||||
private Boolean shouldMentionReferencedAuthor(Message message) {
|
||||
if(message.getReferencedMessage() != null) {
|
||||
return message.getMentionedUsers().contains(message.getReferencedMessage().getAuthor());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -19,5 +19,7 @@ public class MessageEmbeddedModel extends UserInitiatedServerContext {
|
||||
private TextChannel sourceChannel;
|
||||
private Member embeddingUser;
|
||||
private ButtonConfigModel buttonConfigModel;
|
||||
private Long referencedMessageId;
|
||||
private Boolean mentionsReferencedMessage;
|
||||
private Boolean useButton;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
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;
|
||||
@@ -64,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;
|
||||
}
|
||||
|
||||
@@ -81,11 +85,15 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
.member(authorMember)
|
||||
.build();
|
||||
MessageToSend message = templateService.renderEmbedTemplate(MESSAGE_DELETED_TEMPLATE, logModel, messageFromCache.getServerId());
|
||||
postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId());
|
||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId()))
|
||||
.exceptionally(throwable -> {
|
||||
log.error("Failed to send message deleted log.", throwable);
|
||||
return null;
|
||||
});
|
||||
if(messageFromCache.getAttachments() != null){
|
||||
log.debug("Notifying about deletions of {} attachments.", messageFromCache.getAttachments().size());
|
||||
for (int i = 0; i < messageFromCache.getAttachments().size(); i++) {
|
||||
MessageDeletedAttachmentLog log = MessageDeletedAttachmentLog
|
||||
MessageDeletedAttachmentLog attachmentLogModel = MessageDeletedAttachmentLog
|
||||
.builder()
|
||||
.imageUrl(messageFromCache.getAttachments().get(i).getProxyUrl())
|
||||
.counter(i + 1)
|
||||
@@ -93,8 +101,12 @@ public class MessageDeleteLogListener implements AsyncMessageDeletedListener {
|
||||
.channel(textChannel)
|
||||
.member(authorMember)
|
||||
.build();
|
||||
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, log, messageFromCache.getServerId());
|
||||
postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId());
|
||||
MessageToSend attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, attachmentLogModel, messageFromCache.getServerId());
|
||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(attachmentEmbed, LoggingPostTarget.DELETE_LOG, messageFromCache.getServerId()))
|
||||
.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.6</version>
|
||||
<version>1.3.9</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.6</version>
|
||||
<version>1.3.9</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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)
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,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;
|
||||
@@ -35,6 +39,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
public class Warnings extends AbstractConditionableCommand {
|
||||
|
||||
public static final String WARNINGS_RESPONSE_TEMPLATE = "warnings_response";
|
||||
public static final String NO_WARNINGS_TEMPLATE_KEY = "warnings_no_warnings_found";
|
||||
@Autowired
|
||||
private WarnManagementService warnManagementService;
|
||||
|
||||
@@ -56,6 +61,12 @@ public class Warnings extends AbstractConditionableCommand {
|
||||
@Autowired
|
||||
private Warnings self;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Warning> warnsToDisplay;
|
||||
@@ -69,10 +80,17 @@ 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).thenApply(warnEntries -> {
|
||||
self.renderWarnings(commandContext, warnEntries);
|
||||
return CommandResult.fromSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -96,7 +114,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");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,12 +48,11 @@ public class WarnEntryConverter {
|
||||
allFutures.add(warnedMemberFuture);
|
||||
});
|
||||
CompletableFuture<List<WarnEntry>> future = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFutureGeneric(allFutures).whenComplete((unused, throwable) -> {
|
||||
try {
|
||||
future.complete(self.loadFullWarnEntries(loadedWarnings));
|
||||
} catch (Exception exception) {
|
||||
future.completeExceptionally(exception);
|
||||
}
|
||||
FutureUtils.toSingleFutureGeneric(allFutures)
|
||||
.whenComplete((unused, throwable) -> future.complete(self.loadFullWarnEntries(loadedWarnings)))
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.manager;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.moderation.listener.InfractionLevelChangedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.InfractionLevelChangedEventModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class InfractionLevelChangedListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<InfractionLevelChangedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("infractionLevelChangedExecutor")
|
||||
private TaskExecutor infractionLevelChangedExecutor;
|
||||
|
||||
public void sendInfractionLevelChangedEvent(Integer newLevel, Integer oldLevel, Long newPoints, Long oldPoints, ServerUser serverUser) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
InfractionLevelChangedEventModel model = createInfractionChangedModel(newLevel, oldLevel, oldPoints, newPoints, serverUser);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model, infractionLevelChangedExecutor));
|
||||
}
|
||||
|
||||
private InfractionLevelChangedEventModel createInfractionChangedModel(Integer newLevel, Integer oldLevel, Long oldPoints, Long newPoints, ServerUser serverUser) {
|
||||
return InfractionLevelChangedEventModel
|
||||
.builder()
|
||||
.newLevel(newLevel)
|
||||
.oldLevel(oldLevel)
|
||||
.oldPoints(oldPoints)
|
||||
.newPoints(newPoints)
|
||||
.userId(serverUser.getUserId())
|
||||
.serverId(serverUser.getServerId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package dev.sheldan.abstracto.moderation.listener.manager;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.moderation.listener.WarningCreatedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.WarningCreatedEventModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class WarningCreatedListenerManager {
|
||||
|
||||
@Autowired(required = false)
|
||||
private List<WarningCreatedListener> listeners;
|
||||
|
||||
@Autowired
|
||||
private ListenerService listenerService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("warningCreatedExecutor")
|
||||
private TaskExecutor warningCreatedExecutor;
|
||||
|
||||
public void sendWarningCreatedEvent(ServerSpecificId warnId, ServerUser warnedUser, ServerUser warningUser,
|
||||
String reason, ServerChannelMessage warnCommand) {
|
||||
if(listeners == null || listeners.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
WarningCreatedEventModel model = createWarningCreatedEventModel(warnId, warnedUser, warningUser, reason, warnCommand);
|
||||
listeners.forEach(listener -> listenerService.executeFeatureAwareListener(listener, model, warningCreatedExecutor));
|
||||
}
|
||||
|
||||
private WarningCreatedEventModel createWarningCreatedEventModel(ServerSpecificId warnId, ServerUser warnedUser,
|
||||
ServerUser warningUser, String reason, ServerChannelMessage warnCommandMessage) {
|
||||
return WarningCreatedEventModel
|
||||
.builder()
|
||||
.warningId(warnId.getId())
|
||||
.serverId(warnId.getServerId())
|
||||
.warningUserId(warningUser.getUserId())
|
||||
.warnedUserId(warnedUser.getUserId())
|
||||
.reason(reason)
|
||||
.warningChannelId(warnCommandMessage.getChannelId())
|
||||
.warningMessageId(warnCommandMessage.getMessageId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.abstracto.moderation.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface InfractionRepository extends JpaRepository<Infraction, Long> {
|
||||
List<Infraction> findByUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public interface WarnRepository extends JpaRepository<Warning, ServerSpecificId>
|
||||
Long countByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
Long countByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
List<Warning> findByWarnedUserAndDecayedFalse(AUserInAServer aUserInAServer);
|
||||
|
||||
List<Warning> findByWarnedUser(AUserInAServer aUserInAServer);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@@ -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))
|
||||
@@ -90,6 +90,9 @@ public class BanServiceBean implements BanService {
|
||||
returningFuture.completeExceptionally(throwable1);
|
||||
return null;
|
||||
});
|
||||
}).exceptionally(throwable -> {
|
||||
returningFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return returningFuture;
|
||||
}
|
||||
@@ -105,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()
|
||||
@@ -136,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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,9 @@ public class MuteServiceBean implements MuteService {
|
||||
channelService.sendTextToChannel(throwable.getMessage(), feedBackChannel).whenComplete((exceptionMessage, innerThrowable) -> {
|
||||
notificationFuture.complete(null);
|
||||
log.info("Successfully notified user {} in server {} about mute.", memberBeingMuted.getId(), memberBeingMuted.getGuild().getId());
|
||||
}).exceptionally(throwable1 -> {
|
||||
notificationFuture.completeExceptionally(throwable1);
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
});
|
||||
@@ -241,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
|
||||
@@ -310,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;
|
||||
|
||||
@@ -155,14 +155,18 @@ public class PurgeServiceBean implements PurgeService {
|
||||
return aVoid -> {
|
||||
if (amountToDelete >= 1) {
|
||||
log.debug("Still more than 1 message to delete. Continuing.");
|
||||
purgeMessages(amountToDelete, channel, earliestMessage.getIdLong(), purgedMember, totalCount, currentCount, currentStatusMessageId).whenComplete((avoid, throwable) -> {
|
||||
purgeMessages(amountToDelete, channel, earliestMessage.getIdLong(), purgedMember, totalCount, currentCount, currentStatusMessageId)
|
||||
.whenComplete((avoid, throwable) -> {
|
||||
if (throwable != null) {
|
||||
deletionFuture.completeExceptionally(throwable);
|
||||
} else {
|
||||
deletionFuture.complete(null);
|
||||
}
|
||||
}
|
||||
);
|
||||
).exceptionally(throwable -> {
|
||||
deletionFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
log.debug("Completed purging of {} messages.", totalCount);
|
||||
// Todo Move to message service
|
||||
|
||||
@@ -100,9 +100,13 @@ public class ReactionReportServiceBean implements ReactionReportService {
|
||||
|
||||
@Transactional
|
||||
public void createReactionReportInDb(CachedMessage cachedMessage, Message reportMessage, ServerUser reporter) {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
if(reportMessage == null) {
|
||||
log.info("Creation reaction report about message {} was not sent - post target might be disabled in server {}.", cachedMessage.getMessageId(), cachedMessage.getServerId());
|
||||
} else {
|
||||
log.info("Creation reaction report in message {} about message {} in database.", reportMessage.getIdLong(), cachedMessage.getMessageId());
|
||||
reactionReportManagementService.createReactionReport(cachedMessage, reportMessage);
|
||||
updateModerationUserReportCooldown(reporter);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.sheldan.abstracto.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.FutureMemberPair;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
@@ -12,16 +13,20 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningDecayFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.WarningFeatureConfig;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarnDecayMode;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.mode.WarningMode;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarnDecayPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.config.posttarget.WarningPostTarget;
|
||||
import dev.sheldan.abstracto.moderation.listener.manager.WarningCreatedListenerManager;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Warning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnContext;
|
||||
import dev.sheldan.abstracto.moderation.model.template.command.WarnNotification;
|
||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayLogModel;
|
||||
import dev.sheldan.abstracto.moderation.model.template.job.WarnDecayWarning;
|
||||
import dev.sheldan.abstracto.moderation.model.template.listener.WarnDecayMemberNotificationModel;
|
||||
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
|
||||
import dev.sheldan.abstracto.moderation.service.management.WarnManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
@@ -85,6 +90,18 @@ public class WarnServiceBean implements WarnService {
|
||||
@Autowired
|
||||
private WarnServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private InfractionService infractionService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private InfractionManagementService infractionManagementService;
|
||||
|
||||
@Autowired
|
||||
private WarningCreatedListenerManager warningCreatedListenerManager;
|
||||
|
||||
public static final String WARN_LOG_TEMPLATE = "warn_log";
|
||||
public static final String WARN_NOTIFICATION_TEMPLATE = "warn_notification";
|
||||
public static final String WARNINGS_COUNTER_KEY = "WARNINGS";
|
||||
@@ -100,22 +117,34 @@ public class WarnServiceBean implements WarnService {
|
||||
Member warningMember = context.getMember();
|
||||
Guild guild = warnedMember.getGuild();
|
||||
log.info("User {} is warning {} in server {}", warnedMember.getId(), warningMember.getId(), guild.getIdLong());
|
||||
WarnNotification warnNotification = WarnNotification.builder().reason(context.getReason()).warnId(warningId).serverName(guild.getName()).build();
|
||||
WarnNotification warnNotification = WarnNotification
|
||||
.builder()
|
||||
.reason(context.getReason())
|
||||
.warnId(warningId)
|
||||
.serverName(guild.getName())
|
||||
.build();
|
||||
Long serverId = server.getId();
|
||||
String warnNotificationMessage = templateService.renderTemplate(WARN_NOTIFICATION_TEMPLATE, warnNotification, server.getId());
|
||||
List<CompletableFuture<Message>> futures = new ArrayList<>();
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
futures.add(messageService.sendMessageToUser(warnedMember.getUser(), warnNotificationMessage));
|
||||
log.debug("Logging warning for server {}.", server.getId());
|
||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, serverId)) {
|
||||
Long infractionPoints = configService.getLongValueOrConfigDefault(WarningFeatureConfig.WARN_INFRACTION_POINTS, serverId);
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(warnedMember);
|
||||
warnedUser.setServerReference(server);
|
||||
futures.add(infractionService.createInfractionWithNotification(warnedUser, infractionPoints)
|
||||
.thenAccept(infraction -> context.setInfractionId(infraction.getId())));
|
||||
}
|
||||
MessageToSend message = templateService.renderEmbedTemplate(WARN_LOG_TEMPLATE, context, server.getId());
|
||||
futures.addAll(postTargetService.sendEmbedInPostTarget(message, WarningPostTarget.WARN_LOG, context.getGuild().getIdLong()));
|
||||
|
||||
return FutureUtils.toSingleFutureGeneric(futures);
|
||||
return FutureUtils.toSingleFuture(futures);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> warnUserWithLog(WarnContext context) {
|
||||
return notifyAndLogFullUserWarning(context).thenAccept(aVoid ->
|
||||
self.persistWarning(context)
|
||||
);
|
||||
return notifyAndLogFullUserWarning(context)
|
||||
.thenAccept(aVoid -> self.persistWarning(context));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -124,8 +153,15 @@ public class WarnServiceBean implements WarnService {
|
||||
context.getWarnId(), context.getGuild().getId(), context.getWarnedMember().getId(), context.getMember().getId());
|
||||
AUserInAServer warnedUser = userInServerManagementService.loadOrCreateUser(context.getWarnedMember());
|
||||
AUserInAServer warningUser = userInServerManagementService.loadOrCreateUser(context.getMember());
|
||||
warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
|
||||
Warning createdWarning = warnManagementService.createWarning(warnedUser, warningUser, context.getReason(), context.getWarnId());
|
||||
if(context.getInfractionId() != null) {
|
||||
Infraction infraction = infractionManagementService.loadInfraction(context.getInfractionId());
|
||||
createdWarning.setInfraction(infraction);
|
||||
}
|
||||
ServerUser warnedServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerUser warningServerUser = ServerUser.fromAUserInAServer(warnedUser);
|
||||
ServerChannelMessage commandMessage = ServerChannelMessage.fromMessage(context.getMessage());
|
||||
warningCreatedListenerManager.sendWarningCreatedEvent(createdWarning.getWarnId(), warnedServerUser, warningServerUser, context.getReason(), commandMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -188,16 +224,20 @@ public class WarnServiceBean implements WarnService {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WARN_DECAY_NOTIFICATION_TEMPLATE_KEY, model, serverId);
|
||||
log.info("Notifying user {} in server {} about decayed warning {}.", userId, serverId, warningId);
|
||||
notificationFutures.add(messageService.sendMessageToSendToUser(memberToSendTo.getUser(), messageToSend).exceptionally(throwable -> {
|
||||
log.error("Failed to send warn decay message to user {} in server {} to notify about decay warning {}.", userId, server, warningId);
|
||||
log.error("Failed to send warn decay message to user {} in server {} to notify about decay warning {}.", userId, server.getId(), warningId, throwable);
|
||||
return null;
|
||||
}));
|
||||
} else {
|
||||
log.warn("Could not find user {} in server {}. Not notifying about decayed warning {}.", userId, serverId, warningId);
|
||||
}
|
||||
});
|
||||
CompletableFuture<Void> future = new CompletableFuture();
|
||||
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFutureGeneric(notificationFutures)
|
||||
.whenComplete((unused, throwable) -> future.complete(null));
|
||||
.whenComplete((unused, throwable) -> future.complete(null))
|
||||
.exceptionally(throwable -> {
|
||||
future.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@@ -231,10 +271,13 @@ public class WarnServiceBean implements WarnService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decayWarning(Warning warning, Instant now) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), now);
|
||||
warning.setDecayDate(now);
|
||||
public void decayWarning(Warning warning, Instant decayDate) {
|
||||
log.debug("Decaying warning {} in server {} with date {}.", warning.getWarnId().getId(), warning.getWarnId().getServerId(), decayDate);
|
||||
warning.setDecayDate(decayDate);
|
||||
warning.setDecayed(true);
|
||||
if(warning.getInfraction() != null) {
|
||||
infractionService.decayInfraction(warning.getInfraction());
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> logDecayedWarnings(AServer server, List<Warning> warningsToDecay) {
|
||||
@@ -265,6 +308,9 @@ public class WarnServiceBean implements WarnService {
|
||||
return null;
|
||||
});
|
||||
return null;
|
||||
}).exceptionally(throwable -> {
|
||||
sendingFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
return sendingFuture;
|
||||
@@ -300,8 +346,7 @@ public class WarnServiceBean implements WarnService {
|
||||
.warnings(warnDecayWarnings)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WARN_DECAY_LOG_TEMPLATE_KEY, warnDecayLogModel, serverId);
|
||||
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId());
|
||||
return FutureUtils.toSingleFutureGeneric(messageFutures);
|
||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, WarnDecayPostTarget.DECAY_LOG, server.getId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.sheldan.abstracto.moderation.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||
import dev.sheldan.abstracto.moderation.repository.InfractionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class InfractionManagementServiceBean implements InfractionManagementService{
|
||||
|
||||
@Autowired
|
||||
private InfractionRepository infractionRepository;
|
||||
|
||||
@Override
|
||||
public Infraction createInfraction(AUserInAServer aUserInAServer, Long points) {
|
||||
Infraction infraction = Infraction
|
||||
.builder()
|
||||
.user(aUserInAServer)
|
||||
.server(aUserInAServer.getServerReference())
|
||||
.points(points)
|
||||
.build();
|
||||
return infractionRepository.save(infraction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Infraction> getActiveInfractionsForUser(AUserInAServer aUserInAServer) {
|
||||
return infractionRepository.findByUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Infraction loadInfraction(Long infraction) {
|
||||
return infractionRepository.getOne(infraction);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -70,10 +70,15 @@ public class WarnManagementServiceBean implements WarnManagementService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
public Long getActiveWarnCountForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.countByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Warning> getActiveWarnsForUser(AUserInAServer aUserInAServer) {
|
||||
return warnRepository.findByWarnedUserAndDecayedFalse(aUserInAServer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Warning> findByIdOptional(Long id, Long serverId) {
|
||||
return warnRepository.findByWarnId_IdAndWarnId_ServerId(id, serverId);
|
||||
|
||||
@@ -0,0 +1,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,5 @@
|
||||
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.16/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.4/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -7,6 +7,9 @@ abstracto.systemConfigs.reactionReportCooldownSeconds.longValue=300
|
||||
abstracto.featureFlags.moderation.featureName=moderation
|
||||
abstracto.featureFlags.moderation.enabled=false
|
||||
|
||||
abstracto.featureFlags.infractions.featureName=infractions
|
||||
abstracto.featureFlags.infractions.enabled=false
|
||||
|
||||
abstracto.featureFlags.reportReactions.featureName=reportReactions
|
||||
abstracto.featureFlags.reportReactions.enabled=false
|
||||
|
||||
@@ -42,6 +45,31 @@ abstracto.featureModes.warnDecayLogging.featureName=warnings
|
||||
abstracto.featureModes.warnDecayLogging.mode=warnDecayLogging
|
||||
abstracto.featureModes.warnDecayLogging.enabled=true
|
||||
|
||||
abstracto.featureModes.infractionReporting.featureName=infractions
|
||||
abstracto.featureModes.infractionReporting.mode=infractionReporting
|
||||
abstracto.featureModes.infractionReporting.enabled=true
|
||||
|
||||
abstracto.systemConfigs.infractionLvl1.name=infractionLvl1
|
||||
abstracto.systemConfigs.infractionLvl1.longValue=10
|
||||
|
||||
abstracto.systemConfigs.infractionLvl2.name=infractionLvl2
|
||||
abstracto.systemConfigs.infractionLvl2.longValue=20
|
||||
|
||||
abstracto.systemConfigs.infractionLvl3.name=infractionLvl3
|
||||
abstracto.systemConfigs.infractionLvl3.longValue=30
|
||||
|
||||
abstracto.systemConfigs.infractionLvl4.name=infractionLvl4
|
||||
abstracto.systemConfigs.infractionLvl4.longValue=40
|
||||
|
||||
abstracto.systemConfigs.infractionLvl5.name=infractionLvl5
|
||||
abstracto.systemConfigs.infractionLvl5.longValue=50
|
||||
|
||||
abstracto.systemConfigs.infractionLevels.name=infractionLevels
|
||||
abstracto.systemConfigs.infractionLevels.longValue=5
|
||||
|
||||
abstracto.systemConfigs.warnInfractionPoints.name=warnInfractionPoints
|
||||
abstracto.systemConfigs.warnInfractionPoints.longValue=0
|
||||
|
||||
abstracto.featureModes.automaticWarnDecayLogging.featureName=warnDecay
|
||||
abstracto.featureModes.automaticWarnDecayLogging.mode=automaticWarnDecayLogging
|
||||
abstracto.featureModes.automaticWarnDecayLogging.enabled=true
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
@@ -134,6 +135,9 @@ public class WarnServiceBeanTest {
|
||||
@Mock
|
||||
private DefaultConfigManagementService defaultConfigManagementService;
|
||||
|
||||
@Mock
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
private static final String NOTIFICATION_TEXT = "text";
|
||||
private static final String GUILD_NAME = "guild";
|
||||
private static final Long SERVER_ID = 4L;
|
||||
@@ -204,6 +208,7 @@ public class WarnServiceBeanTest {
|
||||
public void testWarnFullUser() {
|
||||
setupWarnContext();
|
||||
setupMocksForWarning();
|
||||
when(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, SERVER_ID)).thenReturn(false);
|
||||
CompletableFuture<Void> future = testUnit.notifyAndLogFullUserWarning(context);
|
||||
future.join();
|
||||
Assert.assertFalse(future.isCompletedExceptionally());
|
||||
|
||||
@@ -97,7 +97,7 @@ public class WarnManagementServiceBeanTest {
|
||||
public void testActiveWarnCountOfUser() {
|
||||
Long count = 5L;
|
||||
when(warnRepository.countByWarnedUserAndDecayedFalse(warnedUser)).thenReturn(count);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnsForUser(warnedUser);
|
||||
Long activeWarnsForUserCount = testUnit.getActiveWarnCountForUser(warnedUser);
|
||||
Assert.assertEquals(count, activeWarnsForUserCount);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.3.6</version>
|
||||
<version>1.3.9</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> {
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package dev.sheldan.abstracto.moderation.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name="infraction")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class Infraction {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id")
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "infraction_user_in_server_id", nullable = false)
|
||||
private AUserInAServer user;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@Column(name = "points")
|
||||
private Long points;
|
||||
|
||||
@Column(name = "decayed")
|
||||
private Boolean decayed;
|
||||
|
||||
@Column(name = "decayed_date")
|
||||
private Instant decayedDate;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public class Warning implements Serializable {
|
||||
@Setter
|
||||
private ServerSpecificId warnId;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@MapsId("serverId")
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
@@ -90,4 +90,10 @@ public class Warning implements Serializable {
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "infraction_id")
|
||||
private Infraction infraction;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.moderation.model.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class InfractionLevelChangedEventModel implements FeatureAwareListenerModel {
|
||||
private Integer oldLevel;
|
||||
private Long oldPoints;
|
||||
private Integer newLevel;
|
||||
private Long newPoints;
|
||||
private Long userId;
|
||||
private Long serverId;
|
||||
|
||||
@Override
|
||||
public Long getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.abstracto.moderation.model.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class WarningCreatedEventModel implements FeatureAwareListenerModel {
|
||||
private Long warningId;
|
||||
private Long warnedUserId;
|
||||
private Long serverId;
|
||||
private Long warningUserId;
|
||||
private Long warningChannelId;
|
||||
private Long warningMessageId;
|
||||
private String reason;
|
||||
|
||||
@Override
|
||||
public Long getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.moderation.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class InfractionLevelChangeModel {
|
||||
private Long newPoints;
|
||||
private Long oldPoints;
|
||||
private Integer newLevel;
|
||||
private Integer oldLevel;
|
||||
private MemberDisplay member;
|
||||
}
|
||||
@@ -28,4 +28,5 @@ public class BanLog {
|
||||
*/
|
||||
private User bannedUser;
|
||||
private Message commandMessage;
|
||||
private Integer deletionDays;
|
||||
}
|
||||
|
||||
@@ -26,4 +26,5 @@ public class WarnContext extends SlimUserInitiatedServerContext {
|
||||
* The persisted {@link Warning} object from the database containing the information about the warning
|
||||
*/
|
||||
private Long warnId;
|
||||
private Long infractionId;
|
||||
}
|
||||
|
||||
@@ -10,9 +10,9 @@ import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public interface BanService {
|
||||
String BAN_EFFECT_KEY = "ban";
|
||||
CompletableFuture<Void> banMember(Member member, String reason, Member banningMember, Message message);
|
||||
CompletableFuture<Void> banUser(User user, String reason, Member banningMember, Message message);
|
||||
CompletableFuture<Void> unBanUser(User user, Member unBanningUser);
|
||||
CompletableFuture<Void> banMemberWithNotification(Member member, String reason, Member banningMember, Integer deletionDays, Message message);
|
||||
CompletableFuture<Void> banUserWithNotification(User user, String reason, Member banningMember, Integer deletionDays, Message message);
|
||||
CompletableFuture<Void> unBanUserWithNotification(User user, Member unBanningUser);
|
||||
CompletableFuture<Void> banUser(Guild guild, User user, Integer deletionDays, String reason);
|
||||
CompletableFuture<Void> unbanUser(Guild guild, User user);
|
||||
CompletableFuture<Void> softBanUser(Guild guild, User user, Duration delDays);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user