added closesilently command for modmail

largely refactored modmail future handling and error handling in case:
no permission, unable to contact user
fixed help command template
This commit is contained in:
Sheldan
2020-05-08 00:20:20 +02:00
parent 95733c9b98
commit c03788a065
18 changed files with 138 additions and 26 deletions

View File

@@ -43,7 +43,7 @@ public class Close extends AbstractConditionableCommand {
List<Object> parameters = commandContext.getParameters().getParameters();
String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate("modmail_close_default_note", new Object());
ModMailThread thread = modMailThreadManagementService.getByChannel(commandContext.getUserInitiatedContext().getChannel());
modMailThreadService.closeModMailThread(thread, commandContext.getChannel(), note);
modMailThreadService.closeModMailThread(thread, commandContext.getChannel(), note, true);
return CommandResult.fromSuccess();
}

View File

@@ -3,14 +3,21 @@ package dev.sheldan.abstracto.modmail.commands;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.modmail.commands.condition.RequiresModMailCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import dev.sheldan.abstracto.templating.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
@@ -19,14 +26,36 @@ public class CloseSilently extends AbstractConditionableCommand {
@Autowired
private RequiresModMailCondition requiresModMailCondition;
@Autowired
private ModMailThreadManagementService modMailThreadManagementService;
@Autowired
private ModMailThreadService modMailThreadService;
@Autowired
private TemplateService templateService;
@Override
public CommandResult execute(CommandContext commandContext) {
return null;
List<Object> parameters = commandContext.getParameters().getParameters();
String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate("modmail_close_default_note", new Object());
ModMailThread thread = modMailThreadManagementService.getByChannel(commandContext.getUserInitiatedContext().getChannel());
modMailThreadService.closeModMailThread(thread, commandContext.getChannel(), note, false);
return CommandResult.fromSuccess();
}
@Override
public CommandConfiguration getConfiguration() {
return null;
Parameter note = Parameter.builder().name("note").type(String.class).remainder(true).optional(true).build();
List<Parameter> parameters = Arrays.asList(note);
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("closeSilently")
.module(ModMailModuleInterface.MODMAIL)
.parameters(parameters)
.help(helpInfo)
.templated(true)
.causesReaction(true)
.build();
}
@Override

View File

@@ -21,6 +21,7 @@ import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -250,7 +251,9 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
}
}
private void sendModMailFailure(String template, AUserInAServer aUserInAServer, ModMailThread modMailThread, MessageChannel channel, Throwable throwable) {
@Transactional
public void sendModMailFailure(String template, AUserInAServer aUserInAServer, Long modMailTreadId, MessageChannel channel, Throwable throwable) {
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailTreadId);
try {
FullUser fullUser = FullUser
.builder()
@@ -270,38 +273,81 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
}
@Override
public void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note) {
public void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note, Boolean notifyUser) {
List<ModMailMessage> modMailMessages = modMailThread.getMessages();
List<CompletableFuture<Message>> messages = modMailMessageService.loadModMailMessages(modMailMessages);
Long modMailThreadId = modMailThread.getId();
for (int i = 0; i < messages.size(); i++) {
CompletableFuture<Message> messageCompletableFuture = messages.get(i);
Long messageId = modMailMessages.get(i).getMessageId();
messageCompletableFuture.exceptionally(throwable -> {
log.warn("Failed to load message {} in mod mail thread {}", messageId, modMailThread.getId());
log.warn("Failed to load message {} in mod mail thread {}", messageId, modMailThreadId);
return null;
});
}
CompletableFuture.allOf(messages.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
self.logModMailThread(modMailThread, messages, note, modMailMessages);
}).exceptionally(throwable -> {
log.warn("Failed to load some mod mail messages for mod mail thread {}. Still trying to post the ones we got.", modMailThread.getId(), throwable);
self.logModMailThread(modMailThread, messages, note, modMailMessages);
return null;
CompletableFuture.allOf(messages.toArray(new CompletableFuture[0])).whenComplete((avoid, throwable) -> {
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);
}
self.logModMailThread(modMailThreadId, messages, note).thenRun(() -> {
self.afterSuccessfulLog(modMailThreadId, feedBack, notifyUser);
}).exceptionally(innerThrowable -> {
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, innerThrowable);
log.error("Failed to log messages for mod mail thread {}.", modMailThreadId, innerThrowable);
return null;
});
});
}
@Transactional
public void logModMailThread(ModMailThread modMailThread, List<CompletableFuture<Message>> messages, String note, List<ModMailMessage> modMailMessages) {
public void afterSuccessfulLog(Long modMailThreadId, MessageChannel feedBack, Boolean notifyUser) {
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
User user = botService.getMemberInServer(modMailThread.getUser()).getUser();
user.openPrivateChannel().queue(privateChannel -> {
try {
List<CompletableFuture<Message>> messageFutures = new ArrayList<>();
if(notifyUser){
messageFutures.addAll(channelService.sendTemplateInChannel("modmail_closing_user_message", new Object(), privateChannel));
} else {
messageFutures.add(CompletableFuture.completedFuture(null));
}
CompletableFuture.allOf(messageFutures.toArray(new CompletableFuture[0])).whenComplete((result, throwable) -> {
if(throwable != null) {
log.warn("Failed to send closing message to user {} after closing mod mail thread {}", user.getIdLong(), modMailThread.getId(), throwable);
}
try {
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) {
log.error("Failed to render closing user message", e);
sendModMailFailure("modmail_exception_generic", modMailThread.getUser(), modMailThreadId, feedBack, e);
}
}, throwable -> log.error("Failed to load private channel with user {}", user.getIdLong(), throwable));
}
@Transactional
public CompletableFuture<Void> logModMailThread(Long modMailThreadId, List<CompletableFuture<Message>> messages, String note) {
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
List<ModMailLoggedMessage> loggedMessages = new ArrayList<>();
messages.forEach(future -> {
try {
if(!future.isCompletedExceptionally()) {
Message loadedMessage = future.get();
if(loadedMessage != null) {
ModMailMessage modmailMessage = modMailMessages
ModMailMessage modmailMessage = modMailThread.getMessages()
.stream()
.filter(modMailMessage -> modMailMessage.getMessageId().equals(loadedMessage.getIdLong()))
.findFirst().get();
@@ -330,19 +376,16 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
List<CompletableFuture<Message>> closeHeaderFutures = postTargetService.sendEmbedInPostTarget(messageToSend, MODMAIL_LOG_POSTTARGET, modMailThread.getServer().getId());
completableFutures.addAll(closeHeaderFutures);
completableFutures.addAll(self.sendMessagesToPostTarget(modMailThread, loggedMessages));
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
channelService.deleteTextChannel(modMailThread.getChannel()).thenAccept(o -> {
self.closeModMailThreadInDb(modMailThread);
});
});
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]));
}
@Transactional
public void closeModMailThreadInDb(ModMailThread modMailThread) {
public void closeModMailThreadInDb(Long modMailThreadId) {
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
log.info("Setting thread {} to closed.", modMailThread.getId());
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.CLOSED);
}
@Transactional
public List<CompletableFuture<Message>> sendMessagesToPostTarget(ModMailThread modMailThread, List<ModMailLoggedMessage> loadedMessages) {
List<CompletableFuture<Message>> messageFutures = new ArrayList<>();
loadedMessages.forEach(message -> {
@@ -391,7 +434,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.MOD_REPLIED);
}).exceptionally(throwable -> {
log.error("Failed to send message to user {}", modMailThread.getUser().getUserReference().getId());
sendModMailFailure("modmail_exception_cannot_message_user", modMailThread.getUser(), modMailThread, feedBack, throwable);
sendModMailFailure("modmail_exception_cannot_message_user", modMailThread.getUser(), modMailThread.getId(), feedBack, throwable);
return null;
});
}

View File

@@ -28,6 +28,11 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
return getByChannel(channel);
}
@Override
public ModMailThread getById(Long modMailThreadId) {
return modMailThreadRepository.getOne(modMailThreadId);
}
@Override
public ModMailThread getByChannel(AChannel channel) {
return modMailThreadRepository.findByChannel(channel);

View File

@@ -0,0 +1,12 @@
{
"author": {
"name": "${user.member.effectiveName}",
"avatar": "${user.member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "<#include "close_failed_to_delete_text_channel">"
}

View File

@@ -0,0 +1,12 @@
{
"author": {
"name": "${user.member.effectiveName}",
"avatar": "${user.member.user.effectiveAvatarUrl}"
},
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "<#include "modmail_generic_error">"
}

View File

@@ -0,0 +1,8 @@
{
"color" : {
"r": 200,
"g": 0,
"b": 255
},
"description": "<#include "modmail_closing_user_message_description">"
}

View File

@@ -17,5 +17,5 @@ public interface ModMailThreadService {
void createModMailPrompt(AUser user, MessageChannel messageChannel);
void relayMessageToModMailThread(ModMailThread modMailThread, Message message);
void relayMessageToDm(ModMailThread modMailThread, String text, Message message, Boolean anonymous, MessageChannel feedBack);
void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note);
void closeModMailThread(ModMailThread modMailThread, MessageChannel feedBack, String note, Boolean notifyUser);
}

View File

@@ -10,6 +10,7 @@ import java.util.List;
public interface ModMailThreadManagementService {
ModMailThread getByChannelId(Long channelId);
ModMailThread getById(Long modMailThreadId);
ModMailThread getByChannel(AChannel channel);
List<ModMailThread> getThreadByUserAndState(AUserInAServer userInAServer, ModMailThreadState state);
ModMailThread getOpenModmailThreadForUser(AUserInAServer userInAServer);

View File

@@ -21,9 +21,8 @@
<#if command.aliases?? && command.aliases?size gt 0>
<#include "help_command_embed_command_aliases">: `${command.aliases?join("`, `")}`
</#if>
<#include "help_command_embed_command_description">:
<#if restricted?? && restricted>
<#include "help_command_embed_command_description"><#if allowedRoles??> <#list allowedRoles as allowedRole> ${allowedRole.asMention}<#sep><#include "help_command_embed_or"><#else><#include "help_command_embed_command_executable_by_nobody"></#list> </#if>
<#include "help_command_embed_command_executable_by">:<#if allowedRoles??> <#list allowedRoles as allowedRole> ${allowedRole.asMention}<#sep><#include "help_command_embed_or"><#else><#include "help_command_embed_command_executable_by_nobody"></#list> </#if>
<#if immuneRoles?? ><#include "help_command_embed_command_immune">: <#list immuneRoles as immuneRole> ${immuneRole.asMention}<#sep><#include "help_command_embed_or"><#else>None</#list> </#if>
<#else>
<#include "help_command_embed_command_not_restricted">

View File

@@ -0,0 +1 @@
Failed to delete text channel containing mod mail thread. The bot does not have permissions to do so.

View File

@@ -0,0 +1 @@
Mod mail thread has been closed. If you have any questions please do not hesitate to contact us again.

View File

@@ -0,0 +1 @@
Generic mod mail failure. Check the logs.