mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-25 14:53:26 +00:00
[AB-xxx] reworking mute logging to use audit log events instead of active logging and member update events
This commit is contained in:
@@ -1,139 +0,0 @@
|
|||||||
package dev.sheldan.abstracto.moderation.listener;
|
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
|
||||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
|
||||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMemberTimeoutUpdatedListener;
|
|
||||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
|
||||||
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
|
|
||||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
|
||||||
import dev.sheldan.abstracto.core.service.MemberService;
|
|
||||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
|
||||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
|
||||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
|
||||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
|
||||||
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget;
|
|
||||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel;
|
|
||||||
import dev.sheldan.abstracto.moderation.service.MuteServiceBean;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import net.dv8tion.jda.api.audit.ActionType;
|
|
||||||
import net.dv8tion.jda.api.audit.AuditLogEntry;
|
|
||||||
import net.dv8tion.jda.api.audit.AuditLogKey;
|
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
|
||||||
import net.dv8tion.jda.api.entities.User;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
@Slf4j
|
|
||||||
public class MemberTimeoutListener implements AsyncMemberTimeoutUpdatedListener {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private TemplateService templateService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private PostTargetService postTargetService;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MemberTimeoutListener self;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MemberService memberService;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DefaultListenerResult execute(MemberTimeoutUpdatedModel model) {
|
|
||||||
Guild guild = model.getGuild();
|
|
||||||
guild.retrieveAuditLogs()
|
|
||||||
.type(ActionType.MEMBER_UPDATE)
|
|
||||||
.limit(10)
|
|
||||||
.queue(auditLogEntries -> {
|
|
||||||
CompletableFuture<Void> notificationFuture = null;
|
|
||||||
if(auditLogEntries.isEmpty()) {
|
|
||||||
log.info("Did not find recent timeouts in guild {}.", model.getServerId());
|
|
||||||
notificationFuture = self.sendMutingUpdateNotification(model, null);
|
|
||||||
} else {
|
|
||||||
Optional<AuditLogEntry> timeoutEntryOptional = auditLogEntries
|
|
||||||
.stream()
|
|
||||||
.filter(auditLogEntry -> auditLogEntry.getChangeByKey(AuditLogKey.MEMBER_TIME_OUT) != null
|
|
||||||
&& auditLogEntry.getTargetIdLong() == model.getTimeoutUser().getUserId())
|
|
||||||
.findFirst();
|
|
||||||
if(timeoutEntryOptional.isPresent()) {
|
|
||||||
AuditLogEntry auditLogEntry = timeoutEntryOptional.get();
|
|
||||||
User responsibleUser = auditLogEntry.getUser();
|
|
||||||
if(guild.getSelfMember().getIdLong() != responsibleUser.getIdLong()) {
|
|
||||||
notificationFuture = self.sendMutingUpdateNotification(model, auditLogEntry);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
notificationFuture = self.sendMutingUpdateNotification(model, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(notificationFuture != null) {
|
|
||||||
notificationFuture.thenAccept(unused -> {
|
|
||||||
log.info("Sent notification about timeout change {} -> {} of user {} in server {}.",
|
|
||||||
model.getOldTimeout(), model.getNewTimeout(), model.getTimeoutUser().getUserId(), model.getServerId());
|
|
||||||
}).exceptionally(throwable -> {
|
|
||||||
log.info("Sent notification about timeout change {} -> {} of user {} in server {}.",
|
|
||||||
model.getOldTimeout(), model.getNewTimeout(), model.getTimeoutUser().getUserId(), model.getServerId());
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return DefaultListenerResult.PROCESSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public CompletableFuture<Void> sendMutingUpdateNotification(MemberTimeoutUpdatedModel model, AuditLogEntry logEntry) {
|
|
||||||
User responsibleUser;
|
|
||||||
Guild guild = model.getGuild();
|
|
||||||
CompletableFuture<Member> future;
|
|
||||||
String reason;
|
|
||||||
if(logEntry != null) {
|
|
||||||
responsibleUser = logEntry.getUser();
|
|
||||||
if(responsibleUser != null) {
|
|
||||||
ServerUser responsibleServerUser = ServerUser
|
|
||||||
.builder()
|
|
||||||
.serverId(guild.getIdLong())
|
|
||||||
.isBot(responsibleUser.isBot())
|
|
||||||
.userId(responsibleUser.getIdLong())
|
|
||||||
.build();
|
|
||||||
future = memberService.retrieveMemberInServer(responsibleServerUser);
|
|
||||||
} else {
|
|
||||||
future = CompletableFuture.completedFuture(null);
|
|
||||||
}
|
|
||||||
reason = logEntry.getReason();
|
|
||||||
} else {
|
|
||||||
future = CompletableFuture.completedFuture(null);
|
|
||||||
reason = null;
|
|
||||||
}
|
|
||||||
CompletableFuture<Void> returningFuture = new CompletableFuture<>();
|
|
||||||
future.whenComplete((aVoid, throwable) -> {
|
|
||||||
try {
|
|
||||||
MuteListenerModel muteLogModel = MuteListenerModel
|
|
||||||
.builder()
|
|
||||||
.muteTargetDate(model.getNewTimeout() != null ? model.getNewTimeout().toInstant() : null)
|
|
||||||
.oldMuteTargetDate(model.getOldTimeout() != null ? model.getOldTimeout().toInstant() : null)
|
|
||||||
.mutingUser(future.isCompletedExceptionally() ? null : MemberDisplay.fromMember(future.join()))
|
|
||||||
.mutedUser(MemberDisplay.fromMember(model.getMember()))
|
|
||||||
.reason(reason)
|
|
||||||
.build();
|
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MuteServiceBean.MUTE_LOG_TEMPLATE, muteLogModel, guild.getIdLong());
|
|
||||||
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, model.getServerId()));
|
|
||||||
returningFuture.complete(null);
|
|
||||||
} catch (Exception exception) {
|
|
||||||
log.error("Failed to log timeout update event for user {} in guild {}.", model.getTimeoutUser().getUserId(), model.getServerId(), exception);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return returningFuture;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FeatureDefinition getFeature() {
|
|
||||||
return ModerationFeatureDefinition.MUTING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package dev.sheldan.abstracto.moderation.listener;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||||
|
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMemberTimeoutUpdatedListener;
|
||||||
|
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||||
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
|
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
|
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget;
|
||||||
|
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel;
|
||||||
|
import dev.sheldan.abstracto.moderation.service.MuteServiceBean;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class MemberTimeoutLoggerListener implements AsyncMemberTimeoutUpdatedListener {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PostTargetService postTargetService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DefaultListenerResult execute(MemberTimeoutUpdatedModel model) {
|
||||||
|
Guild guild = model.getGuild();
|
||||||
|
MemberDisplay memberDisplay = model.getMember() != null ? MemberDisplay.fromMember(model.getMember()) : MemberDisplay.fromServerUser(model.getTimeoutUser());
|
||||||
|
Duration duration = null;
|
||||||
|
if(model.getNewTimeout() != null) {
|
||||||
|
duration = Duration.between(Instant.now(), model.getNewTimeout());
|
||||||
|
}
|
||||||
|
MuteListenerModel muteLogModel = MuteListenerModel
|
||||||
|
.builder()
|
||||||
|
.muteTargetDate(model.getNewTimeout() != null ? model.getNewTimeout().toInstant() : null)
|
||||||
|
.oldMuteTargetDate(model.getOldTimeout() != null ? model.getOldTimeout().toInstant() : null)
|
||||||
|
.mutingUser(MemberDisplay.fromIds(model.getServerId(), model.getResponsibleUserId()))
|
||||||
|
.mutedUser(memberDisplay)
|
||||||
|
.duration(duration)
|
||||||
|
.reason(model.getReason())
|
||||||
|
.build();
|
||||||
|
MessageToSend message = templateService.renderEmbedTemplate(MuteServiceBean.MUTE_LOG_TEMPLATE, muteLogModel, guild.getIdLong());
|
||||||
|
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, model.getServerId()));
|
||||||
|
return DefaultListenerResult.PROCESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return ModerationFeatureDefinition.MUTING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,30 +6,23 @@ import dev.sheldan.abstracto.core.models.ServerUser;
|
|||||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
|
||||||
import dev.sheldan.abstracto.core.service.*;
|
import dev.sheldan.abstracto.core.service.*;
|
||||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
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.templating.service.TemplateService;
|
||||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
|
||||||
import dev.sheldan.abstracto.moderation.config.feature.MutingFeatureConfig;
|
import dev.sheldan.abstracto.moderation.config.feature.MutingFeatureConfig;
|
||||||
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget;
|
|
||||||
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
import dev.sheldan.abstracto.moderation.exception.NoMuteFoundException;
|
||||||
import dev.sheldan.abstracto.moderation.model.MuteResult;
|
import dev.sheldan.abstracto.moderation.model.MuteResult;
|
||||||
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
import dev.sheldan.abstracto.moderation.model.database.Infraction;
|
||||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
||||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel;
|
|
||||||
import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification;
|
import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification;
|
||||||
import dev.sheldan.abstracto.moderation.model.template.command.UnMuteLog;
|
|
||||||
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
import dev.sheldan.abstracto.moderation.service.management.MuteManagementService;
|
||||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Message;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@@ -175,14 +168,13 @@ public class MuteServiceBean implements MuteService {
|
|||||||
Long muteId = counterService.getNextCounterValue(server, MUTE_COUNTER_KEY);
|
Long muteId = counterService.getNextCounterValue(server, MUTE_COUNTER_KEY);
|
||||||
CompletableFuture<MuteResult> result = muteUserInServer(guild, userToMute, reason, duration);
|
CompletableFuture<MuteResult> result = muteUserInServer(guild, userToMute, reason, duration);
|
||||||
return result
|
return result
|
||||||
.thenCompose(unused -> self.sendMuteLog(userToMute, mutingUser, duration, reason))
|
.thenCompose(logMessage -> self.evaluateAndStoreInfraction(userToMute, mutingUser, reason, targetDate))
|
||||||
.thenCompose(logMessage -> self.evaluateAndStoreInfraction(userToMute, mutingUser, reason, targetDate, logMessage))
|
|
||||||
.thenAccept(infractionId -> self.persistMute(userToMute, mutingUser, targetDate, muteId, reason, infractionId, origin))
|
.thenAccept(infractionId -> self.persistMute(userToMute, mutingUser, targetDate, muteId, reason, infractionId, origin))
|
||||||
.thenApply(unused -> result.join());
|
.thenApply(unused -> result.join());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Long> evaluateAndStoreInfraction(ServerUser userToMute, ServerUser mutingUser, String reason, Instant targetDate, Message logMessage) {
|
public CompletableFuture<Long> evaluateAndStoreInfraction(ServerUser userToMute, ServerUser mutingUser, String reason, Instant targetDate) {
|
||||||
Long serverId = userToMute.getServerId();
|
Long serverId = userToMute.getServerId();
|
||||||
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, serverId)) {
|
if(featureFlagService.getFeatureFlagValue(ModerationFeatureDefinition.INFRACTIONS, serverId)) {
|
||||||
Long infractionPoints = configService.getLongValueOrConfigDefault(MutingFeatureConfig.MUTE_INFRACTION_POINTS, serverId);
|
Long infractionPoints = configService.getLongValueOrConfigDefault(MutingFeatureConfig.MUTE_INFRACTION_POINTS, serverId);
|
||||||
@@ -190,7 +182,7 @@ public class MuteServiceBean implements MuteService {
|
|||||||
AUserInAServer mutingUserInAServer = userInServerManagementService.loadOrCreateUser(mutingUser);
|
AUserInAServer mutingUserInAServer = userInServerManagementService.loadOrCreateUser(mutingUser);
|
||||||
Map<String, String> parameters = new HashMap<>();
|
Map<String, String> parameters = new HashMap<>();
|
||||||
parameters.put(INFRACTION_PARAMETER_DURATION_KEY, templateService.renderDuration(Duration.between(Instant.now(), targetDate), serverId));
|
parameters.put(INFRACTION_PARAMETER_DURATION_KEY, templateService.renderDuration(Duration.between(Instant.now(), targetDate), serverId));
|
||||||
return infractionService.createInfractionWithNotification(mutedUserInAServer, infractionPoints, MUTE_INFRACTION_TYPE, reason, mutingUserInAServer, parameters, logMessage)
|
return infractionService.createInfractionWithNotification(mutedUserInAServer, infractionPoints, MUTE_INFRACTION_TYPE, reason, mutingUserInAServer, parameters)
|
||||||
.thenApply(Infraction::getId);
|
.thenApply(Infraction::getId);
|
||||||
} else {
|
} else {
|
||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
@@ -204,48 +196,13 @@ public class MuteServiceBean implements MuteService {
|
|||||||
createMuteObject(userToMute, mutingUser, reason, targetDate, muteId, triggerKey, infractionId, origin);
|
createMuteObject(userToMute, mutingUser, reason, targetDate, muteId, triggerKey, infractionId, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public CompletableFuture<Message> sendMuteLog(ServerUser userBeingMuted, ServerUser mutingUser, Duration duration, String reason) {
|
|
||||||
Instant targetDate = Instant.now().plus(duration);
|
|
||||||
MuteListenerModel model = MuteListenerModel
|
|
||||||
.builder()
|
|
||||||
.mutedUser(MemberDisplay.fromServerUser(userBeingMuted))
|
|
||||||
.mutingUser(MemberDisplay.fromServerUser(mutingUser))
|
|
||||||
.oldMuteTargetDate(null)
|
|
||||||
.duration(duration)
|
|
||||||
.muteTargetDate(targetDate)
|
|
||||||
.reason(reason)
|
|
||||||
.build();
|
|
||||||
log.debug("Sending mute log to the mute post target.");
|
|
||||||
Long serverId = userBeingMuted.getServerId();
|
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, model, serverId);
|
|
||||||
List<CompletableFuture<Message>> futures = postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, serverId);
|
|
||||||
return FutureUtils.toSingleFutureGeneric(futures).thenApply(unused -> futures.get(0).join());
|
|
||||||
}
|
|
||||||
|
|
||||||
private CompletableFuture<Void> sendUnMuteLogMessage(UnMuteLog muteLogModel, AServer server) {
|
|
||||||
MuteListenerModel model = MuteListenerModel
|
|
||||||
.builder()
|
|
||||||
.mutedUser(muteLogModel.getUnMutedUser())
|
|
||||||
.mutingUser(muteLogModel.getMutingUser())
|
|
||||||
.oldMuteTargetDate(muteLogModel.getMute() != null ? muteLogModel.getMute().getMuteTargetDate() : null)
|
|
||||||
.muteTargetDate(null)
|
|
||||||
.build();
|
|
||||||
if(muteLogModel.getMute() != null) {
|
|
||||||
log.debug("Sending unMute log for mute {} to the mute posttarget in server {}", muteLogModel.getMute().getMuteId().getId(), server.getId());
|
|
||||||
}
|
|
||||||
MessageToSend message = templateService.renderEmbedTemplate(MUTE_LOG_TEMPLATE, model, server.getId());
|
|
||||||
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, server.getId()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> unMuteUser(ServerUser userToUnmute, ServerUser unMutingUser, Guild guild) {
|
public CompletableFuture<Void> unMuteUser(ServerUser userToUnmute, ServerUser unMutingUser, Guild guild) {
|
||||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(userToUnmute);
|
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(userToUnmute);
|
||||||
boolean muteActive = muteManagementService.hasActiveMute(aUserInAServer);
|
boolean muteActive = muteManagementService.hasActiveMute(aUserInAServer);
|
||||||
if(!muteActive) {
|
if(!muteActive) {
|
||||||
return memberService.removeTimeout(guild, userToUnmute, null)
|
return memberService.removeTimeout(guild, userToUnmute, null);
|
||||||
.thenCompose(unused -> self.sendUnmuteLog(null, guild, userToUnmute, unMutingUser));
|
|
||||||
} else {
|
} else {
|
||||||
Mute mute = muteManagementService.getAMuteOf(aUserInAServer);
|
Mute mute = muteManagementService.getAMuteOf(aUserInAServer);
|
||||||
return endMute(mute, guild);
|
return endMute(mute, guild);
|
||||||
@@ -261,32 +218,13 @@ public class MuteServiceBean implements MuteService {
|
|||||||
Long muteId = mute.getMuteId().getId();
|
Long muteId = mute.getMuteId().getId();
|
||||||
AServer mutingServer = mute.getServer();
|
AServer mutingServer = mute.getServer();
|
||||||
ServerUser mutedUser = ServerUser.fromAUserInAServer(mute.getMutedUser());
|
ServerUser mutedUser = ServerUser.fromAUserInAServer(mute.getMutedUser());
|
||||||
ServerUser mutingUser = ServerUser.fromAUserInAServer(mute.getMutingUser());
|
|
||||||
log.info("UnMuting {} in server {}", mute.getMutedUser().getUserReference().getId(), mutingServer.getId());
|
log.info("UnMuting {} in server {}", mute.getMutedUser().getUserReference().getId(), mutingServer.getId());
|
||||||
return memberService.removeTimeout(guild, mutedUser, null)
|
return memberService.removeTimeout(guild, mutedUser, null)
|
||||||
.thenCompose(unused -> self.sendUnmuteLog(muteId, guild, mutedUser, mutingUser));
|
.thenAccept(unused -> {
|
||||||
}
|
if(muteId != null) {
|
||||||
|
self.endMuteInDatabase(muteId, guild.getIdLong());
|
||||||
|
}
|
||||||
@Transactional
|
});
|
||||||
public CompletableFuture<Void> sendUnmuteLog(Long muteId, Guild guild, ServerUser unMutedMember, ServerUser mutingMember) {
|
|
||||||
Mute mute = null;
|
|
||||||
if(muteId != null) {
|
|
||||||
mute = muteManagementService.findMute(muteId, guild.getIdLong());
|
|
||||||
}
|
|
||||||
AServer mutingServer = serverManagementService.loadServer(guild.getIdLong());
|
|
||||||
UnMuteLog unMuteLog = UnMuteLog
|
|
||||||
.builder()
|
|
||||||
.mute(mute)
|
|
||||||
.mutingUser(MemberDisplay.fromServerUser(mutingMember))
|
|
||||||
.unMutedUser(MemberDisplay.fromServerUser(unMutedMember))
|
|
||||||
.build();
|
|
||||||
CompletableFuture<Void> notificationFuture = sendUnMuteLogMessage(unMuteLog, mutingServer);
|
|
||||||
return CompletableFuture.allOf(notificationFuture).thenAccept(aVoid -> {
|
|
||||||
if(muteId != null) {
|
|
||||||
self.endMuteInDatabase(muteId, guild.getIdLong());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
package dev.sheldan.abstracto.moderation.model.template.command;
|
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
|
||||||
import dev.sheldan.abstracto.core.utils.MessageUtils;
|
|
||||||
import dev.sheldan.abstracto.moderation.model.database.Mute;
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.Setter;
|
|
||||||
import lombok.experimental.SuperBuilder;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.Instant;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used when rendering the notification when a member was muted. The template is: "unmute_log_embed"
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@SuperBuilder
|
|
||||||
@Setter
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
public class UnMuteLog {
|
|
||||||
/**
|
|
||||||
* The un-muted Member, is null if the member left the server
|
|
||||||
*/
|
|
||||||
private MemberDisplay unMutedUser;
|
|
||||||
/**
|
|
||||||
* The user casting the mute, is null if the member left the server
|
|
||||||
*/
|
|
||||||
private MemberDisplay mutingUser;
|
|
||||||
/**
|
|
||||||
* The persisted mute object from the database containing the information about the mute
|
|
||||||
*/
|
|
||||||
private Mute mute;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The actual duration between the date the mute started and the current time
|
|
||||||
* @return The difference between mute start and now
|
|
||||||
*/
|
|
||||||
public Duration getMuteDuration() {
|
|
||||||
return Duration.between(mute.getMuteDate(), Instant.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The duration between the date the mute started and the un-mute planned
|
|
||||||
* @return The difference between mute start and the target date
|
|
||||||
*/
|
|
||||||
public Duration getPlannedMuteDuration() {
|
|
||||||
return Duration.between(mute.getMuteDate(), mute.getMuteTargetDate());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The un-mute date, which is now, because this is the un-mute log message.
|
|
||||||
* @return The current time stamp
|
|
||||||
*/
|
|
||||||
public Instant getUnmuteDate() {
|
|
||||||
return Instant.now();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the link to the original message triggering the mute
|
|
||||||
* @return A string containing an URL leading to the message where the mute was triggered
|
|
||||||
*/
|
|
||||||
public String getMessageUrl() {
|
|
||||||
if(this.mute.getMessageId() != null && this.mute.getMutingChannel() != null) {
|
|
||||||
return MessageUtils.buildMessageUrl(this.mute.getServer().getId(), this.mute.getMutingChannel().getId(), this.mute.getMessageId());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,8 +3,13 @@ package dev.sheldan.abstracto.core.listener.async.jda;
|
|||||||
import dev.sheldan.abstracto.core.listener.ListenerService;
|
import dev.sheldan.abstracto.core.listener.ListenerService;
|
||||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||||
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
|
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
|
||||||
|
import dev.sheldan.abstracto.core.service.MemberService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateTimeOutEvent;
|
import net.dv8tion.jda.api.audit.ActionType;
|
||||||
|
import net.dv8tion.jda.api.audit.AuditLogChange;
|
||||||
|
import net.dv8tion.jda.api.audit.AuditLogKey;
|
||||||
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
|
import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent;
|
||||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
@@ -12,7 +17,10 @@ import org.springframework.core.task.TaskExecutor;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@@ -27,23 +35,46 @@ public class AsyncMemberTimeoutListenerBean extends ListenerAdapter {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ListenerService listenerService;
|
private ListenerService listenerService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberService memberService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGuildMemberUpdateTimeOut(@Nonnull GuildMemberUpdateTimeOutEvent event) {
|
public void onGuildAuditLogEntryCreate(@Nonnull GuildAuditLogEntryCreateEvent event) {
|
||||||
if(listenerList == null) return;
|
if(listenerList == null) return;
|
||||||
MemberTimeoutUpdatedModel model = getModel(event);
|
if(event.getEntry().getType().equals(ActionType.MEMBER_UPDATE)) {
|
||||||
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberTimeoutExecutor));
|
AuditLogChange memberTimeoutChange = event.getEntry().getChangeByKey(AuditLogKey.MEMBER_TIME_OUT);
|
||||||
|
if(memberTimeoutChange != null) {
|
||||||
|
CompletableFuture<Member> memberInstanceFuture = memberService.retrieveMemberInServer(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getTargetIdLong()));
|
||||||
|
memberInstanceFuture.whenComplete((member, throwable) -> {
|
||||||
|
executeListeners(memberTimeoutChange, event, member);
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
Long memberId = event.getEntry().getTargetIdLong();
|
||||||
|
Long serverId = event.getGuild().getIdLong();
|
||||||
|
log.warn("Failed to load member {} for member update audit log in server {}.", memberId, serverId, throwable);
|
||||||
|
executeListeners(memberTimeoutChange, event, null);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MemberTimeoutUpdatedModel getModel(GuildMemberUpdateTimeOutEvent event) {
|
private void executeListeners(AuditLogChange change, GuildAuditLogEntryCreateEvent event, Member member) {
|
||||||
return MemberTimeoutUpdatedModel
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
|
||||||
.builder()
|
OffsetDateTime timeoutAfter = change.getNewValue() != null ? OffsetDateTime.parse(change.getNewValue(), timeFormatter) : null;
|
||||||
.oldTimeout(event.getOldTimeOutEnd())
|
OffsetDateTime timeoutBefore = change.getOldValue() != null ? OffsetDateTime.parse(change.getOldValue(), timeFormatter) : null;
|
||||||
.newTimeout(event.getNewTimeOutEnd())
|
String reason = event.getEntry().getReason();
|
||||||
.member(event.getMember())
|
MemberTimeoutUpdatedModel model = MemberTimeoutUpdatedModel
|
||||||
.event(event)
|
.builder()
|
||||||
.timeoutUser(ServerUser.fromMember(event.getMember()))
|
.oldTimeout(timeoutBefore)
|
||||||
.guild(event.getGuild())
|
.newTimeout(timeoutAfter)
|
||||||
.user(event.getUser())
|
.responsibleUserId(event.getEntry().getUserIdLong())
|
||||||
.build();
|
.member(member)
|
||||||
}
|
.reason(reason)
|
||||||
|
.guild(event.getGuild())
|
||||||
|
.user(member != null ? member.getUser() : null)
|
||||||
|
.timeoutUser(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getTargetIdLong()))
|
||||||
|
.build();
|
||||||
|
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberTimeoutExecutor));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import lombok.Setter;
|
|||||||
import net.dv8tion.jda.api.entities.Guild;
|
import net.dv8tion.jda.api.entities.Guild;
|
||||||
import net.dv8tion.jda.api.entities.Member;
|
import net.dv8tion.jda.api.entities.Member;
|
||||||
import net.dv8tion.jda.api.entities.User;
|
import net.dv8tion.jda.api.entities.User;
|
||||||
import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdateTimeOutEvent;
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime;
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
@@ -19,10 +18,11 @@ public class MemberTimeoutUpdatedModel implements FeatureAwareListenerModel {
|
|||||||
private ServerUser timeoutUser;
|
private ServerUser timeoutUser;
|
||||||
private User user;
|
private User user;
|
||||||
private Guild guild;
|
private Guild guild;
|
||||||
|
private String reason;
|
||||||
|
private Long responsibleUserId;
|
||||||
private OffsetDateTime oldTimeout;
|
private OffsetDateTime oldTimeout;
|
||||||
private OffsetDateTime newTimeout;
|
private OffsetDateTime newTimeout;
|
||||||
private Member member;
|
private Member member;
|
||||||
private GuildMemberUpdateTimeOutEvent event;
|
|
||||||
@Override
|
@Override
|
||||||
public Long getServerId() {
|
public Long getServerId() {
|
||||||
return guild.getIdLong();
|
return guild.getIdLong();
|
||||||
|
|||||||
Reference in New Issue
Block a user