mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-15 20:16:34 +00:00
[AB-96] adding ability to edit/delete modmail messages via editing/deleting the original message causing the message,
adding featuremode to modmail to define whether or not there is a separate message posted to the mod mail thread, to see it easier, renaming modmail related tables to singular, adding some necessary methods (caching) to all entities
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package dev.sheldan.abstracto.modmail.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.listener.MessageDeletedListener;
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ModMailMessageDeletedListener implements MessageDeletedListener {
|
||||
|
||||
@Autowired
|
||||
private ModMailMessageManagementService modMailMessageManagementService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private ModMailMessageDeletedListener self;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore, AServerAChannelAUser authorUser, GuildChannelMember authorMember) {
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageBefore.getMessageId());
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
ModMailThread thread = modMailMessage.getThreadReference();
|
||||
Long dmMessageId = modMailMessage.getCreatedMessageInDM();
|
||||
boolean hasMessageInChannel = modMailMessage.getCreatedMessageInChannel() != null;
|
||||
Long channelMessage = modMailMessage.getCreatedMessageInChannel();
|
||||
Long channelId = thread.getChannel().getId();
|
||||
Long serverId = thread.getServer().getId();
|
||||
log.info("Deleting message for mod mail thread {} in channel {} in server {}.", thread.getId(), channelId, serverId);
|
||||
botService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId()).thenAccept(member -> {
|
||||
CompletableFuture<Void> dmDeletePromise = messageService.deleteMessageInChannelWithUser(member.getUser(), dmMessageId);
|
||||
CompletableFuture<Void> channelDeletePromise;
|
||||
if(hasMessageInChannel) {
|
||||
channelDeletePromise = messageService.deleteMessageInChannelInServer(serverId, channelId, channelMessage);
|
||||
} else {
|
||||
channelDeletePromise = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
CompletableFuture.allOf(dmDeletePromise, channelDeletePromise).thenAccept(unused ->
|
||||
self.removeMessageFromThread(messageBefore.getMessageId())
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void removeMessageFromThread(Long messageId) {
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageId);
|
||||
messageOptional.ifPresent(modMailMessage ->
|
||||
modMailMessageManagementService.deleteMessageFromThread(modMailMessage)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return ModMailFeatures.MOD_MAIL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.sheldan.abstracto.modmail.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.Parameters;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandService;
|
||||
import dev.sheldan.abstracto.core.config.FeatureEnum;
|
||||
import dev.sheldan.abstracto.core.listener.MessageTextUpdatedListener;
|
||||
import dev.sheldan.abstracto.core.models.FullUserInServer;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
|
||||
import dev.sheldan.abstracto.modmail.models.template.ModMailModeratorReplyModel;
|
||||
import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
|
||||
import dev.sheldan.abstracto.modmail.service.ModMailThreadServiceBean;
|
||||
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
|
||||
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.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ModMailMessageEditedListener implements MessageTextUpdatedListener {
|
||||
|
||||
public static final String DEFAULT_COMMAND_FOR_MODMAIL_EDIT = "reply";
|
||||
@Autowired
|
||||
private ModMailMessageManagementService modMailMessageManagementService;
|
||||
|
||||
@Autowired
|
||||
private CommandService commandService;
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ModMailMessageEditedListener self;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private CommandRegistry commandRegistry;
|
||||
|
||||
@Autowired
|
||||
private ModMailThreadService modMailThreadService;
|
||||
|
||||
@Override
|
||||
public void execute(CachedMessage messageBefore, Message messageAfter) {
|
||||
if(!modMailThreadService.isModMailThread(messageBefore.getChannelId())) {
|
||||
return;
|
||||
}
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageBefore.getMessageId());
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
log.info("Editing send message {} in channel {} in mod mail thread {} in server {}.", messageBefore.getMessageId(), messageBefore.getChannelId(), modMailMessage.getThreadReference().getId(), messageBefore.getServerId());
|
||||
String contentStripped = messageAfter.getContentRaw();
|
||||
String commandName = commandRegistry.getCommandName(contentStripped.substring(0, contentStripped.indexOf(" ")), messageBefore.getServerId());
|
||||
if(!commandService.doesCommandExist(commandName)) {
|
||||
commandName = DEFAULT_COMMAND_FOR_MODMAIL_EDIT;
|
||||
log.info("Edit did not contain the original command to retrieve the parameters for. Resulting to {}.", DEFAULT_COMMAND_FOR_MODMAIL_EDIT);
|
||||
}
|
||||
CompletableFuture<Parameters> parameterParseFuture = commandService.getParametersForCommand(commandName, messageAfter);
|
||||
CompletableFuture<Member> loadTargetUser = botService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId());
|
||||
CompletableFuture<Member> loadEditingUser = botService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getAuthor().getUserReference().getId());
|
||||
CompletableFuture.allOf(parameterParseFuture, loadTargetUser, loadEditingUser).thenAccept(unused ->
|
||||
self.updateMessageInThread(messageAfter, parameterParseFuture.join(), loadTargetUser.join(), loadEditingUser.join())
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateMessageInThread(Message messageAfter, Parameters parameters, Member targetMember, Member editingUser) {
|
||||
String newText = (String) parameters.getParameters().get(0);
|
||||
Optional<ModMailMessage> messageOptional = modMailMessageManagementService.getByMessageIdOptional(messageAfter.getIdLong());
|
||||
messageOptional.ifPresent(modMailMessage -> {
|
||||
FullUserInServer fullThreadUser = FullUserInServer
|
||||
.builder()
|
||||
.aUserInAServer(modMailMessage.getThreadReference().getUser())
|
||||
.member(targetMember)
|
||||
.build();
|
||||
ModMailModeratorReplyModel.ModMailModeratorReplyModelBuilder modMailModeratorReplyModelBuilder = ModMailModeratorReplyModel
|
||||
.builder()
|
||||
.text(newText)
|
||||
.modMailThread(modMailMessage.getThreadReference())
|
||||
.postedMessage(messageAfter)
|
||||
.anonymous(modMailMessage.getAnonymous())
|
||||
.threadUser(fullThreadUser);
|
||||
if(modMailMessage.getAnonymous()) {
|
||||
modMailModeratorReplyModelBuilder.moderator(botService.getBotInGuild(modMailMessage.getThreadReference().getServer()));
|
||||
} else {
|
||||
modMailModeratorReplyModelBuilder.moderator(editingUser);
|
||||
}
|
||||
ModMailModeratorReplyModel modMailUserReplyModel = modMailModeratorReplyModelBuilder.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(ModMailThreadServiceBean.MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY, modMailUserReplyModel);
|
||||
Long threadId = modMailMessage.getThreadReference().getId();
|
||||
long serverId = editingUser.getGuild().getIdLong();
|
||||
if(modMailMessage.getCreatedMessageInChannel() != null) {
|
||||
AChannel channel = modMailMessage.getThreadReference().getChannel();
|
||||
log.trace("Editing message {} in mod mail channel {} for thread {} in server {} as well.", modMailMessage.getCreatedMessageInChannel(), channel.getId(), threadId, serverId);
|
||||
channelService.editMessageInAChannel(messageToSend, channel, modMailMessage.getCreatedMessageInChannel());
|
||||
}
|
||||
log.trace("Editing message {} in DM channel with user {} for thread {} in server {}.", modMailMessage.getCreatedMessageInDM(), targetMember.getUser().getIdLong(), threadId, serverId);
|
||||
messageService.editMessageInDMChannel(targetMember.getUser(), messageToSend, modMailMessage.getCreatedMessageInDM());
|
||||
});
|
||||
|
||||
if(!messageOptional.isPresent()) {
|
||||
log.warn("Message {} of user {} in channel {} for server {} for thread about user {} could not be found in the mod mail messages when updating the text.",
|
||||
messageAfter.getIdLong(), editingUser.getIdLong(), messageAfter.getChannel().getIdLong(), messageAfter.getGuild().getIdLong(), targetMember.getIdLong());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureEnum getFeature() {
|
||||
return ModMailFeatures.MOD_MAIL;
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import org.springframework.stereotype.Repository;
|
||||
|
||||
import javax.persistence.QueryHint;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Repository to manage the stored {@link ModMailMessage} instances
|
||||
@@ -16,4 +17,7 @@ import java.util.List;
|
||||
public interface ModMailMessageRepository extends JpaRepository<ModMailMessage, Long> {
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<ModMailMessage> findByThreadReference(ModMailThread modMailThread);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
Optional<ModMailMessage> findByMessageId(Long messageId);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import java.util.Optional;
|
||||
public interface ModMailThreadRepository extends JpaRepository<ModMailThread, Long> {
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
ModMailThread findByChannel(AChannel channel);
|
||||
Optional<ModMailThread> findByChannel(AChannel channel);
|
||||
|
||||
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
|
||||
List<ModMailThread> findByUser(AUserInAServer aUserInAServer);
|
||||
|
||||
@@ -38,7 +38,6 @@ public class ModMailMessageServiceBean implements ModMailMessageService {
|
||||
modMailMessages.forEach(modMailMessage -> {
|
||||
ServerChannelMessageUser.ServerChannelMessageUserBuilder serverChannelMessageBuilder = ServerChannelMessageUser
|
||||
.builder()
|
||||
.messageId(modMailMessage.getMessageId())
|
||||
.userId(modMailMessage.getAuthor().getUserReference().getId())
|
||||
.serverId(thread.getServer().getId());
|
||||
// if its not from a private chat, we need to set channel ID in order to fetch the data
|
||||
@@ -46,6 +45,9 @@ public class ModMailMessageServiceBean implements ModMailMessageService {
|
||||
log.trace("Message {} was from DM.", modMailMessage.getMessageId());
|
||||
serverChannelMessageBuilder
|
||||
.channelId(modMailMessage.getThreadReference().getChannel().getId());
|
||||
serverChannelMessageBuilder.messageId(modMailMessage.getCreatedMessageInChannel());
|
||||
} else {
|
||||
serverChannelMessageBuilder.messageId(modMailMessage.getCreatedMessageInDM());
|
||||
}
|
||||
messageIds.add(serverChannelMessageBuilder.build());
|
||||
});
|
||||
|
||||
@@ -17,6 +17,7 @@ import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.modmail.config.*;
|
||||
import dev.sheldan.abstracto.modmail.exception.ModMailCategoryIdException;
|
||||
import dev.sheldan.abstracto.modmail.exception.ModMailThreadChannelNotFound;
|
||||
import dev.sheldan.abstracto.modmail.exception.ModMailThreadNotFoundException;
|
||||
import dev.sheldan.abstracto.modmail.models.dto.LoadedModmailThreadMessageList;
|
||||
import dev.sheldan.abstracto.modmail.models.database.*;
|
||||
@@ -57,6 +58,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
* The template key used for default mod mail exceptions
|
||||
*/
|
||||
public static final String MODMAIL_EXCEPTION_GENERIC_TEMPLATE = "modmail_exception_generic";
|
||||
public static final String MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY = "modmail_staff_message";
|
||||
|
||||
@Autowired
|
||||
private ModMailThreadManagementService modMailThreadManagementService;
|
||||
@@ -184,7 +186,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
ModMailThread thread = createThreadObject(channel, aUserInAServer);
|
||||
if(initialMessage != null) {
|
||||
log.trace("Adding initial message {} to modmail thread in channel {}.", initialMessage.getId(), channel.getId());
|
||||
modMailMessageManagementService.addMessageToThread(thread, sendMessage, aUserInAServer, false, false);
|
||||
modMailMessageManagementService.addMessageToThread(thread, null, sendMessage, initialMessage, aUserInAServer, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,22 +329,22 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Message> relayMessageToModMailThread(ModMailThread modMailThread, Message message, List<UndoActionInstance> undoActions) {
|
||||
public CompletableFuture<Message> relayMessageToModMailThread(ModMailThread modMailThread, Message messageFromUser, List<UndoActionInstance> undoActions) {
|
||||
Long serverId = modMailThread.getServer().getId();
|
||||
Long channelId = modMailThread.getChannel().getId();
|
||||
Long modmailThreadId = modMailThread.getId();
|
||||
log.trace("Relaying message {} to modmail thread {} for user {} to server {}.", message.getId(), modMailThread.getId(), message.getAuthor().getIdLong(), modMailThread.getServer().getId());
|
||||
return botService.getMemberInServerAsync(modMailThread.getServer().getId(), message.getAuthor().getIdLong()).thenCompose(member -> {
|
||||
log.trace("Relaying message {} to modmail thread {} for user {} to server {}.", messageFromUser.getId(), modMailThread.getId(), messageFromUser.getAuthor().getIdLong(), modMailThread.getServer().getId());
|
||||
return botService.getMemberInServerAsync(modMailThread.getServer().getId(), messageFromUser.getAuthor().getIdLong()).thenCompose(member -> {
|
||||
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(serverId, channelId);
|
||||
if(textChannelFromServer.isPresent()) {
|
||||
TextChannel textChannel = textChannelFromServer.get();
|
||||
return self.sendUserReply(textChannel, modmailThreadId, message, member, true);
|
||||
return self.sendUserReply(textChannel, modmailThreadId, messageFromUser, member, true);
|
||||
} else {
|
||||
log.warn("Closing modmail thread {}, because it seems the channel {} in server {} got deleted.", modmailThreadId, channelId, serverId);
|
||||
log.warn("Closing mod mail thread {}, because it seems the channel {} in server {} got deleted.", modmailThreadId, channelId, serverId);
|
||||
// in this case there was no text channel on the server associated with the mod mail thread
|
||||
// close the existing one, so the user can start a new one
|
||||
self.closeModMailThreadInDb(modmailThreadId);
|
||||
return message.getChannel().sendMessage(templateService.renderTemplate("modmail_failed_to_forward_message", new Object())).submit();
|
||||
return messageFromUser.getChannel().sendMessage(templateService.renderTemplate("modmail_failed_to_forward_message", new Object())).submit();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -354,12 +356,12 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
* side.
|
||||
* @param textChannel The {@link TextChannel} in which the {@link ModMailThread} is being handled
|
||||
* @param modMailThreadId The id of the modmail thread to which the received {@link Message} is a reply to, can be null, if it is null, its the initial message
|
||||
* @param message The received message from the user
|
||||
* @param messageFromUser The received message from the user
|
||||
* @param member The {@link Member} instance from the user the thread is about. It is used as author
|
||||
* @param modMailThreadExists Whether or not the modmail thread already exists and is persisted.
|
||||
* @return A {@link CompletableFuture} which resolves when the post processing of the message is completed (adding read notification, and storing messageIDs)
|
||||
*/
|
||||
public CompletableFuture<Message> sendUserReply(TextChannel textChannel, Long modMailThreadId, Message message, Member member, boolean modMailThreadExists) {
|
||||
public CompletableFuture<Message> sendUserReply(TextChannel textChannel, Long modMailThreadId, Message messageFromUser, Member member, boolean modMailThreadExists) {
|
||||
List<CompletableFuture<Member>> subscriberMemberFutures = new ArrayList<>();
|
||||
if(modMailThreadExists) {
|
||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
|
||||
@@ -378,7 +380,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
List<FullUserInServer> subscribers = new ArrayList<>();
|
||||
ModMailUserReplyModel modMailUserReplyModel = ModMailUserReplyModel
|
||||
.builder()
|
||||
.postedMessage(message)
|
||||
.postedMessage(messageFromUser)
|
||||
.member(member)
|
||||
.subscribers(subscribers)
|
||||
.build();
|
||||
@@ -387,11 +389,11 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
return CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]))
|
||||
.thenCompose(aVoid -> {
|
||||
log.trace("Adding read reaction to initial message for mod mail thread in channel {}.", textChannel.getGuild().getId());
|
||||
return messageService.addReactionToMessageWithFuture("readReaction", textChannel.getGuild().getIdLong(), message);
|
||||
return messageService.addReactionToMessageWithFuture("readReaction", textChannel.getGuild().getIdLong(), messageFromUser);
|
||||
})
|
||||
.thenApply(aVoid -> {
|
||||
if(modMailThreadExists) {
|
||||
self.postProcessSendMessages(textChannel, completableFutures.get(0).join());
|
||||
self.postProcessSendMessages(textChannel, completableFutures.get(0).join(), messageFromUser);
|
||||
}
|
||||
return completableFutures.get(0).join();
|
||||
});
|
||||
@@ -403,26 +405,28 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
/**
|
||||
* This message handles the post processing of the messages received by the user. This includes: saving the messageIDs
|
||||
* in the database, updating the state of the {@link ModMailThread} and adding the read reaction to the user message
|
||||
* @param message The actual {@link Message} instance received from the user.
|
||||
* @param textChannel The channel in which the message
|
||||
* @param messageInModMailThread The actual {@link Message} instance which was sent to the mod mail thread
|
||||
* @param messageFromUser The {@link Message} object which was sent from the user
|
||||
*/
|
||||
@Transactional
|
||||
public void postProcessSendMessages(TextChannel textChannel, Message message) {
|
||||
Optional<ModMailThread> modMailThreadOpt = modMailThreadManagementService.getByIdOptional(textChannel.getIdLong());
|
||||
public void postProcessSendMessages(TextChannel textChannel, Message messageInModMailThread, Message messageFromUser) {
|
||||
Optional<ModMailThread> modMailThreadOpt = modMailThreadManagementService.getByChannelIdOptional(textChannel.getIdLong());
|
||||
if(modMailThreadOpt.isPresent()) {
|
||||
ModMailThread modMailThread = modMailThreadOpt.get();
|
||||
log.trace("Adding message {} sent from user to modmail thread {} and setting status to {}.", message.getId(), modMailThread.getId(), ModMailThreadState.USER_REPLIED);
|
||||
modMailMessageManagementService.addMessageToThread(modMailThread, message, modMailThread.getUser(), false, false);
|
||||
log.trace("Adding created message {} based on messeage {} sent from user to modmail thread {} and setting status to {}.", messageInModMailThread.getId(), messageFromUser.getId(), modMailThread.getId(), ModMailThreadState.USER_REPLIED);
|
||||
modMailMessageManagementService.addMessageToThread(modMailThread, null, messageInModMailThread, messageFromUser, modMailThread.getUser(), false, false);
|
||||
// update the state of the thread
|
||||
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.USER_REPLIED);
|
||||
} else {
|
||||
throw new ModMailThreadNotFoundException(textChannel.getIdLong());
|
||||
throw new ModMailThreadChannelNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> relayMessageToDm(Long modmailThreadId, String text, Message message, boolean anonymous, MessageChannel feedBack, List<UndoActionInstance> undoActions, Member targetMember) {
|
||||
log.info("Relaying message {} to user {} in modmail thread {} on server {}.", message.getId(), targetMember.getId(), modmailThreadId, targetMember.getGuild().getId());
|
||||
AUserInAServer moderator = userInServerManagementService.loadUser(message.getMember());
|
||||
public CompletableFuture<Void> relayMessageToDm(Long modmailThreadId, String text, Message replyCommandMessage, boolean anonymous, MessageChannel feedBack, List<UndoActionInstance> undoActions, Member targetMember) {
|
||||
log.info("Relaying message {} to user {} in modmail thread {} on server {}.", replyCommandMessage.getId(), targetMember.getId(), modmailThreadId, targetMember.getGuild().getId());
|
||||
AUserInAServer moderator = userInServerManagementService.loadUser(replyCommandMessage.getMember());
|
||||
ModMailThread modMailThread = modMailThreadManagementService.getById(modmailThreadId);
|
||||
FullUserInServer fullThreadUser = FullUserInServer
|
||||
.builder()
|
||||
@@ -433,7 +437,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
.builder()
|
||||
.text(text)
|
||||
.modMailThread(modMailThread)
|
||||
.postedMessage(message)
|
||||
.postedMessage(replyCommandMessage)
|
||||
.anonymous(anonymous)
|
||||
.threadUser(fullThreadUser);
|
||||
if(anonymous) {
|
||||
@@ -445,9 +449,16 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
modMailModeratorReplyModelBuilder.moderator(moderatorMember);
|
||||
}
|
||||
ModMailModeratorReplyModel modMailUserReplyModel = modMailModeratorReplyModelBuilder.build();
|
||||
CompletableFuture<Message> future = messageService.sendEmbedToUserWithMessage(targetMember.getUser(), "modmail_staff_message", modMailUserReplyModel);
|
||||
return future.thenAccept(sendMessage ->
|
||||
self.saveSendMessagesAndUpdateState(modmailThreadId, anonymous, moderator, sendMessage)
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY, modMailUserReplyModel);
|
||||
CompletableFuture<Message> future = messageService.sendMessageToSendToUser(targetMember.getUser(), messageToSend);
|
||||
CompletableFuture<Message> sameThreadMessageFuture;
|
||||
if(featureModeService.featureModeActive(ModMailFeatures.MOD_MAIL, modMailThread.getServer(), ModMailMode.SEPARATE_MESSAGE)) {
|
||||
sameThreadMessageFuture = channelService.sendMessageToSendToAChannel(messageToSend, modMailThread.getChannel()).get(0);
|
||||
} else {
|
||||
sameThreadMessageFuture = CompletableFuture.completedFuture(null);
|
||||
}
|
||||
return CompletableFuture.allOf(future, sameThreadMessageFuture).thenAccept(avoid ->
|
||||
self.saveSendMessagesAndUpdateState(modmailThreadId, anonymous, moderator, future.join(), replyCommandMessage, sameThreadMessageFuture.join())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -481,6 +492,17 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModMailThread(AChannel channel) {
|
||||
return modMailThreadManagementService.getByChannelOptional(channel).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModMailThread(Long channelId) {
|
||||
AChannel channel = channelManagementService.loadChannel(channelId);
|
||||
return modMailThreadManagementService.getByChannelOptional(channel).isPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method takes the actively loaded futures, calls the method responsible for logging the messages, and calls the method
|
||||
* after the logging has been done.
|
||||
@@ -603,7 +625,13 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
log.info("Logging message {} in modmail thread {}.", loadedMessage.getId(), modMailThreadId);
|
||||
ModMailMessage modmailMessage = modMailThread.getMessages()
|
||||
.stream()
|
||||
.filter(modMailMessage -> modMailMessage.getMessageId().equals(loadedMessage.getIdLong()))
|
||||
.filter(modMailMessage -> {
|
||||
if(modMailMessage.getDmChannel()) {
|
||||
return modMailMessage.getCreatedMessageInDM().equals(loadedMessage.getIdLong());
|
||||
} else {
|
||||
return modMailMessage.getCreatedMessageInChannel().equals(loadedMessage.getIdLong());
|
||||
}
|
||||
})
|
||||
.findFirst().orElseThrow(() -> new AbstractoRunTimeException("Could not find desired message in list of messages in thread. This should not happen, as we just retrieved them from the same place."));
|
||||
Member author = futures.getMemberFuture().join();
|
||||
ModMailLoggedMessageModel modMailLoggedMessageModel =
|
||||
@@ -688,12 +716,12 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
|
||||
* @throws ModMailThreadNotFoundException in case the {@link ModMailThread} is not found by the ID
|
||||
*/
|
||||
@Transactional
|
||||
public void saveSendMessagesAndUpdateState(Long modMailThreadId, Boolean anonymous, AUserInAServer moderator, Message message) {
|
||||
public void saveSendMessagesAndUpdateState(Long modMailThreadId, Boolean anonymous, AUserInAServer moderator, Message createdMessageInDM, Message replyCommandMessage, Message modMailThreadMessage) {
|
||||
Optional<ModMailThread> modMailThreadOpt = modMailThreadManagementService.getByIdOptional(modMailThreadId);
|
||||
if(modMailThreadOpt.isPresent()) {
|
||||
ModMailThread modMailThread = modMailThreadOpt.get();
|
||||
log.trace("Adding (anonymous: {}) message {} of moderator to modmail thread {} and setting state to {}.", anonymous, message.getId(), modMailThreadId, ModMailThreadState.MOD_REPLIED);
|
||||
modMailMessageManagementService.addMessageToThread(modMailThread, message, moderator, anonymous, true);
|
||||
log.trace("Adding (anonymous: {}) message {} of moderator to modmail thread {} and setting state to {}.", anonymous, createdMessageInDM.getId(), modMailThreadId, ModMailThreadState.MOD_REPLIED);
|
||||
modMailMessageManagementService.addMessageToThread(modMailThread, createdMessageInDM, modMailThreadMessage, replyCommandMessage, moderator, anonymous, true);
|
||||
modMailThreadManagementService.setModMailThreadState(modMailThread, ModMailThreadState.MOD_REPLIED);
|
||||
} else {
|
||||
throw new ModMailThreadNotFoundException(modMailThreadId);
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
@@ -19,17 +20,21 @@ public class ModMailMessageManagementServiceBean implements ModMailMessageManage
|
||||
private ModMailMessageRepository modMailMessageRepository;
|
||||
|
||||
@Override
|
||||
public ModMailMessage addMessageToThread(ModMailThread modMailThread, Message message, AUserInAServer author, Boolean anonymous, Boolean dmChannel) {
|
||||
public ModMailMessage addMessageToThread(ModMailThread modMailThread, Message createdMessageInDM, Message createdMessageInChannel, Message userPostedMessage, AUserInAServer author, Boolean anonymous, Boolean dmChannel) {
|
||||
Long dmId = createdMessageInDM != null ? createdMessageInDM.getIdLong() : null;
|
||||
Long channelMessageId = createdMessageInChannel != null ? createdMessageInChannel.getIdLong() : null;
|
||||
ModMailMessage modMailMessage = ModMailMessage
|
||||
.builder()
|
||||
.author(author)
|
||||
.messageId(message.getIdLong())
|
||||
.messageId(userPostedMessage.getIdLong())
|
||||
.createdMessageInDM(dmId)
|
||||
.createdMessageInChannel(channelMessageId)
|
||||
.dmChannel(dmChannel)
|
||||
.threadReference(modMailThread)
|
||||
.anonymous(anonymous)
|
||||
.build();
|
||||
log.info("Storing modmail thread message {} to modmail thread {} of user {} in server {}.",
|
||||
message.getId(), modMailThread.getId(), author.getUserReference().getId(), author.getServerReference().getId());
|
||||
log.info("Storing created message in DM {} with created message in channel {} caused by message {} to modmail thread {} of user {} in server {}.",
|
||||
dmId, channelMessageId, userPostedMessage.getId(), modMailThread.getId(), author.getUserReference().getId(), author.getServerReference().getId());
|
||||
|
||||
modMailMessageRepository.save(modMailMessage);
|
||||
return modMailMessage;
|
||||
@@ -39,4 +44,14 @@ public class ModMailMessageManagementServiceBean implements ModMailMessageManage
|
||||
public List<ModMailMessage> getMessagesOfThread(ModMailThread modMailThread) {
|
||||
return modMailMessageRepository.findByThreadReference(modMailThread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModMailMessage> getByMessageIdOptional(Long messageId) {
|
||||
return modMailMessageRepository.findByMessageId(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteMessageFromThread(ModMailMessage modMailMessage) {
|
||||
modMailMessageRepository.delete(modMailMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.modmail.exception.ModMailThreadChannelNotFound;
|
||||
import dev.sheldan.abstracto.modmail.exception.ModMailThreadNotFoundException;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThreadState;
|
||||
@@ -44,9 +45,20 @@ public class ModMailThreadManagementServiceBean implements ModMailThreadManageme
|
||||
|
||||
@Override
|
||||
public ModMailThread getByChannel(AChannel channel) {
|
||||
return modMailThreadRepository.findByChannel(channel).orElseThrow(ModMailThreadChannelNotFound::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModMailThread> getByChannelOptional(AChannel channel) {
|
||||
return modMailThreadRepository.findByChannel(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModMailThread> getByChannelIdOptional(Long channelId) {
|
||||
AChannel channel = channelManagementService.loadChannel(channelId);
|
||||
return getByChannelOptional(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ModMailThread> getThreadByUserAndState(AUserInAServer userInAServer, ModMailThreadState state) {
|
||||
return modMailThreadRepository.findByUserAndState(userInAServer, state);
|
||||
|
||||
@@ -10,10 +10,16 @@
|
||||
<property name="today" value="(SELECT NOW())"/>
|
||||
<changeSet author="Sheldan" id="modmail_default_feature_mode-insertion">
|
||||
<insert tableName="default_feature_mode">
|
||||
<column name="enabled" value="false"/>
|
||||
<column name="enabled" value="true"/>
|
||||
<column name="mode" value="log"/>
|
||||
<column name="feature_id" valueComputed="${modmailFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
<insert tableName="default_feature_mode">
|
||||
<column name="enabled" value="true"/>
|
||||
<column name="mode" value="threadMessage"/>
|
||||
<column name="feature_id" valueComputed="${modmailFeature}" />
|
||||
<column name="created" valueComputed="${today}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -6,10 +6,10 @@
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="modmail_messages-table">
|
||||
<createTable tableName="modmail_messages">
|
||||
<changeSet author="Sheldan" id="modmail_message-table">
|
||||
<createTable tableName="modmail_message">
|
||||
<column name="message_id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="modmail_messages_pkey"/>
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="modmail_message_pkey"/>
|
||||
</column>
|
||||
<column name="anonymous" type="BOOLEAN"/>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
@@ -22,10 +22,10 @@
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="modmail_messages-fk_modmail_message_thread">
|
||||
<addForeignKeyConstraint baseColumnNames="thread_reference" baseTableName="modmail_messages" constraintName="fk_modmail_message_thread" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="modmail_thread" validate="true"/>
|
||||
<changeSet author="Sheldan" id="modmail_message-fk_modmail_message_thread">
|
||||
<addForeignKeyConstraint baseColumnNames="thread_reference" baseTableName="modmail_message" constraintName="fk_modmail_message_thread" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="modmail_thread" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="modmail_messages-fk_modmail_message_author">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_message_author" baseTableName="modmail_messages" constraintName="fk_modmail_message_author" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<changeSet author="Sheldan" id="modmail_message-fk_modmail_message_author">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_message_author" baseTableName="modmail_message" constraintName="fk_modmail_message_author" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -6,10 +6,10 @@
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<changeSet author="Sheldan" id="modmail_roles-table">
|
||||
<createTable tableName="modmail_roles">
|
||||
<changeSet author="Sheldan" id="modmail_role-table">
|
||||
<createTable tableName="modmail_role">
|
||||
<column autoIncrement="true" name="mod_mail_role_id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="modmail_roles_pkey"/>
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="modmail_role_pkey"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
@@ -21,10 +21,10 @@
|
||||
</column>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="modmail_roles-fk_modmail_role_role">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_role" baseTableName="modmail_roles" constraintName="fk_modmail_role_role" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="role" validate="true"/>
|
||||
<changeSet author="Sheldan" id="modmail_role-fk_modmail_role_role">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_role" baseTableName="modmail_role" constraintName="fk_modmail_role_role" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="role" validate="true"/>
|
||||
</changeSet>
|
||||
<changeSet author="Sheldan" id="modmail_roles-fk_modmail_role_server">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_role_server" baseTableName="modmail_roles" constraintName="fk_modmail_role_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<changeSet author="Sheldan" id="modmail_role-fk_modmail_role_server">
|
||||
<addForeignKeyConstraint baseColumnNames="modmail_role_server" baseTableName="modmail_role" constraintName="fk_modmail_role_server" deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION" referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -6,8 +6,8 @@
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
|
||||
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
|
||||
<include file="modmail_threads.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_messages.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_thread.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_message.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_subscriber.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_roles.xml" relativeToChangelogFile="true"/>
|
||||
<include file="modmail_role.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,142 @@
|
||||
package dev.sheldan.abstracto.modmail.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.AServerAChannelAUser;
|
||||
import dev.sheldan.abstracto.core.models.GuildChannelMember;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ModMailMessageDeletedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private ModMailMessageDeletedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private ModMailMessageManagementService modMailMessageManagementService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private ModMailMessageDeletedListener self;
|
||||
|
||||
@Mock
|
||||
private BotService botService;
|
||||
|
||||
@Mock
|
||||
private CachedMessage deletedMessage;
|
||||
|
||||
@Mock
|
||||
private AServerAChannelAUser origin;
|
||||
|
||||
@Mock
|
||||
private GuildChannelMember jdaOrigin;
|
||||
|
||||
@Mock
|
||||
private ModMailMessage modMailMessage;
|
||||
|
||||
@Mock
|
||||
private Member targetMember;
|
||||
|
||||
@Mock
|
||||
private User targetUser;
|
||||
|
||||
@Mock
|
||||
private AServer server;
|
||||
|
||||
@Mock
|
||||
private AChannel channel;
|
||||
|
||||
private static final Long DELETED_MESSAGE_ID = 4L;
|
||||
private static final Long CREATED_MESSAGE_ID_1 = 3L;
|
||||
private static final Long CREATED_MESSAGE_ID_2 = 5L;
|
||||
private static final Long USER_ID = 5L;
|
||||
private static final Long SERVER_ID = 6L;
|
||||
private static final Long CHANNEL_ID = 9L;
|
||||
|
||||
@Test
|
||||
public void testDeleteOutSideOfThread() {
|
||||
when(deletedMessage.getMessageId()).thenReturn(DELETED_MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.empty());
|
||||
testUnit.execute(deletedMessage, origin, jdaOrigin);
|
||||
verify(botService, times(0)).getMemberInServerAsync(anyLong(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteNonDuplicatedMessage() {
|
||||
when(deletedMessage.getMessageId()).thenReturn(DELETED_MESSAGE_ID);
|
||||
when(deletedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
AUserInAServer targetUsInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(thread.getUser()).thenReturn(targetUsInAServer);
|
||||
when(thread.getChannel()).thenReturn(channel);
|
||||
when(thread.getServer()).thenReturn(server);
|
||||
AUser targetAUser = Mockito.mock(AUser.class);
|
||||
when(targetUsInAServer.getUserReference()).thenReturn(targetAUser);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(null);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID_2);
|
||||
when(targetAUser.getId()).thenReturn(USER_ID);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(messageService.deleteMessageInChannelWithUser(targetUser, CREATED_MESSAGE_ID_2)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.execute(deletedMessage, origin, jdaOrigin);
|
||||
verify(messageService, times(0)).deleteMessageInChannelInServer(eq(SERVER_ID), anyLong(), any());
|
||||
verify(self, times(1)).removeMessageFromThread(DELETED_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteDuplicatedMessage() {
|
||||
when(deletedMessage.getMessageId()).thenReturn(DELETED_MESSAGE_ID);
|
||||
when(deletedMessage.getServerId()).thenReturn(SERVER_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
AUserInAServer targetUsInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(thread.getUser()).thenReturn(targetUsInAServer);
|
||||
when(thread.getChannel()).thenReturn(channel);
|
||||
when(thread.getServer()).thenReturn(server);
|
||||
when(server.getId()).thenReturn(SERVER_ID);
|
||||
when(channel.getId()).thenReturn(CHANNEL_ID);
|
||||
AUser targetAUser = Mockito.mock(AUser.class);
|
||||
when(targetUsInAServer.getUserReference()).thenReturn(targetAUser);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(CREATED_MESSAGE_ID_1);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID_2);
|
||||
when(targetAUser.getId()).thenReturn(USER_ID);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(messageService.deleteMessageInChannelWithUser(targetUser, CREATED_MESSAGE_ID_2)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
when(messageService.deleteMessageInChannelInServer(SERVER_ID, CHANNEL_ID, CREATED_MESSAGE_ID_1)).thenReturn(CompletableFuture.completedFuture(null));
|
||||
testUnit.execute(deletedMessage, origin, jdaOrigin);
|
||||
verify(self, times(1)).removeMessageFromThread(DELETED_MESSAGE_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void removeMessageFromThread() {
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
testUnit.removeMessageFromThread(DELETED_MESSAGE_ID);
|
||||
verify(modMailMessageManagementService, times(1)).deleteMessageFromThread(modMailMessage);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
package dev.sheldan.abstracto.modmail.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.config.Parameters;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandService;
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
import dev.sheldan.abstracto.modmail.models.template.ModMailModeratorReplyModel;
|
||||
import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
|
||||
import dev.sheldan.abstracto.modmail.service.ModMailThreadServiceBean;
|
||||
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
|
||||
import dev.sheldan.abstracto.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.templating.service.TemplateService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static dev.sheldan.abstracto.modmail.listener.ModMailMessageEditedListener.DEFAULT_COMMAND_FOR_MODMAIL_EDIT;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ModMailMessageEditedListenerTest {
|
||||
|
||||
@InjectMocks
|
||||
private ModMailMessageEditedListener testUnit;
|
||||
|
||||
@Mock
|
||||
private ModMailThreadService modMailThreadService;
|
||||
|
||||
@Mock
|
||||
private ModMailMessageManagementService modMailMessageManagementService;
|
||||
|
||||
@Mock
|
||||
private CommandRegistry commandRegistry;
|
||||
|
||||
@Mock
|
||||
private CommandService commandService;
|
||||
|
||||
@Mock
|
||||
private BotService botService;
|
||||
|
||||
@Mock
|
||||
private TemplateService templateService;
|
||||
|
||||
@Mock
|
||||
private ChannelService channelService;
|
||||
|
||||
@Mock
|
||||
private MessageService messageService;
|
||||
|
||||
@Mock
|
||||
private ModMailMessageEditedListener self;
|
||||
|
||||
@Mock
|
||||
private CachedMessage messageBefore;
|
||||
|
||||
@Mock
|
||||
private Message messageAfter;
|
||||
|
||||
@Mock
|
||||
private ModMailMessage modMailMessage;
|
||||
|
||||
@Mock
|
||||
private Parameters parsedParameters;
|
||||
|
||||
@Mock
|
||||
private Member targetMember;
|
||||
|
||||
@Mock
|
||||
private User targetUser;
|
||||
|
||||
@Mock
|
||||
private MessageToSend messageToSend;
|
||||
|
||||
@Mock
|
||||
private Member authorMember;
|
||||
|
||||
@Mock
|
||||
private Guild guild;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<ModMailModeratorReplyModel> replyModelArgumentCaptor;
|
||||
|
||||
private static final Long CHANNEL_ID = 5L;
|
||||
private static final Long MESSAGE_ID = 6L;
|
||||
private static final Long CREATED_MESSAGE_ID = 10L;
|
||||
private static final String NEW_COMMAND_PART = "editedText";
|
||||
private static final String NEW_PARAM = "param";
|
||||
private static final String NEW_CONTENT = NEW_COMMAND_PART + " " + NEW_PARAM;
|
||||
private static final Long SERVER_ID = 4L;
|
||||
private static final Long USER_ID = 3L;
|
||||
private static final Long AUTHOR_USER_ID = 9L;
|
||||
|
||||
@Test
|
||||
public void testEditOutsideModMailThread() {
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(false);
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
verify(modMailMessageManagementService, times(0)).getByMessageIdOptional(anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditNotTrackedMessage() {
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.empty());
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
verify(commandRegistry, times(0)).getCommandName(anyString(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditMessageWithCorrectCommand() {
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(messageBefore.getServerId()).thenReturn(SERVER_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
AUserInAServer targetUsInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(thread.getUser()).thenReturn(targetUsInAServer);
|
||||
AUser targetUser = Mockito.mock(AUser.class);
|
||||
when(targetUsInAServer.getUserReference()).thenReturn(targetUser);
|
||||
when(targetUser.getId()).thenReturn(USER_ID);
|
||||
AUserInAServer authorUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(modMailMessage.getAuthor()).thenReturn(authorUserInAServer);
|
||||
AUser authorUser = Mockito.mock(AUser.class);
|
||||
when(authorUser.getId()).thenReturn(AUTHOR_USER_ID);
|
||||
when(authorUserInAServer.getUserReference()).thenReturn(authorUser);
|
||||
when(messageAfter.getContentRaw()).thenReturn(NEW_CONTENT);
|
||||
when(commandRegistry.getCommandName(NEW_COMMAND_PART, SERVER_ID)).thenReturn(NEW_COMMAND_PART);
|
||||
when(commandService.doesCommandExist(NEW_COMMAND_PART)).thenReturn(true);
|
||||
when(commandService.getParametersForCommand(NEW_COMMAND_PART, messageAfter)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
verify(self, times(1)).updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEditMessageWithInCorrectCommand() {
|
||||
when(modMailThreadService.isModMailThread(CHANNEL_ID)).thenReturn(true);
|
||||
when(messageBefore.getChannelId()).thenReturn(CHANNEL_ID);
|
||||
when(messageBefore.getMessageId()).thenReturn(MESSAGE_ID);
|
||||
when(messageBefore.getServerId()).thenReturn(SERVER_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
AUserInAServer aUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(thread.getUser()).thenReturn(aUserInAServer);
|
||||
AUser user = Mockito.mock(AUser.class);
|
||||
when(aUserInAServer.getUserReference()).thenReturn(user);
|
||||
when(user.getId()).thenReturn(USER_ID);
|
||||
AUserInAServer authorUserInAServer = Mockito.mock(AUserInAServer.class);
|
||||
when(modMailMessage.getAuthor()).thenReturn(authorUserInAServer);
|
||||
AUser authorUser = Mockito.mock(AUser.class);
|
||||
when(authorUser.getId()).thenReturn(AUTHOR_USER_ID);
|
||||
when(authorUserInAServer.getUserReference()).thenReturn(authorUser);
|
||||
when(messageAfter.getContentRaw()).thenReturn(NEW_CONTENT);
|
||||
when(commandRegistry.getCommandName(NEW_COMMAND_PART, SERVER_ID)).thenReturn(NEW_COMMAND_PART);
|
||||
when(commandService.doesCommandExist(NEW_COMMAND_PART)).thenReturn(false);
|
||||
when(commandService.getParametersForCommand(DEFAULT_COMMAND_FOR_MODMAIL_EDIT, messageAfter)).thenReturn(CompletableFuture.completedFuture(parsedParameters));
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
|
||||
when(botService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
|
||||
testUnit.execute(messageBefore, messageAfter);
|
||||
verify(self, times(1)).updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAnonymousMessageInThreadNotDuplicated() {
|
||||
when(messageAfter.getIdLong()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
when(modMailMessage.getAnonymous()).thenReturn(true);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(null);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID);
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(authorMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(parsedParameters.getParameters()).thenReturn(Arrays.asList(NEW_PARAM));
|
||||
when(templateService.renderEmbedTemplate(eq(ModMailThreadServiceBean.MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY), replyModelArgumentCaptor.capture())).thenReturn(messageToSend);
|
||||
testUnit.updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
verify(channelService, times(0)).editMessageInAChannel(eq(messageToSend), any(AChannel.class), anyLong());
|
||||
verify(messageService, times(1)).editMessageInDMChannel(targetUser, messageToSend, CREATED_MESSAGE_ID);
|
||||
Assert.assertTrue(replyModelArgumentCaptor.getValue().getAnonymous());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAnonymousMessageInThreadDuplicated() {
|
||||
when(messageAfter.getIdLong()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
when(modMailMessage.getAnonymous()).thenReturn(true);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(CREATED_MESSAGE_ID);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID);
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(authorMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(thread.getChannel()).thenReturn(channel);
|
||||
when(channel.getId()).thenReturn(CHANNEL_ID);
|
||||
when(parsedParameters.getParameters()).thenReturn(Arrays.asList(NEW_PARAM));
|
||||
when(templateService.renderEmbedTemplate(eq(ModMailThreadServiceBean.MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY), replyModelArgumentCaptor.capture())).thenReturn(messageToSend);
|
||||
testUnit.updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
verify(channelService, times(1)).editMessageInAChannel(eq(messageToSend), eq(channel), eq(CREATED_MESSAGE_ID));
|
||||
verify(messageService, times(1)).editMessageInDMChannel(targetUser, messageToSend, CREATED_MESSAGE_ID);
|
||||
Assert.assertTrue(replyModelArgumentCaptor.getValue().getAnonymous());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMessageInThreadNotDuplicated() {
|
||||
when(messageAfter.getIdLong()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
when(modMailMessage.getAnonymous()).thenReturn(false);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(null);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID);
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(authorMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
when(parsedParameters.getParameters()).thenReturn(Arrays.asList(NEW_PARAM));
|
||||
when(templateService.renderEmbedTemplate(eq(ModMailThreadServiceBean.MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY), replyModelArgumentCaptor.capture())).thenReturn(messageToSend);
|
||||
testUnit.updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
verify(channelService, times(0)).editMessageInAChannel(eq(messageToSend), any(AChannel.class), anyLong());
|
||||
verify(messageService, times(1)).editMessageInDMChannel(targetUser, messageToSend, CREATED_MESSAGE_ID);
|
||||
Assert.assertFalse(replyModelArgumentCaptor.getValue().getAnonymous());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMessageInThreadDuplicated() {
|
||||
when(messageAfter.getIdLong()).thenReturn(MESSAGE_ID);
|
||||
when(modMailMessageManagementService.getByMessageIdOptional(MESSAGE_ID)).thenReturn(Optional.of(modMailMessage));
|
||||
when(modMailMessage.getAnonymous()).thenReturn(false);
|
||||
when(modMailMessage.getCreatedMessageInChannel()).thenReturn(CREATED_MESSAGE_ID);
|
||||
when(modMailMessage.getCreatedMessageInDM()).thenReturn(CREATED_MESSAGE_ID);
|
||||
ModMailThread thread = Mockito.mock(ModMailThread.class);
|
||||
when(modMailMessage.getThreadReference()).thenReturn(thread);
|
||||
when(targetMember.getUser()).thenReturn(targetUser);
|
||||
when(authorMember.getGuild()).thenReturn(guild);
|
||||
when(guild.getIdLong()).thenReturn(SERVER_ID);
|
||||
AChannel channel = Mockito.mock(AChannel.class);
|
||||
when(thread.getChannel()).thenReturn(channel);
|
||||
when(channel.getId()).thenReturn(CHANNEL_ID);
|
||||
when(parsedParameters.getParameters()).thenReturn(Arrays.asList(NEW_PARAM));
|
||||
when(templateService.renderEmbedTemplate(eq(ModMailThreadServiceBean.MODMAIL_STAFF_MESSAGE_TEMPLATE_KEY), replyModelArgumentCaptor.capture())).thenReturn(messageToSend);
|
||||
testUnit.updateMessageInThread(messageAfter, parsedParameters, targetMember, authorMember);
|
||||
verify(channelService, times(1)).editMessageInAChannel(eq(messageToSend), eq(channel), eq(CREATED_MESSAGE_ID));
|
||||
verify(messageService, times(1)).editMessageInDMChannel(targetUser, messageToSend, CREATED_MESSAGE_ID);
|
||||
Assert.assertFalse(replyModelArgumentCaptor.getValue().getAnonymous());
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class ModMailFeature implements FeatureConfig {
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(ModMailMode.LOGGING);
|
||||
return Arrays.asList(ModMailMode.LOGGING, ModMailMode.SEPARATE_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,7 @@ import lombok.Getter;
|
||||
*/
|
||||
@Getter
|
||||
public enum ModMailMode implements FeatureMode {
|
||||
LOGGING("log");
|
||||
LOGGING("log"), SEPARATE_MESSAGE("threadMessage");
|
||||
|
||||
private final String key;
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.abstracto.modmail.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
|
||||
public class ModMailThreadChannelNotFound extends AbstractoRunTimeException {
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import lombok.*;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
@@ -16,19 +17,30 @@ import java.time.Instant;
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "modmail_messages")
|
||||
@Cacheable
|
||||
@Table(name = "modmail_message")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@Cacheable
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class ModMailMessage {
|
||||
public class ModMailMessage implements Serializable {
|
||||
|
||||
/**
|
||||
* The globally unique message ID which was send in the mod mail thread, either by a user of by the staff handling the thread
|
||||
* The ID of the message which caused this message to be created, either the message containing the command or the message received from the user
|
||||
*/
|
||||
@Id
|
||||
private Long messageId;
|
||||
|
||||
/**
|
||||
* The message which got created:
|
||||
* for a message from the user, the messageId of the message in the thread
|
||||
* for a message from staff, the messageId of the message in the DM channel
|
||||
*/
|
||||
@Column(name = "created_message_in_dm")
|
||||
private Long createdMessageInDM;
|
||||
@Column
|
||||
private Long createdMessageInChannel;
|
||||
|
||||
/**
|
||||
* The {@link AUserInAServer} which authored this message
|
||||
*/
|
||||
@@ -39,18 +51,21 @@ public class ModMailMessage {
|
||||
/**
|
||||
* The {@link ModMailThread} in whose context this message was sent and this message is related to
|
||||
*/
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
|
||||
@JoinColumn(name = "threadReference", nullable = false)
|
||||
private ModMailThread threadReference;
|
||||
|
||||
/**
|
||||
* Whether or not this message was from the user or a staff member, for convenience
|
||||
* true: message was send via command, false: message was send from the user
|
||||
* This is used to decide where to get the message from in case of logging, because the user might delete the message and we do not want to re-parse the command message
|
||||
*/
|
||||
@Column
|
||||
private Boolean dmChannel;
|
||||
|
||||
/**
|
||||
* Staff only: Whether or not this message meant to be sent anonymous
|
||||
*/
|
||||
@Column
|
||||
private Boolean anonymous;
|
||||
|
||||
@Column(name = "created")
|
||||
|
||||
@@ -6,6 +6,7 @@ import lombok.*;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
@@ -16,12 +17,13 @@ import java.time.Instant;
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "modmail_roles")
|
||||
@Cacheable
|
||||
@Table(name = "modmail_role")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@Cacheable
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class ModMailRole {
|
||||
public class ModMailRole implements Serializable {
|
||||
|
||||
/**
|
||||
* Unique ID of the mod mail role
|
||||
|
||||
@@ -5,6 +5,7 @@ import lombok.*;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -18,11 +19,12 @@ import java.util.List;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "modmail_thread")
|
||||
@Cacheable
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@Cacheable
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class ModMailThread {
|
||||
public class ModMailThread implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
|
||||
@@ -16,9 +16,10 @@ import java.time.Instant;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "modmail_subscriber")
|
||||
@Cacheable
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
@Cacheable
|
||||
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
|
||||
public class ModMailThreadSubscriber {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package dev.sheldan.abstracto.modmail.service;
|
||||
|
||||
|
||||
import dev.sheldan.abstracto.core.models.UndoActionInstance;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUser;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
@@ -50,9 +51,9 @@ public interface ModMailThreadService {
|
||||
* In case there was no channel found, this will cause a message to be shown to the user and the existing mod mail thread will be closed.
|
||||
* This is the case, if the mod mail thread was still open in the database, but no text channel was found anymore.
|
||||
* @param modMailThread The {@link ModMailThread} on which the user answered
|
||||
* @param message The {@link Message} object which was sent by the user to answer with
|
||||
* @param messageFromUser The {@link Message} object which was sent by the user as an answer
|
||||
*/
|
||||
CompletableFuture<Message> relayMessageToModMailThread(ModMailThread modMailThread, Message message, List<UndoActionInstance> undoActions);
|
||||
CompletableFuture<Message> relayMessageToModMailThread(ModMailThread modMailThread, Message messageFromUser, List<UndoActionInstance> undoActions);
|
||||
|
||||
/**
|
||||
* Forwards a message send by a moderator to the direct message channel opened with the user. If the message is
|
||||
@@ -91,4 +92,7 @@ public interface ModMailThreadService {
|
||||
* @param logThread Whether or not the thread should be logged to the appropriate post target
|
||||
*/
|
||||
CompletableFuture<Void> closeModMailThread(ModMailThread modMailThread, String note, boolean notifyUser, boolean logThread, List<UndoActionInstance> undoActions);
|
||||
|
||||
boolean isModMailThread(AChannel channel);
|
||||
boolean isModMailThread(Long channelId);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Management service to handle the creation and retrieval of {@link ModMailMessage} instances from the database
|
||||
@@ -14,13 +15,15 @@ public interface ModMailMessageManagementService {
|
||||
/**
|
||||
* Creates an instance of {@link ModMailMessage}, attaches it to the given {@link ModMailThread} and returns the created instance
|
||||
* @param modMailThread The {@link ModMailThread} the message should be attached to
|
||||
* @param message The {@link Message} which should be attached to the {@link ModMailThread}
|
||||
* @param createdMessageInDM The {@link Message} which should be attached to the {@link ModMailThread} and was posted to the DM channel (might be null)
|
||||
* @param createdMessageInChannel The {@link Message} which should be attached to the {@link ModMailThread} and was posted to the modmail thread (might be null)
|
||||
* @param userPostedMessage The {@link Message} which caused this message to be created, the command or the message by the user
|
||||
* @param author The {@link AUserInAServer} who authored the {@link Message} originally
|
||||
* @param anonymous Whether or not the message was sent anonymous (only possible by staff members)
|
||||
* @param dmChannel Whether or not the message originated from the user, and therefore in an direct message channel
|
||||
* @return
|
||||
*/
|
||||
ModMailMessage addMessageToThread(ModMailThread modMailThread, Message message, AUserInAServer author, Boolean anonymous, Boolean dmChannel);
|
||||
ModMailMessage addMessageToThread(ModMailThread modMailThread, Message createdMessageInDM, Message createdMessageInChannel, Message userPostedMessage, AUserInAServer author, Boolean anonymous, Boolean dmChannel);
|
||||
|
||||
/**
|
||||
* Retrieves all messages which were sent in a {@link ModMailThread}
|
||||
@@ -28,4 +31,8 @@ public interface ModMailMessageManagementService {
|
||||
* @return A list of {@link ModMailMessage} which were sent in the given thread
|
||||
*/
|
||||
List<ModMailMessage> getMessagesOfThread(ModMailThread modMailThread);
|
||||
|
||||
Optional<ModMailMessage> getByMessageIdOptional(Long messageId);
|
||||
|
||||
void deleteMessageFromThread(ModMailMessage modMailMessage);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,8 @@ public interface ModMailThreadManagementService {
|
||||
* @return The found mod mail thread, or null if none was found
|
||||
*/
|
||||
ModMailThread getByChannel(AChannel channel);
|
||||
Optional<ModMailThread> getByChannelOptional(AChannel channel);
|
||||
Optional<ModMailThread> getByChannelIdOptional(Long channelId);
|
||||
|
||||
/**
|
||||
* Searches for mod mail threads with the appropriate staten which concern the given {@link AUserInAServer}
|
||||
|
||||
Reference in New Issue
Block a user