[AB-xxx] refactoring handling of bans and mutes: commands actively log, the reason for this is that the command is the only place who actually knows how executed the command. the event itself only sees the bot performing the action

adding event based logging of kicks
This commit is contained in:
Sheldan
2024-05-06 00:07:24 +02:00
parent 234aae3783
commit a01a5055a0
32 changed files with 440 additions and 136 deletions

View File

@@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.time.Duration; import java.time.Duration;
import java.time.Instant;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -73,11 +74,15 @@ public class Mute extends AbstractConditionableCommand {
Duration duration = (Duration) parameters.get(1); Duration duration = (Duration) parameters.get(1);
String defaultReason = templateService.renderSimpleTemplate(MUTE_DEFAULT_REASON_TEMPLATE, guild.getIdLong()); String defaultReason = templateService.renderSimpleTemplate(MUTE_DEFAULT_REASON_TEMPLATE, guild.getIdLong());
String reason = parameters.size() == 3 ? (String) parameters.get(2) : defaultReason; String reason = parameters.size() == 3 ? (String) parameters.get(2) : defaultReason;
Instant oldTimeoutDate = null;
if(member.getTimeOutEnd() != null && member.isTimedOut()) {
oldTimeoutDate = member.getTimeOutEnd().toInstant();
}
ServerUser userToMute = ServerUser.fromMember(member); ServerUser userToMute = ServerUser.fromMember(member);
ServerUser mutingUser = ServerUser.fromMember(commandContext.getAuthor()); ServerUser mutingUser = ServerUser.fromMember(commandContext.getAuthor());
Long serverId = commandContext.getGuild().getIdLong(); Long serverId = commandContext.getGuild().getIdLong();
ServerChannelMessage serverChannelMessage = ServerChannelMessage.fromMessage(commandContext.getMessage()); ServerChannelMessage serverChannelMessage = ServerChannelMessage.fromMessage(commandContext.getMessage());
return muteService.muteMemberWithLog(userToMute, mutingUser, reason, duration, commandContext.getGuild(), serverChannelMessage) return muteService.muteMemberWithLog(userToMute, mutingUser, reason, duration, commandContext.getGuild(), serverChannelMessage, oldTimeoutDate)
.thenCompose(muteResult -> { .thenCompose(muteResult -> {
if(muteResult == NOTIFICATION_FAILED) { if(muteResult == NOTIFICATION_FAILED) {
MessageToSend errorNotification = templateService.renderEmbedTemplate(MUTE_NOTIFICATION_NOT_POSSIBLE_TEMPLATE_KEY, new Object(), serverId); MessageToSend errorNotification = templateService.renderEmbedTemplate(MUTE_NOTIFICATION_NOT_POSSIBLE_TEMPLATE_KEY, new Object(), serverId);

View File

@@ -50,7 +50,7 @@ public class UnBan extends AbstractConditionableCommand {
String userIdStr = (String) parameters.get(0); String userIdStr = (String) parameters.get(0);
Long userId = Long.parseLong(userIdStr); Long userId = Long.parseLong(userIdStr);
return userService.retrieveUserForId(userId) return userService.retrieveUserForId(userId)
.thenCompose(user -> banService.unbanUser(commandContext.getGuild(), userId)) .thenCompose(user -> banService.unbanUser(commandContext.getGuild(), user, commandContext.getAuthor()))
.thenApply(aVoid -> CommandResult.fromSuccess()); .thenApply(aVoid -> CommandResult.fromSuccess());
} }
@@ -59,7 +59,7 @@ public class UnBan extends AbstractConditionableCommand {
String userIdStr = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, String.class); String userIdStr = slashCommandParameterService.getCommandOption(USER_PARAMETER, event, String.class);
Long userId = Long.parseLong(userIdStr); Long userId = Long.parseLong(userIdStr);
return userService.retrieveUserForId(userId) return userService.retrieveUserForId(userId)
.thenCompose(user -> banService.unbanUser(event.getGuild(), userId)) .thenCompose(user -> banService.unbanUser(event.getGuild(), user, event.getMember()))
.thenCompose(unused -> interactionService.replyEmbed(UN_BAN_RESPONSE, event)) .thenCompose(unused -> interactionService.replyEmbed(UN_BAN_RESPONSE, event))
.thenApply(interactionHook -> CommandResult.fromSuccess()); .thenApply(interactionHook -> CommandResult.fromSuccess());
} }

View File

@@ -12,7 +12,6 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException; import dev.sheldan.abstracto.core.exception.EntityGuildMismatchException;
import dev.sheldan.abstracto.core.interaction.InteractionService; import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition; import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
import dev.sheldan.abstracto.moderation.config.ModerationSlashCommandNames; import dev.sheldan.abstracto.moderation.config.ModerationSlashCommandNames;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
@@ -42,9 +41,6 @@ public class UnMute extends AbstractConditionableCommand {
@Autowired @Autowired
private InteractionService interactionService; private InteractionService interactionService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override @Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) { public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters(); List<Object> parameters = commandContext.getParameters().getParameters();

View File

@@ -0,0 +1,43 @@
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.AsyncMemberKickedListener;
import dev.sheldan.abstracto.core.models.listener.MemberKickedModel;
import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.model.template.command.KickLogModel;
import dev.sheldan.abstracto.moderation.service.KickService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class MemberKickedListener implements AsyncMemberKickedListener {
@Autowired
private KickService kickService;
@Override
public FeatureDefinition getFeature() {
return ModerationFeatureDefinition.MODERATION;
}
@Override
public DefaultListenerResult execute(MemberKickedModel eventModel) {
log.info("Notifying about kicked of user {} in guild {}.", eventModel.getKickedServerUser().getUserId(), eventModel.getServerId());
if(eventModel.getKickingServerUser().getUserId() == eventModel.getGuild().getJDA().getSelfUser().getIdLong()) {
log.info("Skipping logging kicked event about user {} in guild {}, because it was done by us.", eventModel.getKickedServerUser().getUserId(), eventModel.getGuild().getIdLong());
return DefaultListenerResult.IGNORED;
}
KickLogModel model = KickLogModel
.builder()
.kickedUser(eventModel.getKickedUser() != null ? UserDisplay.fromUser(eventModel.getKickedUser()) : UserDisplay.fromId(eventModel.getKickedServerUser().getUserId()))
.kickingUser(eventModel.getKickingUser() != null ? UserDisplay.fromUser(eventModel.getKickingUser()) : UserDisplay.fromServerUser(eventModel.getKickingServerUser()))
.reason(eventModel.getReason())
.build();
kickService.sendKicklog(model, eventModel.getServerId());
return DefaultListenerResult.PROCESSED;
}
}

View File

@@ -5,16 +5,10 @@ import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMemberTimeoutUpdatedListener; import dev.sheldan.abstracto.core.listener.async.jda.AsyncMemberTimeoutUpdatedListener;
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel; import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; 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.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.posttarget.MutingPostTarget; import dev.sheldan.abstracto.moderation.model.template.command.MuteLogModel;
import dev.sheldan.abstracto.moderation.model.template.command.MuteListenerModel; import dev.sheldan.abstracto.moderation.service.MuteService;
import dev.sheldan.abstracto.moderation.service.MuteServiceBean;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -26,30 +20,31 @@ import java.time.Instant;
public class MemberTimeoutLoggerListener implements AsyncMemberTimeoutUpdatedListener { public class MemberTimeoutLoggerListener implements AsyncMemberTimeoutUpdatedListener {
@Autowired @Autowired
private TemplateService templateService; private MuteService muteService;
@Autowired
private PostTargetService postTargetService;
@Override @Override
public DefaultListenerResult execute(MemberTimeoutUpdatedModel model) { public DefaultListenerResult execute(MemberTimeoutUpdatedModel model) {
Guild guild = model.getGuild(); log.info("Notifying about timeout of user {} in guild {}.", model.getMutedUser().getUserId(), model.getServerId());
MemberDisplay memberDisplay = model.getMember() != null ? MemberDisplay.fromMember(model.getMember()) : MemberDisplay.fromServerUser(model.getTimeoutUser()); if(model.getMutingUser().getUserId() == model.getGuild().getSelfMember().getIdLong()) {
log.info("Skipping logging timeout event about user {} in guild {}, because it was done by us.", model.getMutedUser().getUserId(), model.getGuild().getIdLong());
return DefaultListenerResult.IGNORED;
}
MemberDisplay mutedMemberDisplay = model.getMutedMember() != null ? MemberDisplay.fromMember(model.getMutedMember()) : MemberDisplay.fromServerUser(model.getMutedUser());
MemberDisplay mutingMemberDisplay = model.getMutingMember() != null ? MemberDisplay.fromMember(model.getMutingMember()) : MemberDisplay.fromServerUser(model.getMutingUser());
Duration duration = null; Duration duration = null;
if(model.getNewTimeout() != null) { if(model.getNewTimeout() != null) {
duration = Duration.between(Instant.now(), model.getNewTimeout()); duration = Duration.between(Instant.now(), model.getNewTimeout());
} }
MuteListenerModel muteLogModel = MuteListenerModel MuteLogModel muteLogModel = MuteLogModel
.builder() .builder()
.muteTargetDate(model.getNewTimeout() != null ? model.getNewTimeout().toInstant() : null) .muteTargetDate(model.getNewTimeout() != null ? model.getNewTimeout().toInstant() : null)
.oldMuteTargetDate(model.getOldTimeout() != null ? model.getOldTimeout().toInstant() : null) .oldMuteTargetDate(model.getOldTimeout() != null ? model.getOldTimeout().toInstant() : null)
.mutingUser(MemberDisplay.fromIds(model.getServerId(), model.getResponsibleUserId())) .mutingMember(mutingMemberDisplay)
.mutedUser(memberDisplay) .mutedMember(mutedMemberDisplay)
.duration(duration) .duration(duration)
.reason(model.getReason()) .reason(model.getReason())
.build(); .build();
MessageToSend message = templateService.renderEmbedTemplate(MuteServiceBean.MUTE_LOG_TEMPLATE, muteLogModel, guild.getIdLong()); muteService.sendMuteLogMessage(muteLogModel, model.getServerId());
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, model.getServerId()));
return DefaultListenerResult.PROCESSED; return DefaultListenerResult.PROCESSED;
} }

View File

@@ -9,7 +9,6 @@ import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionLis
import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerResult; import dev.sheldan.abstracto.core.interaction.modal.listener.ModalInteractionListenerResult;
import dev.sheldan.abstracto.core.models.ServerChannelMessage; import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.core.utils.ParseUtils; import dev.sheldan.abstracto.core.utils.ParseUtils;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
@@ -38,9 +37,6 @@ public class MuteModerationActionModalListener implements ModalInteractionListen
@Autowired @Autowired
private InteractionService interactionService; private InteractionService interactionService;
@Autowired
private TemplateService templateService;
@Autowired @Autowired
private InteractionExceptionService interactionExceptionService; private InteractionExceptionService interactionExceptionService;

View File

@@ -3,15 +3,11 @@ package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult; import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncUserBannedListener; import dev.sheldan.abstracto.core.listener.async.jda.AsyncUserBannedListener;
import dev.sheldan.abstracto.core.models.listener.UserBannedModel; import dev.sheldan.abstracto.core.models.listener.UserBannedListenerModel;
import dev.sheldan.abstracto.core.models.template.display.UserDisplay; import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
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.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget; import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedLogModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedListenerLogModel; import dev.sheldan.abstracto.moderation.service.BanService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -21,24 +17,22 @@ import org.springframework.stereotype.Component;
public class UserBannedListener implements AsyncUserBannedListener { public class UserBannedListener implements AsyncUserBannedListener {
@Autowired @Autowired
private TemplateService templateService; private BanService banService;
@Autowired
private PostTargetService postTargetService;
public static final String USER_BANNED_NOTIFICATION_TEMPLATE = "userBanned_listener_notification";
@Override @Override
public DefaultListenerResult execute(UserBannedModel eventModel) { public DefaultListenerResult execute(UserBannedListenerModel eventModel) {
log.info("Notifying about ban of user {} in guild {}.", eventModel.getBannedServerUser().getUserId(), eventModel.getServerId()); log.info("Notifying about ban of user {} in guild {}.", eventModel.getBannedServerUser().getUserId(), eventModel.getServerId());
UserBannedListenerLogModel model = UserBannedListenerLogModel if(eventModel.getBanningServerUser().getUserId() == eventModel.getGuild().getJDA().getSelfUser().getIdLong()) {
log.info("Skipping logging banned event about user {} in guild {}, because it was done by us.", eventModel.getBannedServerUser().getUserId(), eventModel.getGuild().getIdLong());
return DefaultListenerResult.IGNORED;
}
UserBannedLogModel model = UserBannedLogModel
.builder() .builder()
.bannedUser(eventModel.getBannedUser() != null ? UserDisplay.fromUser(eventModel.getBannedUser()) : UserDisplay.fromId(eventModel.getBannedServerUser().getUserId())) .bannedUser(eventModel.getBannedUser() != null ? UserDisplay.fromUser(eventModel.getBannedUser()) : UserDisplay.fromId(eventModel.getBannedServerUser().getUserId()))
.banningUser(eventModel.getBanningUser() != null ? UserDisplay.fromUser(eventModel.getBanningUser()) : UserDisplay.fromServerUser(eventModel.getBanningServerUser())) .banningUser(eventModel.getBanningUser() != null ? UserDisplay.fromUser(eventModel.getBanningUser()) : UserDisplay.fromServerUser(eventModel.getBanningServerUser()))
.reason(eventModel.getReason()) .reason(eventModel.getReason())
.build(); .build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_BANNED_NOTIFICATION_TEMPLATE, model, eventModel.getServerId()); banService.sendBanLogMessage(model, eventModel.getServerId());
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModerationPostTarget.BAN_LOG, eventModel.getServerId()));
return DefaultListenerResult.PROCESSED; return DefaultListenerResult.PROCESSED;
} }

View File

@@ -3,15 +3,11 @@ package dev.sheldan.abstracto.moderation.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult; import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncUserUnBannedListener; import dev.sheldan.abstracto.core.listener.async.jda.AsyncUserUnBannedListener;
import dev.sheldan.abstracto.core.models.listener.UserUnBannedModel; import dev.sheldan.abstracto.core.models.listener.UserUnBannedListenerModel;
import dev.sheldan.abstracto.core.models.template.display.UserDisplay; import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
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.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget; import dev.sheldan.abstracto.moderation.model.template.listener.UserUnBannedLogModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserUnBannedListenerLogModel; import dev.sheldan.abstracto.moderation.service.BanService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -21,24 +17,22 @@ import org.springframework.stereotype.Component;
public class UserUnBannedListener implements AsyncUserUnBannedListener { public class UserUnBannedListener implements AsyncUserUnBannedListener {
@Autowired @Autowired
private TemplateService templateService; private BanService banService;
@Autowired
private PostTargetService postTargetService;
private static final String USER_UN_BANNED_NOTIFICATION_TEMPLATE = "userUnBanned_listener_notification";
@Override @Override
public DefaultListenerResult execute(UserUnBannedModel eventModel) { public DefaultListenerResult execute(UserUnBannedListenerModel eventModel) {
log.info("Notifying about unban of user {} in guild {}.", eventModel.getUnBannedServerUser().getUserId(), eventModel.getServerId()); log.info("Notifying about unban of user {} in guild {}.", eventModel.getUnBannedServerUser().getUserId(), eventModel.getServerId());
UserUnBannedListenerLogModel model = UserUnBannedListenerLogModel if(eventModel.getUnBanningUser().getIdLong() == eventModel.getGuild().getSelfMember().getIdLong()) {
log.info("Skipping logging banned event about user {} in guild {}, because it was done by us.", eventModel.getUnBannedServerUser().getUserId(), eventModel.getGuild().getIdLong());
return DefaultListenerResult.IGNORED;
}
UserUnBannedLogModel model = UserUnBannedLogModel
.builder() .builder()
.unBannedUser(eventModel.getUnBannedUser() != null ? UserDisplay.fromUser(eventModel.getUnBannedUser()) : UserDisplay.fromId(eventModel.getUnBannedServerUser().getUserId())) .unBannedUser(eventModel.getUnBannedUser() != null ? UserDisplay.fromUser(eventModel.getUnBannedUser()) : UserDisplay.fromId(eventModel.getUnBannedServerUser().getUserId()))
.unBanningUser(eventModel.getUnBanningUser() != null ? UserDisplay.fromUser(eventModel.getUnBanningUser()) : UserDisplay.fromServerUser(eventModel.getUnBanningServerUser())) .unBanningUser(eventModel.getUnBanningUser() != null ? UserDisplay.fromUser(eventModel.getUnBanningUser()) : UserDisplay.fromServerUser(eventModel.getUnBanningServerUser()))
.reason(eventModel.getReason()) .reason(eventModel.getReason())
.build(); .build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_UN_BANNED_NOTIFICATION_TEMPLATE, model, eventModel.getServerId()); banService.sendUnBanLogMessage(model, eventModel.getServerId());
FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModerationPostTarget.BAN_LOG, eventModel.getServerId()));
return DefaultListenerResult.PROCESSED; return DefaultListenerResult.PROCESSED;
} }

View File

@@ -14,8 +14,9 @@ import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefiniti
import dev.sheldan.abstracto.moderation.listener.InfractionUpdatedDescriptionListener; import dev.sheldan.abstracto.moderation.listener.InfractionUpdatedDescriptionListener;
import dev.sheldan.abstracto.moderation.model.database.Infraction; import dev.sheldan.abstracto.moderation.model.database.Infraction;
import dev.sheldan.abstracto.moderation.model.listener.InfractionDescriptionEventModel; import dev.sheldan.abstracto.moderation.model.listener.InfractionDescriptionEventModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedListenerLogModel; import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedLogModel;
import dev.sheldan.abstracto.moderation.service.BanService; import dev.sheldan.abstracto.moderation.service.BanService;
import dev.sheldan.abstracto.moderation.service.BanServiceBean;
import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService; import dev.sheldan.abstracto.moderation.service.management.InfractionManagementService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
@@ -26,8 +27,6 @@ import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.moderation.listener.UserBannedListener.USER_BANNED_NOTIFICATION_TEMPLATE;
@Component @Component
@Slf4j @Slf4j
@@ -75,14 +74,14 @@ public class BanReasonUpdatedListener implements InfractionUpdatedDescriptionLis
public void handleBanUpdate(InfractionDescriptionEventModel model, CompletableFuture<User> infractionUser, CompletableFuture<User> infractionCreator, CompletableFuture<DefaultListenerResult> returningFuture) { public void handleBanUpdate(InfractionDescriptionEventModel model, CompletableFuture<User> infractionUser, CompletableFuture<User> infractionCreator, CompletableFuture<DefaultListenerResult> returningFuture) {
Infraction infraction = infractionManagementService.loadInfraction(model.getInfractionId()); Infraction infraction = infractionManagementService.loadInfraction(model.getInfractionId());
GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(model.getServerId(), infraction.getLogChannel().getId()); GuildMessageChannel messageChannel = channelService.getMessageChannelFromServer(model.getServerId(), infraction.getLogChannel().getId());
UserBannedListenerLogModel banLog = UserBannedListenerLogModel UserBannedLogModel banLog = UserBannedLogModel
.builder() .builder()
.bannedUser(infractionUser.isCompletedExceptionally() ? null : UserDisplay.fromUser(infractionUser.join())) .bannedUser(infractionUser.isCompletedExceptionally() ? null : UserDisplay.fromUser(infractionUser.join()))
.banningUser(infractionCreator.isCompletedExceptionally() ? null : UserDisplay.fromUser(infractionCreator.join())) .banningUser(infractionCreator.isCompletedExceptionally() ? null : UserDisplay.fromUser(infractionCreator.join()))
.reason(model.getNewDescription()) .reason(model.getNewDescription())
.build(); .build();
MessageToSend message = templateService.renderEmbedTemplate(USER_BANNED_NOTIFICATION_TEMPLATE, banLog, model.getServerId()); MessageToSend message = templateService.renderEmbedTemplate(BanServiceBean.USER_BANNED_NOTIFICATION_TEMPLATE, banLog, model.getServerId());
messageService.editMessageInChannel(messageChannel, message, infraction.getLogMessageId()) messageService.editMessageInChannel(messageChannel, message, infraction.getLogMessageId())
.thenAccept(unused1 -> returningFuture.complete(DefaultListenerResult.PROCESSED)) .thenAccept(unused1 -> returningFuture.complete(DefaultListenerResult.PROCESSED))
.exceptionally(throwable1 -> { .exceptionally(throwable1 -> {

View File

@@ -2,27 +2,36 @@ package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ConfigService; import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
import dev.sheldan.abstracto.core.service.FeatureFlagService; import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.MessageService;
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.CompletableFutureMap;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
import dev.sheldan.abstracto.moderation.config.posttarget.ModerationPostTarget;
import dev.sheldan.abstracto.moderation.model.BanResult; import dev.sheldan.abstracto.moderation.model.BanResult;
import dev.sheldan.abstracto.moderation.model.database.Infraction; import dev.sheldan.abstracto.moderation.model.database.Infraction;
import dev.sheldan.abstracto.moderation.model.template.command.BanNotificationModel; import dev.sheldan.abstracto.moderation.model.template.command.BanNotificationModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedLogModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserUnBannedLogModel;
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.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.UserSnowflake; import net.dv8tion.jda.api.entities.UserSnowflake;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Component @Component
@@ -52,6 +61,15 @@ public class BanServiceBean implements BanService {
@Autowired @Autowired
private InfractionService infractionService; private InfractionService infractionService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private UserService userService;
public static final String USER_BANNED_NOTIFICATION_TEMPLATE = "userBanned_listener_notification";
private static final String USER_UN_BANNED_NOTIFICATION_TEMPLATE = "userUnBanned_listener_notification";
@Override @Override
public CompletableFuture<BanResult> banUserWithNotification(ServerUser userToBeBanned, String reason, ServerUser banningUser, Guild guild, Duration deletionDuration) { public CompletableFuture<BanResult> banUserWithNotification(ServerUser userToBeBanned, String reason, ServerUser banningUser, Guild guild, Duration deletionDuration) {
BanResult[] result = {BanResult.SUCCESSFUL}; BanResult[] result = {BanResult.SUCCESSFUL};
@@ -61,6 +79,7 @@ public class BanServiceBean implements BanService {
return null; return null;
}) })
.thenCompose(unused -> banUser(guild, userToBeBanned, deletionDuration, reason)) .thenCompose(unused -> banUser(guild, userToBeBanned, deletionDuration, reason))
.thenCompose(unused -> self.composeAndSendBanLogMessage(userToBeBanned, banningUser, reason))
.thenAccept(banLogMessage -> self.evaluateAndStoreInfraction(userToBeBanned, guild, reason, banningUser, deletionDuration)) .thenAccept(banLogMessage -> self.evaluateAndStoreInfraction(userToBeBanned, guild, reason, banningUser, deletionDuration))
.thenApply(unused -> result[0]); .thenApply(unused -> result[0]);
} }
@@ -103,15 +122,60 @@ public class BanServiceBean implements BanService {
} }
@Override @Override
public CompletableFuture<Void> unbanUser(Guild guild, Long userId) { public CompletableFuture<Void> unbanUser(Guild guild, User user, Member memberPerforming) {
log.info("Unbanning user {} in guild {}.", userId, guild.getId()); log.info("Unbanning user {} in guild {}.", user.getIdLong(), guild.getId());
return guild.unban(UserSnowflake.fromId(userId)).submit(); return guild.unban(user).submit().thenCompose(unused -> self.composeAndSendUnBanLogMessage(guild, user, memberPerforming));
}
@Transactional
public CompletionStage<Void> composeAndSendUnBanLogMessage(Guild guild, User user, Member memberPerforming) {
UserUnBannedLogModel model = UserUnBannedLogModel
.builder()
.unBannedUser(UserDisplay.fromUser(user))
.unBanningUser(UserDisplay.fromUser(memberPerforming.getUser()))
.reason(null)
.build();
return sendUnBanLogMessage(model, guild.getIdLong());
}
@Transactional
public CompletableFuture<Void> composeAndSendBanLogMessage(ServerUser serverUserToBeBanned, ServerUser serverUserBanning, String reason) {
CompletableFutureMap<Long, User> userMap = userService.retrieveUsersMapped(Arrays.asList(serverUserToBeBanned.getUserId(), serverUserBanning.getUserId()));
return userMap.getMainFuture().thenCompose(unused -> {
User userToBeBanned = userMap.getElement(serverUserToBeBanned.getUserId());
User banningUser = userMap.getElement(serverUserBanning.getUserId());
UserBannedLogModel model = UserBannedLogModel
.builder()
.bannedUser(UserDisplay.fromUser(userToBeBanned))
.banningUser(UserDisplay.fromUser(banningUser))
.reason(reason)
.build();
return self.sendBanLogMessage(model, serverUserToBeBanned.getServerId());
}).exceptionally(throwable -> {
log.warn("Failed to load users ({}, {}) for ban log message.", serverUserToBeBanned.getUserId(), serverUserBanning.getUserId(), throwable);
UserBannedLogModel model = UserBannedLogModel
.builder()
.bannedUser(UserDisplay.fromId(serverUserToBeBanned.getUserId()))
.banningUser(UserDisplay.fromId(serverUserBanning.getUserId()))
.reason(reason)
.build();
self.sendBanLogMessage(model, serverUserToBeBanned.getServerId());
return null;
});
} }
@Override @Override
public CompletableFuture<Void> softBanUser(Guild guild, ServerUser user, Duration delDays) { @Transactional
return banUser(guild, user, delDays, "") public CompletableFuture<Void> sendUnBanLogMessage(UserUnBannedLogModel model, Long serverId) {
.thenCompose(unused -> unbanUser(guild, user.getUserId())); MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_UN_BANNED_NOTIFICATION_TEMPLATE, model, serverId);
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModerationPostTarget.BAN_LOG, serverId));
}
@Override
@Transactional
public CompletableFuture<Void> sendBanLogMessage(UserBannedLogModel model, Long serverId) {
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_BANNED_NOTIFICATION_TEMPLATE, model, serverId);
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModerationPostTarget.BAN_LOG, serverId));
} }
} }

View File

@@ -2,11 +2,13 @@ package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
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.models.template.display.UserDisplay;
import dev.sheldan.abstracto.core.service.ConfigService; import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.FeatureFlagService; import dev.sheldan.abstracto.core.service.FeatureFlagService;
import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.UserService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureMap;
import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureConfig;
import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition; import dev.sheldan.abstracto.moderation.config.feature.ModerationFeatureDefinition;
@@ -16,14 +18,12 @@ import dev.sheldan.abstracto.moderation.model.template.command.KickLogModel;
import dev.sheldan.abstracto.core.templating.model.MessageToSend; import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService; import dev.sheldan.abstracto.core.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.UserSnowflake;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -51,6 +51,9 @@ public class KickServiceBean implements KickService {
@Autowired @Autowired
private InfractionService infractionService; private InfractionService infractionService;
@Autowired
private UserService userService;
@Autowired @Autowired
private KickServiceBean self; private KickServiceBean self;
@@ -59,7 +62,7 @@ public class KickServiceBean implements KickService {
Guild guild = kickedMember.getGuild(); Guild guild = kickedMember.getGuild();
log.info("Kicking user {} from guild {}", kickedMember.getUser().getIdLong(), guild.getIdLong()); log.info("Kicking user {} from guild {}", kickedMember.getUser().getIdLong(), guild.getIdLong());
CompletableFuture<Void> kickFuture = guild.kick(kickedMember, reason).submit(); CompletableFuture<Void> kickFuture = guild.kick(kickedMember, reason).submit();
CompletableFuture<Message> logFuture = sendKickLog(kickedMember, kickingMember, reason, guild.getIdLong()); CompletableFuture<Message> logFuture = sendKickLog(kickedMember.getUser(), ServerUser.fromMember(kickedMember), kickingMember.getUser(), ServerUser.fromMember(kickingMember), reason, guild.getIdLong());
return CompletableFuture.allOf(kickFuture, logFuture) return CompletableFuture.allOf(kickFuture, logFuture)
.thenAccept(unused -> self.storeInfraction(kickedMember, kickingMember, reason, logFuture.join(), guild.getIdLong())); .thenAccept(unused -> self.storeInfraction(kickedMember, kickingMember, reason, logFuture.join(), guild.getIdLong()));
} }
@@ -96,27 +99,30 @@ public class KickServiceBean implements KickService {
} }
} }
private CompletableFuture<Message> sendKickLog(Member kickedMember, Member kickingMember, String reason, Long serverId) { public CompletableFuture<Message> sendKickLog(User kickedUser, ServerUser kickedServerUser, User kickingUser, ServerUser kickingServerUser, String reason, Long serverId) {
KickLogModel kickLogModel = KickLogModel KickLogModel kickLogModel = KickLogModel
.builder() .builder()
.kickedMember(MemberDisplay.fromMember(kickedMember)) .kickedUser(kickedUser != null ? UserDisplay.fromUser(kickedUser) : UserDisplay.fromServerUser(kickedServerUser))
.kickingMember(MemberDisplay.fromMember(kickingMember)) .kickingUser(kickingUser != null ? UserDisplay.fromUser(kickingUser) : UserDisplay.fromServerUser(kickingServerUser))
.reason(reason) .reason(reason)
.build(); .build();
return sendKicklog(serverId, kickLogModel); return sendKicklog(kickLogModel, serverId);
} }
private CompletableFuture<Message> sendKickLog(ServerUser kickedMember, ServerUser kickingMember, String reason, Long serverId) { public CompletableFuture<Message> sendKickLog(ServerUser kickedMember, ServerUser kickingMember, String reason, Long serverId) {
KickLogModel kickLogModel = KickLogModel CompletableFutureMap<Long, User> userMap = userService.retrieveUsersMapped(Arrays.asList(kickedMember.getUserId(), kickingMember.getUserId()));
.builder() return userMap.getMainFuture().thenCompose(unused -> {
.kickedMember(MemberDisplay.fromServerUser(kickedMember)) User kickedUser = userMap.getElement(kickedMember.getUserId());
.kickingMember(MemberDisplay.fromServerUser(kickingMember)) User kickingUser = userMap.getElement(kickingMember.getUserId());
.reason(reason) return self.sendKickLog(kickedUser, kickedMember, kickingUser, kickingMember, reason, serverId);
.build(); }).exceptionally(throwable -> {
return sendKicklog(serverId, kickLogModel); log.warn("Failed to fetch users ({}, {}) for kick event logging in server {}.", kickingMember.getUserId(), kickedMember.getUserId(), serverId, throwable);
self.sendKickLog(null, kickedMember, null, kickingMember, reason, serverId);
return null;
});
} }
private CompletableFuture<Message> sendKicklog(Long serverId, KickLogModel kickLogModel) { public CompletableFuture<Message> sendKicklog(KickLogModel kickLogModel, Long serverId) {
MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, serverId); MessageToSend warnLogMessage = templateService.renderEmbedTemplate(KICK_LOG_TEMPLATE, kickLogModel, serverId);
log.debug("Sending kick log message in guild {}.", serverId); log.debug("Sending kick log message in guild {}.", serverId);
List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, serverId); List<CompletableFuture<Message>> messageFutures = postTargetService.sendEmbedInPostTarget(warnLogMessage, ModerationPostTarget.KICK_LOG, serverId);

View File

@@ -6,23 +6,29 @@ 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.MuteLogModel;
import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification; import dev.sheldan.abstracto.moderation.model.template.command.MuteNotification;
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.Member;
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;
@@ -161,18 +167,58 @@ public class MuteServiceBean implements MuteService {
@Override @Override
public CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin) { public CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin) {
return muteMemberWithLog(userToMute, mutingUser, reason, duration, guild, origin, null);
}
@Override
public CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin, Instant oldTimeout) {
Long serverId = userToMute.getServerId(); Long serverId = userToMute.getServerId();
Instant targetDate = Instant.now().plus(duration); Instant targetDate = Instant.now().plus(duration);
log.debug("Muting member {} in server {}.", userToMute.getUserId(), serverId); log.info("Muting member {} in server {}.", userToMute.getUserId(), serverId);
AServer server = serverManagementService.loadOrCreate(serverId); AServer server = serverManagementService.loadOrCreate(serverId);
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(muteResult -> self.composeAndLogMute(userToMute, mutingUser, reason, duration, guild, oldTimeout))
.thenCompose(logMessage -> self.evaluateAndStoreInfraction(userToMute, mutingUser, reason, targetDate)) .thenCompose(logMessage -> self.evaluateAndStoreInfraction(userToMute, mutingUser, reason, targetDate))
.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
public CompletableFuture<Void> composeAndLogMute(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, Instant oldTimeout) {
CompletableFuture<Member> mutedMemberFuture = memberService.retrieveMemberInServer(userToMute);
CompletableFuture<Member> mutingMemberFuture = memberService.retrieveMemberInServer(mutingUser);
Instant targetDate = Instant.now().plus(duration);
return CompletableFuture.allOf(mutedMemberFuture, mutingMemberFuture).thenCompose(unused -> {
Member mutedMember = mutedMemberFuture.join();
Member mutingMember = mutingMemberFuture.join();
MuteLogModel muteLogModel = MuteLogModel
.builder()
.muteTargetDate(targetDate)
.oldMuteTargetDate(oldTimeout)
.mutingMember(MemberDisplay.fromMember(mutingMember))
.mutedMember(MemberDisplay.fromMember(mutedMember))
.duration(duration)
.reason(reason)
.build();
return self.sendMuteLogMessage(muteLogModel, guild.getIdLong());
}).exceptionally(throwable -> {
log.warn("Failed to load users for mute log ({}, {}) in guild {}.", userToMute.getUserId(), mutingUser.getUserId(), guild.getIdLong(), throwable);
MuteLogModel muteLogModel = MuteLogModel
.builder()
.muteTargetDate(targetDate)
.oldMuteTargetDate(null)
.mutingMember(MemberDisplay.fromServerUser(mutingUser))
.mutedMember(MemberDisplay.fromServerUser(userToMute))
.duration(duration)
.reason(reason)
.build();
self.sendMuteLogMessage(muteLogModel, guild.getIdLong());
return null;
});
}
@Transactional @Transactional
public CompletableFuture<Long> evaluateAndStoreInfraction(ServerUser userToMute, ServerUser mutingUser, String reason, Instant targetDate) { public CompletableFuture<Long> evaluateAndStoreInfraction(ServerUser userToMute, ServerUser mutingUser, String reason, Instant targetDate) {
Long serverId = userToMute.getServerId(); Long serverId = userToMute.getServerId();
@@ -218,8 +264,10 @@ 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.composeAndLogUnmute(mutedUser, mutingUser, guild))
.thenAccept(unused -> { .thenAccept(unused -> {
if(muteId != null) { if(muteId != null) {
self.endMuteInDatabase(muteId, guild.getIdLong()); self.endMuteInDatabase(muteId, guild.getIdLong());
@@ -227,6 +275,26 @@ public class MuteServiceBean implements MuteService {
}); });
} }
@Transactional
public CompletableFuture<Void> composeAndLogUnmute(ServerUser mutedUser, ServerUser mutingUser, Guild guild) {
CompletableFuture<Member> mutedMemberFuture = memberService.retrieveMemberInServer(mutedUser);
CompletableFuture<Member> mutingMemberFuture = memberService.retrieveMemberInServer(mutingUser);
return CompletableFuture.allOf(mutedMemberFuture, mutingMemberFuture).thenCompose(unused -> {
Member mutedMember = mutedMemberFuture.join();
Member mutingMember = mutingMemberFuture.join();
MuteLogModel muteLogModel = MuteLogModel
.builder()
.muteTargetDate(null)
.oldMuteTargetDate(null)
.mutingMember(MemberDisplay.fromMember(mutingMember))
.mutedMember(MemberDisplay.fromMember(mutedMember))
.duration(null)
.reason(null)
.build();
return self.sendMuteLogMessage(muteLogModel, guild.getIdLong());
});
}
@Transactional @Transactional
public void endMuteInDatabase(Long muteId, Long serverId) { public void endMuteInDatabase(Long muteId, Long serverId) {
Optional<Mute> muteOptional = muteManagementService.findMuteOptional(muteId, serverId); Optional<Mute> muteOptional = muteManagementService.findMuteOptional(muteId, serverId);
@@ -248,6 +316,12 @@ public class MuteServiceBean implements MuteService {
} }
} }
@Override
public CompletableFuture<Void> sendMuteLogMessage(MuteLogModel model, Long serverId) {
MessageToSend message = templateService.renderEmbedTemplate(MuteServiceBean.MUTE_LOG_TEMPLATE, model, serverId);
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(message, MutingPostTarget.MUTE_LOG, serverId));
}
@Override @Override
public void completelyUnMuteUser(AUserInAServer aUserInAServer) { public void completelyUnMuteUser(AUserInAServer aUserInAServer) {
log.info("Completely unmuting user {} in server {}.", aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId()); log.info("Completely unmuting user {} in server {}.", aUserInAServer.getUserReference().getId(), aUserInAServer.getServerReference().getId());

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.moderation.model.template.command; package dev.sheldan.abstracto.moderation.model.template.command;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
import lombok.Builder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@@ -13,6 +13,6 @@ import lombok.Setter;
@Setter @Setter
public class KickLogModel { public class KickLogModel {
private String reason; private String reason;
private MemberDisplay kickedMember; private UserDisplay kickedUser;
private MemberDisplay kickingMember; private UserDisplay kickingUser;
} }

View File

@@ -10,15 +10,15 @@ import java.time.Instant;
@Getter @Getter
@SuperBuilder @SuperBuilder
public class MuteListenerModel { public class MuteLogModel {
/** /**
* The {@link Member} being muted * The {@link Member} being muted
*/ */
private MemberDisplay mutedUser; private MemberDisplay mutedMember;
/** /**
* The {@link Member} executing the mute * The {@link Member} executing the mute
*/ */
private MemberDisplay mutingUser; private MemberDisplay mutingMember;
/** /**
* The persisted mute object from the database containing the information about the mute * The persisted mute object from the database containing the information about the mute
*/ */

View File

@@ -8,7 +8,7 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class UserBannedListenerLogModel { public class UserBannedLogModel {
private UserDisplay bannedUser; private UserDisplay bannedUser;
private String reason; private String reason;
private UserDisplay banningUser; private UserDisplay banningUser;

View File

@@ -8,7 +8,7 @@ import lombok.Setter;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class UserUnBannedListenerLogModel { public class UserUnBannedLogModel {
private UserDisplay unBannedUser; private UserDisplay unBannedUser;
private String reason; private String reason;
private UserDisplay unBanningUser; private UserDisplay unBanningUser;

View File

@@ -2,6 +2,8 @@ package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.moderation.model.BanResult; import dev.sheldan.abstracto.moderation.model.BanResult;
import dev.sheldan.abstracto.moderation.model.template.listener.UserBannedLogModel;
import dev.sheldan.abstracto.moderation.model.template.listener.UserUnBannedLogModel;
import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.*;
import java.time.Duration; import java.time.Duration;
@@ -13,6 +15,7 @@ public interface BanService {
String INFRACTION_PARAMETER_DELETION_DURATION_KEY = "DELETION_DURATION"; String INFRACTION_PARAMETER_DELETION_DURATION_KEY = "DELETION_DURATION";
CompletableFuture<BanResult> banUserWithNotification(ServerUser userToBeBanned, String reason, ServerUser banningUser, Guild guild, Duration deletionDuration); CompletableFuture<BanResult> banUserWithNotification(ServerUser userToBeBanned, String reason, ServerUser banningUser, Guild guild, Duration deletionDuration);
CompletableFuture<Void> banUser(Guild guild, ServerUser userToBeBanned, Duration deletionDuration, String reason); CompletableFuture<Void> banUser(Guild guild, ServerUser userToBeBanned, Duration deletionDuration, String reason);
CompletableFuture<Void> unbanUser(Guild guild, Long userId); CompletableFuture<Void> unbanUser(Guild guild, User user, Member memberPerforming);
CompletableFuture<Void> softBanUser(Guild guild, ServerUser user, Duration delDays); CompletableFuture<Void> sendBanLogMessage(UserBannedLogModel model, Long serverId);
CompletableFuture<Void> sendUnBanLogMessage(UserUnBannedLogModel model, Long serverId);
} }

View File

@@ -1,8 +1,10 @@
package dev.sheldan.abstracto.moderation.service; package dev.sheldan.abstracto.moderation.service;
import dev.sheldan.abstracto.core.models.ServerUser; import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.moderation.model.template.command.KickLogModel;
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.Message;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@@ -11,4 +13,5 @@ public interface KickService {
String KICK_INFRACTION_TYPE = "kick"; String KICK_INFRACTION_TYPE = "kick";
CompletableFuture<Void> kickMember(Member kickedMember, Member kickingMember, String reason); CompletableFuture<Void> kickMember(Member kickedMember, Member kickingMember, String reason);
CompletableFuture<Void> kickMember(Guild guild, ServerUser kickedUser, String reason, ServerUser kickingUser); CompletableFuture<Void> kickMember(Guild guild, ServerUser kickedUser, String reason, ServerUser kickingUser);
CompletableFuture<Message> sendKicklog(KickLogModel kickLogModel, Long serverId);
} }

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.moderation.model.MuteResult; import dev.sheldan.abstracto.moderation.model.MuteResult;
import dev.sheldan.abstracto.moderation.model.database.Mute; import dev.sheldan.abstracto.moderation.model.database.Mute;
import dev.sheldan.abstracto.moderation.model.template.command.MuteLogModel;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import java.time.Duration; import java.time.Duration;
@@ -17,11 +18,13 @@ public interface MuteService {
String INFRACTION_PARAMETER_DURATION_KEY = "DURATION"; String INFRACTION_PARAMETER_DURATION_KEY = "DURATION";
CompletableFuture<MuteResult> muteUserInServer(Guild guild, ServerUser userBeingMuted, String reason, Duration duration); CompletableFuture<MuteResult> muteUserInServer(Guild guild, ServerUser userBeingMuted, String reason, Duration duration);
CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin); CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin);
CompletableFuture<MuteResult> muteMemberWithLog(ServerUser userToMute, ServerUser mutingUser, String reason, Duration duration, Guild guild, ServerChannelMessage origin, Instant oldTimeout);
String startUnMuteJobFor(Instant unMuteDate, Long muteId, Long serverId); String startUnMuteJobFor(Instant unMuteDate, Long muteId, Long serverId);
void cancelUnMuteJob(Mute mute); void cancelUnMuteJob(Mute mute);
CompletableFuture<Void> unMuteUser(ServerUser userToUnMute, ServerUser memberUnMuting, Guild guild); CompletableFuture<Void> unMuteUser(ServerUser userToUnMute, ServerUser memberUnMuting, Guild guild);
CompletableFuture<Void> endMute(Mute mute, Guild guild); CompletableFuture<Void> endMute(Mute mute, Guild guild);
CompletableFuture<Void> endMute(Long muteId, Long serverId); CompletableFuture<Void> endMute(Long muteId, Long serverId);
CompletableFuture<Void> sendMuteLogMessage(MuteLogModel model, Long serverId);
void completelyUnMuteUser(AUserInAServer aUserInAServer); void completelyUnMuteUser(AUserInAServer aUserInAServer);
void completelyUnMuteMember(ServerUser serverUser); void completelyUnMuteMember(ServerUser serverUser);
} }

View File

@@ -17,6 +17,11 @@ public class ListenerExecutorConfig {
return executorService.setupExecutorFor("memberTimeoutListener"); return executorService.setupExecutorFor("memberTimeoutListener");
} }
@Bean(name = "memberKickedListenerExecutor")
public TaskExecutor memberKickedListenerExecutor() {
return executorService.setupExecutorFor("memberKickedListener");
}
@Bean(name = "joinListenerExecutor") @Bean(name = "joinListenerExecutor")
public TaskExecutor joinListenerExecutor() { public TaskExecutor joinListenerExecutor() {
return executorService.setupExecutorFor("joinListener"); return executorService.setupExecutorFor("joinListener");

View File

@@ -0,0 +1,85 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MemberKickedModel;
import dev.sheldan.abstracto.core.models.listener.MemberTimeoutUpdatedModel;
import dev.sheldan.abstracto.core.service.UserService;
import dev.sheldan.abstracto.core.utils.CompletableFutureMap;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.audit.ActionType;
import net.dv8tion.jda.api.audit.AuditLogChange;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.guild.GuildAuditLogEntryCreateEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
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 javax.annotation.Nonnull;
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
@Component
@Slf4j
public class AsyncMemberKickedListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncMemberKickedListener> listenerList;
@Autowired
@Qualifier("memberKickedListenerExecutor")
private TaskExecutor memberKickedTaskExecutor;
@Autowired
private ListenerService listenerService;
@Autowired
private UserService userService;
@Override
public void onGuildAuditLogEntryCreate(@Nonnull GuildAuditLogEntryCreateEvent event) {
if(listenerList == null) return;
if(event.getEntry().getType().equals(ActionType.KICK)) {
log.info("Handling kick audit log entry created for user {} in server {}.", event.getEntry().getTargetIdLong(), event.getGuild().getIdLong());
CompletableFutureMap<Long, User> longUserCompletableFutureMap = userService.retrieveUsersMapped(Arrays.asList(event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong()));
longUserCompletableFutureMap.getMainFuture().thenAccept(avoid -> {
User kickedUser = longUserCompletableFutureMap.getElement(event.getEntry().getTargetIdLong());
User kickingUser = longUserCompletableFutureMap.getElement(event.getEntry().getUserIdLong());
MemberKickedModel model = getModel(event, kickedUser, kickingUser);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberKickedTaskExecutor));
}).exceptionally(throwable -> {
log.warn("Failed to fetch users {} or {} for kicked event.", event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong(), throwable);
MemberKickedModel model = getModel(event, null, null);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberKickedTaskExecutor));
return null;
});
}
}
private MemberKickedModel getModel(GuildAuditLogEntryCreateEvent event, User kickedUser, User kickingUser) {
ServerUser kickededServerUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getEntry().getTargetIdLong())
.build();
ServerUser kickingServerUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getEntry().getUserIdLong())
.build();
return MemberKickedModel
.builder()
.kickedServerUser(kickededServerUser)
.kickingServerUser(kickingServerUser)
.kickedUser(kickedUser)
.kickingUser(kickingUser)
.guild(event.getGuild())
.reason(event.getEntry().getReason())
.build();
}
}

View File

@@ -44,14 +44,15 @@ public class AsyncMemberTimeoutListenerBean extends ListenerAdapter {
if(event.getEntry().getType().equals(ActionType.MEMBER_UPDATE)) { if(event.getEntry().getType().equals(ActionType.MEMBER_UPDATE)) {
AuditLogChange memberTimeoutChange = event.getEntry().getChangeByKey(AuditLogKey.MEMBER_TIME_OUT); AuditLogChange memberTimeoutChange = event.getEntry().getChangeByKey(AuditLogKey.MEMBER_TIME_OUT);
if(memberTimeoutChange != null) { if(memberTimeoutChange != null) {
CompletableFuture<Member> memberInstanceFuture = memberService.retrieveMemberInServer(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getTargetIdLong())); CompletableFuture<Member> targetMemberFuture = memberService.retrieveMemberInServer(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getTargetIdLong()));
memberInstanceFuture.whenComplete((member, throwable) -> { CompletableFuture<Member> mutingMemberFuture = memberService.retrieveMemberInServer(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getUserIdLong()));
executeListeners(memberTimeoutChange, event, member); CompletableFuture.allOf(targetMemberFuture, mutingMemberFuture).whenComplete((avoid, throwable) -> {
executeListeners(memberTimeoutChange, event, targetMemberFuture.join(), mutingMemberFuture.join());
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
Long memberId = event.getEntry().getTargetIdLong(); Long memberId = event.getEntry().getTargetIdLong();
Long serverId = event.getGuild().getIdLong(); Long serverId = event.getGuild().getIdLong();
log.warn("Failed to load member {} for member update audit log in server {}.", memberId, serverId, throwable); log.warn("Failed to load member {} for member update audit log in server {}.", memberId, serverId, throwable);
executeListeners(memberTimeoutChange, event, null); executeListeners(memberTimeoutChange, event, null, null);
return null; return null;
}); });
@@ -59,21 +60,23 @@ public class AsyncMemberTimeoutListenerBean extends ListenerAdapter {
} }
} }
private void executeListeners(AuditLogChange change, GuildAuditLogEntryCreateEvent event, Member member) { private void executeListeners(AuditLogChange change, GuildAuditLogEntryCreateEvent event, Member mutedMember, Member mutingMember) {
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME; DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
OffsetDateTime timeoutAfter = change.getNewValue() != null ? OffsetDateTime.parse(change.getNewValue(), timeFormatter) : null; OffsetDateTime timeoutAfter = change.getNewValue() != null ? OffsetDateTime.parse(change.getNewValue(), timeFormatter) : null;
OffsetDateTime timeoutBefore = change.getOldValue() != null ? OffsetDateTime.parse(change.getOldValue(), timeFormatter) : null; OffsetDateTime timeoutBefore = change.getOldValue() != null ? OffsetDateTime.parse(change.getOldValue(), timeFormatter) : null;
String reason = event.getEntry().getReason(); String reason = event.getEntry().getReason();
Long serverId = event.getGuild().getIdLong();
MemberTimeoutUpdatedModel model = MemberTimeoutUpdatedModel MemberTimeoutUpdatedModel model = MemberTimeoutUpdatedModel
.builder() .builder()
.oldTimeout(timeoutBefore) .oldTimeout(timeoutBefore)
.newTimeout(timeoutAfter) .newTimeout(timeoutAfter)
.responsibleUserId(event.getEntry().getUserIdLong()) .responsibleUserId(event.getEntry().getUserIdLong())
.member(member) .mutedMember(mutedMember)
.mutingMember(mutingMember)
.reason(reason) .reason(reason)
.guild(event.getGuild()) .guild(event.getGuild())
.user(member != null ? member.getUser() : null) .mutingUser(ServerUser.fromId(serverId, event.getEntry().getUserIdLong()))
.timeoutUser(ServerUser.fromId(event.getGuild().getIdLong(), event.getEntry().getTargetIdLong())) .mutedUser(ServerUser.fromId(serverId, event.getEntry().getTargetIdLong()))
.build(); .build();
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberTimeoutExecutor)); listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, memberTimeoutExecutor));
} }

View File

@@ -2,7 +2,7 @@ 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.UserBannedModel; import dev.sheldan.abstracto.core.models.listener.UserBannedListenerModel;
import dev.sheldan.abstracto.core.service.UserService; import dev.sheldan.abstracto.core.service.UserService;
import dev.sheldan.abstracto.core.utils.CompletableFutureMap; import dev.sheldan.abstracto.core.utils.CompletableFutureMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -45,18 +45,18 @@ public class AsyncUserBannedListenerBean extends ListenerAdapter {
longUserCompletableFutureMap.getMainFuture().thenAccept(avoid -> { longUserCompletableFutureMap.getMainFuture().thenAccept(avoid -> {
User bannedUser = longUserCompletableFutureMap.getElement(event.getEntry().getTargetIdLong()); User bannedUser = longUserCompletableFutureMap.getElement(event.getEntry().getTargetIdLong());
User banningUser = longUserCompletableFutureMap.getElement(event.getEntry().getUserIdLong()); User banningUser = longUserCompletableFutureMap.getElement(event.getEntry().getUserIdLong());
UserBannedModel model = getModel(event, bannedUser, banningUser); UserBannedListenerModel model = getModel(event, bannedUser, banningUser);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor)); listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor));
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
log.warn("Failed to fetch users {} or {} for banned event.", event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong(), throwable); log.warn("Failed to fetch users {} or {} for banned event.", event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong(), throwable);
UserBannedModel model = getModel(event, null, null); UserBannedListenerModel model = getModel(event, null, null);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor)); listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor));
return null; return null;
}); });
} }
} }
private UserBannedModel getModel(GuildAuditLogEntryCreateEvent event, User bannedUser, User banningUser) { private UserBannedListenerModel getModel(GuildAuditLogEntryCreateEvent event, User bannedUser, User banningUser) {
ServerUser bannedServerUser = ServerUser ServerUser bannedServerUser = ServerUser
.builder() .builder()
.serverId(event.getGuild().getIdLong()) .serverId(event.getGuild().getIdLong())
@@ -67,7 +67,7 @@ public class AsyncUserBannedListenerBean extends ListenerAdapter {
.serverId(event.getGuild().getIdLong()) .serverId(event.getGuild().getIdLong())
.userId(event.getEntry().getUserIdLong()) .userId(event.getEntry().getUserIdLong())
.build(); .build();
return UserBannedModel return UserBannedListenerModel
.builder() .builder()
.bannedServerUser(bannedServerUser) .bannedServerUser(bannedServerUser)
.banningUser(banningUser) .banningUser(banningUser)

View File

@@ -2,7 +2,7 @@ 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.UserUnBannedModel; import dev.sheldan.abstracto.core.models.listener.UserUnBannedListenerModel;
import dev.sheldan.abstracto.core.service.UserService; import dev.sheldan.abstracto.core.service.UserService;
import dev.sheldan.abstracto.core.utils.CompletableFutureMap; import dev.sheldan.abstracto.core.utils.CompletableFutureMap;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -44,18 +44,18 @@ public class AsyncUserUnBannedListenerBean extends ListenerAdapter {
longUserCompletableFutureMap.getMainFuture().thenAccept(avoid -> { longUserCompletableFutureMap.getMainFuture().thenAccept(avoid -> {
User unBannedUser = longUserCompletableFutureMap.getElement(event.getEntry().getTargetIdLong()); User unBannedUser = longUserCompletableFutureMap.getElement(event.getEntry().getTargetIdLong());
User unBanningUser = longUserCompletableFutureMap.getElement(event.getEntry().getUserIdLong()); User unBanningUser = longUserCompletableFutureMap.getElement(event.getEntry().getUserIdLong());
UserUnBannedModel model = getModel(event, unBannedUser, unBanningUser); UserUnBannedListenerModel model = getModel(event, unBannedUser, unBanningUser);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor)); listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor));
}).exceptionally(throwable -> { }).exceptionally(throwable -> {
log.warn("Failed to fetch users {} or {} for unbanned event.", event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong(), throwable); log.warn("Failed to fetch users {} or {} for unbanned event.", event.getEntry().getTargetIdLong(), event.getEntry().getUserIdLong(), throwable);
UserUnBannedModel model = getModel(event, null, null); UserUnBannedListenerModel model = getModel(event, null, null);
listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor)); listenerList.forEach(leaveListener -> listenerService.executeFeatureAwareListener(leaveListener, model, leaveListenerExecutor));
return null; return null;
}); });
} }
} }
private UserUnBannedModel getModel(GuildAuditLogEntryCreateEvent event, User unBannedUser, User unBanningUser) { private UserUnBannedListenerModel getModel(GuildAuditLogEntryCreateEvent event, User unBannedUser, User unBanningUser) {
ServerUser unBannedServerUser = ServerUser ServerUser unBannedServerUser = ServerUser
.builder() .builder()
.serverId(event.getGuild().getIdLong()) .serverId(event.getGuild().getIdLong())
@@ -66,7 +66,7 @@ public class AsyncUserUnBannedListenerBean extends ListenerAdapter {
.serverId(event.getGuild().getIdLong()) .serverId(event.getGuild().getIdLong())
.userId(event.getEntry().getUserIdLong()) .userId(event.getEntry().getUserIdLong())
.build(); .build();
return UserUnBannedModel return UserUnBannedListenerModel
.builder() .builder()
.unBannedServerUser(unBannedServerUser) .unBannedServerUser(unBannedServerUser)
.unBanningUser(unBanningUser) .unBanningUser(unBanningUser)

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
import dev.sheldan.abstracto.core.models.listener.MemberKickedModel;
public interface AsyncMemberKickedListener extends FeatureAwareListener<MemberKickedModel, DefaultListenerResult> {
}

View File

@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult; import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.FeatureAwareListener; import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
import dev.sheldan.abstracto.core.models.listener.UserBannedModel; import dev.sheldan.abstracto.core.models.listener.UserBannedListenerModel;
public interface AsyncUserBannedListener extends FeatureAwareListener<UserBannedModel, DefaultListenerResult> { public interface AsyncUserBannedListener extends FeatureAwareListener<UserBannedListenerModel, DefaultListenerResult> {
} }

View File

@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult; import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.FeatureAwareListener; import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
import dev.sheldan.abstracto.core.models.listener.UserUnBannedModel; import dev.sheldan.abstracto.core.models.listener.UserUnBannedListenerModel;
public interface AsyncUserUnBannedListener extends FeatureAwareListener<UserUnBannedModel, DefaultListenerResult> { public interface AsyncUserUnBannedListener extends FeatureAwareListener<UserUnBannedListenerModel, DefaultListenerResult> {
} }

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.core.models.listener;
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
import dev.sheldan.abstracto.core.models.ServerUser;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
@Getter
@Setter
@Builder
public class MemberKickedModel implements FeatureAwareListenerModel {
private ServerUser kickedServerUser;
private ServerUser kickingServerUser;
private Guild guild;
private String reason;
private Long responsibleUserId;
private User kickedUser;
private User kickingUser;
@Override
public Long getServerId() {
return guild.getIdLong();
}
}

View File

@@ -7,7 +7,6 @@ import lombok.Getter;
import lombok.Setter; 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 java.time.OffsetDateTime; import java.time.OffsetDateTime;
@@ -15,14 +14,15 @@ import java.time.OffsetDateTime;
@Setter @Setter
@Builder @Builder
public class MemberTimeoutUpdatedModel implements FeatureAwareListenerModel { public class MemberTimeoutUpdatedModel implements FeatureAwareListenerModel {
private ServerUser timeoutUser; private ServerUser mutedUser;
private User user; private ServerUser mutingUser;
private Guild guild; private Guild guild;
private String reason; private String reason;
private Long responsibleUserId; private Long responsibleUserId;
private OffsetDateTime oldTimeout; private OffsetDateTime oldTimeout;
private OffsetDateTime newTimeout; private OffsetDateTime newTimeout;
private Member member; private Member mutedMember;
private Member mutingMember;
@Override @Override
public Long getServerId() { public Long getServerId() {
return guild.getIdLong(); return guild.getIdLong();

View File

@@ -11,7 +11,7 @@ import net.dv8tion.jda.api.entities.User;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class UserBannedModel implements FeatureAwareListenerModel { public class UserBannedListenerModel implements FeatureAwareListenerModel {
private ServerUser bannedServerUser; private ServerUser bannedServerUser;
private ServerUser banningServerUser; private ServerUser banningServerUser;
private User bannedUser; private User bannedUser;

View File

@@ -11,7 +11,7 @@ import net.dv8tion.jda.api.entities.User;
@Getter @Getter
@Setter @Setter
@Builder @Builder
public class UserUnBannedModel implements FeatureAwareListenerModel { public class UserUnBannedListenerModel implements FeatureAwareListenerModel {
private ServerUser unBannedServerUser; private ServerUser unBannedServerUser;
private ServerUser unBanningServerUser; private ServerUser unBanningServerUser;
private User unBannedUser; private User unBannedUser;

View File

@@ -15,6 +15,7 @@ public class MemberDisplay {
private String memberMention; private String memberMention;
private String name; private String name;
private Long userId; private Long userId;
private String discriminator;
private Long serverId; private Long serverId;
public static MemberDisplay fromMember(Member member) { public static MemberDisplay fromMember(Member member) {
@@ -22,6 +23,7 @@ public class MemberDisplay {
.builder() .builder()
.memberMention(member.getAsMention()) .memberMention(member.getAsMention())
.name(member.getEffectiveName()) .name(member.getEffectiveName())
.discriminator(member.getUser().getDiscriminator())
.serverId(member.getGuild().getIdLong()) .serverId(member.getGuild().getIdLong())
.userId(member.getIdLong()) .userId(member.getIdLong())
.build(); .build();