mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-25 20:04:01 +00:00
added undo logic to mod mail logging
added some more logging when closing the mod mail thread
This commit is contained in:
@@ -11,6 +11,7 @@ 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.UserInServerManagementService;
|
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||||
import dev.sheldan.abstracto.core.service.management.UserInServerService;
|
import dev.sheldan.abstracto.core.service.management.UserInServerService;
|
||||||
|
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||||
import dev.sheldan.abstracto.modmail.config.ModMailFeature;
|
import dev.sheldan.abstracto.modmail.config.ModMailFeature;
|
||||||
import dev.sheldan.abstracto.modmail.models.database.*;
|
import dev.sheldan.abstracto.modmail.models.database.*;
|
||||||
import dev.sheldan.abstracto.modmail.models.dto.ServerChoice;
|
import dev.sheldan.abstracto.modmail.models.dto.ServerChoice;
|
||||||
@@ -107,7 +108,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
|
|
||||||
textChannel.thenAccept(channel -> {
|
textChannel.thenAccept(channel -> {
|
||||||
List<UndoActionInstance> undoActions = new ArrayList<>();
|
List<UndoActionInstance> undoActions = new ArrayList<>();
|
||||||
undoActions.add(UndoActionInstance.getChannelDeleteAction(channel.getIdLong(), aUserInAServer.getAUserInAServer().getServerReference().getId()));
|
undoActions.add(UndoActionInstance.getChannelDeleteAction(aUserInAServer.getAUserInAServer().getServerReference().getId(), channel.getIdLong()));
|
||||||
self.performModMailThreadSetup(aUserInAServer, channel, userInitiated, undoActions);
|
self.performModMailThreadSetup(aUserInAServer, channel, userInitiated, undoActions);
|
||||||
}).exceptionally(throwable -> {
|
}).exceptionally(throwable -> {
|
||||||
log.error("Failed to create mod mail thread", throwable);
|
log.error("Failed to create mod mail thread", throwable);
|
||||||
@@ -331,8 +332,10 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note, Boolean notifyUser) {
|
public synchronized void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note, Boolean notifyUser) {
|
||||||
|
log.info("Starting closing procedure for thread {}", modMailThread.getId());
|
||||||
List<ModMailMessage> modMailMessages = modMailThread.getMessages();
|
List<ModMailMessage> modMailMessages = modMailThread.getMessages();
|
||||||
List<CompletableFuture<Message>> messages = modMailMessageService.loadModMailMessages(modMailMessages);
|
List<CompletableFuture<Message>> messages = modMailMessageService.loadModMailMessages(modMailMessages);
|
||||||
|
log.trace("Loading {} mod mail thread messages.", messages.size());
|
||||||
Long modMailThreadId = modMailThread.getId();
|
Long modMailThreadId = modMailThread.getId();
|
||||||
for (int i = 0; i < messages.size(); i++) {
|
for (int i = 0; i < messages.size(); i++) {
|
||||||
CompletableFuture<Message> messageCompletableFuture = messages.get(i);
|
CompletableFuture<Message> messageCompletableFuture = messages.get(i);
|
||||||
@@ -343,13 +346,25 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
CompletableFuture.allOf(messages.toArray(new CompletableFuture[0])).whenComplete((avoid, throwable) -> {
|
CompletableFuture.allOf(messages.toArray(new CompletableFuture[0])).whenComplete((avoid, throwable) -> {
|
||||||
|
log.trace("Loaded {} mod mail thread messages", messages.size());
|
||||||
if(throwable != null) {
|
if(throwable != null) {
|
||||||
log.warn("Failed to load some mod mail messages for mod mail thread {}. Still trying to post the ones we got.", modMailThreadId, throwable);
|
log.warn("Failed to load some mod mail messages for mod mail thread {}. Still trying to post the ones we got.", modMailThreadId, throwable);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
self.logModMailThread(modMailThreadId, messages, note).thenRun(() -> {
|
List<UndoActionInstance> undoActions = new ArrayList<>();
|
||||||
self.afterSuccessfulLog(modMailThreadId, feedBack, notifyUser);
|
CompletableFutureList<Message> list = self.logModMailThread(modMailThreadId, messages, note);
|
||||||
}).exceptionally(innerThrowable -> {
|
list.getMainFuture().thenRun(() -> {
|
||||||
|
list.getFutures().forEach(messageCompletableFuture -> {
|
||||||
|
try {
|
||||||
|
Message message = messageCompletableFuture.get();
|
||||||
|
undoActions.add(UndoActionInstance.getMessageDeleteAction(message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong()));
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
log.error("Failed to post logging messages.", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
self.afterSuccessfulLog(modMailThreadId, feedBack, notifyUser, undoActions);
|
||||||
|
});
|
||||||
|
list.getMainFuture().exceptionally(innerThrowable -> {
|
||||||
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, innerThrowable);
|
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, innerThrowable);
|
||||||
log.error("Failed to log messages for mod mail thread {}.", modMailThreadId, innerThrowable);
|
log.error("Failed to log messages for mod mail thread {}.", modMailThreadId, innerThrowable);
|
||||||
return null;
|
return null;
|
||||||
@@ -367,44 +382,64 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void afterSuccessfulLog(Long modMailThreadId, MessageChannel feedBack, Boolean notifyUser) {
|
public void afterSuccessfulLog(Long modMailThreadId, MessageChannel feedBack, Boolean notifyUser, List<UndoActionInstance> undoActions) {
|
||||||
|
log.trace("Mod mail logging for thread {} has completed. Starting post logging activities.", modMailThreadId);
|
||||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
||||||
User user = botService.getMemberInServer(modMailThread.getUser()).getUser();
|
User user = botService.getMemberInServer(modMailThread.getUser()).getUser();
|
||||||
user.openPrivateChannel().queue(privateChannel -> {
|
user.openPrivateChannel().queue(privateChannel -> {
|
||||||
try {
|
try {
|
||||||
List<CompletableFuture<Message>> messageFutures = new ArrayList<>();
|
List<CompletableFuture<Message>> messageFutures = new ArrayList<>();
|
||||||
if(notifyUser){
|
if(notifyUser){
|
||||||
|
log.trace("Notifying user {}", user.getIdLong());
|
||||||
messageFutures.addAll(channelService.sendTemplateInChannel("modmail_closing_user_message", new Object(), privateChannel));
|
messageFutures.addAll(channelService.sendTemplateInChannel("modmail_closing_user_message", new Object(), privateChannel));
|
||||||
} else {
|
} else {
|
||||||
|
log.trace("*Not* notifying user {}", user.getIdLong());
|
||||||
messageFutures.add(CompletableFuture.completedFuture(null));
|
messageFutures.add(CompletableFuture.completedFuture(null));
|
||||||
}
|
}
|
||||||
CompletableFuture.allOf(messageFutures.toArray(new CompletableFuture[0])).whenComplete((result, throwable) -> {
|
CompletableFuture.allOf(messageFutures.toArray(new CompletableFuture[0])).whenComplete((result, throwable) -> {
|
||||||
if(throwable != null) {
|
if(throwable != null) {
|
||||||
log.warn("Failed to send closing message to user {} after closing mod mail thread {}", user.getIdLong(), modMailThread.getId(), throwable);
|
log.warn("Failed to send closing message to user {} after closing mod mail thread {}", user.getIdLong(), modMailThread.getId(), throwable);
|
||||||
}
|
}
|
||||||
try {
|
self.deleteChannelAndClose(modMailThreadId, feedBack, undoActions);
|
||||||
channelService.deleteTextChannel(modMailThread.getChannel()).thenRun(() -> {
|
|
||||||
self.closeModMailThreadInDb(modMailThreadId);
|
|
||||||
}).exceptionally(throwable2 -> {
|
|
||||||
log.error("Failed to delete text channel containing mod mail thread {}", modMailThread.getId(), throwable2);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
} catch (InsufficientPermissionException ex){
|
|
||||||
log.error("Failed to delete text channel containing mod mail thread {}", modMailThread.getId(), ex);
|
|
||||||
sendModMailFailure("modmail_exception_cannot_delete_channel", modMailThread.getUser(), modMailThreadId, feedBack, ex);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
log.error("Failed to delete text channel containing mod mail thread {}", modMailThread.getId(), ex);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to render closing user message", e);
|
log.error("Failed to render closing user message", e);
|
||||||
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, e);
|
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, e);
|
||||||
}
|
}
|
||||||
}, throwable -> log.error("Failed to load private channel with user {}", user.getIdLong(), throwable));
|
}, throwable -> {
|
||||||
|
log.error("Failed to load private channel with user {}", user.getIdLong(), throwable);
|
||||||
|
undoActionService.performActions(undoActions);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public CompletableFuture<Void> logModMailThread(Long modMailThreadId, List<CompletableFuture<Message>> messages, String note) {
|
public void deleteChannelAndClose(Long modMailThreadId, MessageChannel feedBack, List<UndoActionInstance> undoActions) {
|
||||||
|
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
||||||
|
try {
|
||||||
|
channelService.deleteTextChannel(modMailThread.getChannel()).thenRun(() -> {
|
||||||
|
try {
|
||||||
|
self.closeModMailThreadInDb(modMailThreadId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
undoActionService.performActions(undoActions);
|
||||||
|
}
|
||||||
|
}).exceptionally(throwable2 -> {
|
||||||
|
undoActionService.performActions(undoActions);
|
||||||
|
log.error("Failed to delete text channel containing mod mail thread {}", modMailThread.getId(), throwable2);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
} catch (InsufficientPermissionException ex) {
|
||||||
|
log.error("Failed to delete text channel containing mod mail thread {}", modMailThreadId, ex);
|
||||||
|
undoActionService.performActions(undoActions);
|
||||||
|
sendModMailFailure("modmail_exception_cannot_delete_channel", modMailThread.getUser(), modMailThreadId, feedBack, ex);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
log.error("Failed to delete text channel containing mod mail thread {}", modMailThreadId, ex);
|
||||||
|
undoActionService.performActions(undoActions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public CompletableFutureList<Message> logModMailThread(Long modMailThreadId, List<CompletableFuture<Message>> messages, String note) {
|
||||||
|
log.info("Logging mod mail thread {}.", modMailThreadId);
|
||||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
||||||
List<ModMailLoggedMessage> loggedMessages = new ArrayList<>();
|
List<ModMailLoggedMessage> loggedMessages = new ArrayList<>();
|
||||||
messages.forEach(future -> {
|
messages.forEach(future -> {
|
||||||
@@ -437,17 +472,23 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
|||||||
.closedThread(modMailThread)
|
.closedThread(modMailThread)
|
||||||
.note(note)
|
.note(note)
|
||||||
.build();
|
.build();
|
||||||
|
log.trace("Sending close header and individual mod mail messages to mod mail log target.");
|
||||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_close_header", headerModel);
|
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_close_header", headerModel);
|
||||||
List<CompletableFuture<Message>> closeHeaderFutures = postTargetService.sendEmbedInPostTarget(messageToSend, MODMAIL_LOG_POSTTARGET, modMailThread.getServer().getId());
|
List<CompletableFuture<Message>> closeHeaderFutures = postTargetService.sendEmbedInPostTarget(messageToSend, MODMAIL_LOG_POSTTARGET, modMailThread.getServer().getId());
|
||||||
completableFutures.addAll(closeHeaderFutures);
|
completableFutures.addAll(closeHeaderFutures);
|
||||||
completableFutures.addAll(self.sendMessagesToPostTarget(modMailThread, loggedMessages));
|
completableFutures.addAll(self.sendMessagesToPostTarget(modMailThread, loggedMessages));
|
||||||
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
|
CompletableFuture<Void> voidCompletableFuture = CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
|
||||||
|
return CompletableFutureList
|
||||||
|
.<Message>builder()
|
||||||
|
.mainFuture(voidCompletableFuture)
|
||||||
|
.futures(completableFutures)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void closeModMailThreadInDb(Long modMailThreadId) {
|
public void closeModMailThreadInDb(Long modMailThreadId) {
|
||||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
||||||
log.info("Setting thread {} to closed.", modMailThread.getId());
|
log.info("Setting thread {} to closed in db.", modMailThread.getId());
|
||||||
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.CLOSED);
|
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.CLOSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,13 +23,21 @@ public class UndoActionServiceBean implements UndoActionService {
|
|||||||
public void performActions(List<UndoActionInstance> actionsToPerform) {
|
public void performActions(List<UndoActionInstance> actionsToPerform) {
|
||||||
actionsToPerform.forEach(undoActionInstance -> {
|
actionsToPerform.forEach(undoActionInstance -> {
|
||||||
UndoAction action = undoActionInstance.getAction();
|
UndoAction action = undoActionInstance.getAction();
|
||||||
|
List<Long> ids = undoActionInstance.getIds();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case DELETE_CHANNEL:
|
case DELETE_CHANNEL:
|
||||||
if(undoActionInstance.getIds().size() != 2) {
|
if(ids.size() != 2) {
|
||||||
throw new UndoActionException("Not the correct amount of ides provided for the channel deletion undo action");
|
log.error("Not the correct amount of ids provided for the channel deletion undo action.");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
deleteChannel(undoActionInstance.getIds().get(0), undoActionInstance.getIds().get(1));
|
deleteChannel(ids.get(0), ids.get(1));
|
||||||
break;
|
break;
|
||||||
|
case DELETE_MESSAGE:
|
||||||
|
if(ids.size() != 3) {
|
||||||
|
log.error("Not the correct amount of ids provided for the message deletion undo action.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
botService.deleteMessage(ids.get(0), ids.get(1), ids.get(2));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,11 +14,19 @@ public class UndoActionInstance {
|
|||||||
private List<Long> ids;
|
private List<Long> ids;
|
||||||
private UndoAction action;
|
private UndoAction action;
|
||||||
|
|
||||||
public static UndoActionInstance getChannelDeleteAction(Long channelId, Long serverId) {
|
public static UndoActionInstance getChannelDeleteAction(Long serverId, Long channelId) {
|
||||||
return UndoActionInstance
|
return UndoActionInstance
|
||||||
.builder()
|
.builder()
|
||||||
.action(UndoAction.DELETE_CHANNEL)
|
.action(UndoAction.DELETE_CHANNEL)
|
||||||
.ids(Arrays.asList(serverId, channelId))
|
.ids(Arrays.asList(serverId, channelId))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static UndoActionInstance getMessageDeleteAction(Long serverId, Long channelId, Long messageId) {
|
||||||
|
return UndoActionInstance
|
||||||
|
.builder()
|
||||||
|
.action(UndoAction.DELETE_MESSAGE)
|
||||||
|
.ids(Arrays.asList(serverId, channelId, messageId))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package dev.sheldan.abstracto.core.utils;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class CompletableFutureList<T> {
|
||||||
|
private CompletableFuture<Void> mainFuture;
|
||||||
|
private List<CompletableFuture<T>> futures;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user