[AB-184] adding various metrics to the system, organizing imports, changing some transactional behaviour

adding okhttp metrics, split bot service into multiple services (guild, message), unified some places that services are used in order to interact with the api, and not directly the objects (this is to make it easier for metric to be accurate)
This commit is contained in:
Sheldan
2021-01-29 17:46:41 +01:00
parent 2a2a3aea70
commit b838678c15
362 changed files with 3045 additions and 1573 deletions

View File

@@ -39,6 +39,12 @@
<artifactId>modmail-int</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>metrics-interface</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -9,7 +9,7 @@ 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.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
@@ -40,7 +40,7 @@ public class AnonReply extends AbstractConditionableCommand {
private ModMailThreadManagementService modMailThreadManagementService;
@Autowired
private BotService botService;
private MemberService memberService;
@Autowired
private ChannelManagementService channelManagementService;
@@ -53,7 +53,7 @@ public class AnonReply extends AbstractConditionableCommand {
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel);
Long threadId = thread.getId();
return botService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
modMailThreadService.relayMessageToDm(threadId, text, commandContext.getMessage(), true, commandContext.getChannel(), commandContext.getUndoActions(), member)
).thenApply(aVoid -> CommandResult.fromSuccess());
}

View File

@@ -50,7 +50,7 @@ public class Contact extends AbstractConditionableCommand {
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Member targetUser = (Member) commandContext.getParameters().getParameters().get(0);
AUserInAServer user = userManagementService.loadUser(targetUser);
AUserInAServer user = userManagementService.loadOrCreateUser(targetUser);
// if this AUserInAServer already has an open thread, we should instead post a message
// containing a link to the channel, instead of opening a new one
if(modMailThreadManagementService.hasOpenModMailThreadForUser(user)) {

View File

@@ -9,7 +9,7 @@ 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.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
@@ -39,7 +39,7 @@ public class Reply extends AbstractConditionableCommand {
private ModMailThreadManagementService modMailThreadManagementService;
@Autowired
private BotService botService;
private MemberService memberService;
@Autowired
private ChannelManagementService channelManagementService;
@@ -51,7 +51,7 @@ public class Reply extends AbstractConditionableCommand {
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel);
Long threadId = thread.getId();
return botService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member ->
modMailThreadService.relayMessageToDm(threadId, text, commandContext.getMessage(), false, commandContext.getChannel(), commandContext.getUndoActions(), member)
).thenApply(aVoid -> CommandResult.fromSuccess());
}

View File

@@ -41,7 +41,7 @@ public class Subscribe extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
modMailSubscriptionService.subscribeToThread(userInServerManagementService.loadUser(commandContext.getAuthor()), modMailThread);
modMailSubscriptionService.subscribeToThread(userInServerManagementService.loadOrCreateUser(commandContext.getAuthor()), modMailThread);
return CommandResult.fromSuccess();
}

View File

@@ -42,7 +42,7 @@ public class UnSubscribe extends AbstractConditionableCommand {
@Override
public CommandResult execute(CommandContext commandContext) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(commandContext.getAuthor());
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
modMailSubscriptionService.unsubscribeFromThread(aUserInAServer, modMailThread);
return CommandResult.fromSuccess();
}

View File

@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.modmail.listener;
import dev.sheldan.abstracto.core.config.FeatureEnum;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageDeletedListener;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
@@ -31,7 +31,7 @@ public class ModMailMessageDeletedListener implements AsyncMessageDeletedListene
private ModMailMessageDeletedListener self;
@Autowired
private BotService botService;
private MemberService memberService;
@Override
public void execute(CachedMessage messageBefore) {
@@ -44,7 +44,7 @@ public class ModMailMessageDeletedListener implements AsyncMessageDeletedListene
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 -> {
memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId()).thenAccept(member -> {
CompletableFuture<Void> dmDeletePromise = messageService.deleteMessageInChannelWithUser(member.getUser(), dmMessageId);
CompletableFuture<Void> channelDeletePromise;
if(hasMessageInChannel) {

View File

@@ -8,8 +8,8 @@ import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageTextUpdatedList
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.MemberService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
@@ -41,7 +41,7 @@ public class ModMailMessageEditedListener implements AsyncMessageTextUpdatedList
private CommandService commandService;
@Autowired
private BotService botService;
private MemberService memberService;
@Autowired
private TemplateService templateService;
@@ -84,8 +84,8 @@ public class ModMailMessageEditedListener implements AsyncMessageTextUpdatedList
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, loadedMessage);
CompletableFuture<Member> loadTargetUser = botService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId());
CompletableFuture<Member> loadEditingUser = botService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getAuthor().getUserReference().getId());
CompletableFuture<Member> loadTargetUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getThreadReference().getUser().getUserReference().getId());
CompletableFuture<Member> loadEditingUser = memberService.getMemberInServerAsync(messageBefore.getServerId(), modMailMessage.getAuthor().getUserReference().getId());
CompletableFuture.allOf(parameterParseFuture, loadTargetUser, loadEditingUser).thenAccept(unused ->
self.updateMessageInThread(loadedMessage, parameterParseFuture.join(), loadTargetUser.join(), loadEditingUser.join())
);
@@ -110,7 +110,7 @@ public class ModMailMessageEditedListener implements AsyncMessageTextUpdatedList
.anonymous(modMailMessage.getAnonymous())
.threadUser(fullThreadUser);
if(modMailMessage.getAnonymous()) {
modMailModeratorReplyModelBuilder.moderator(botService.getBotInGuild(modMailMessage.getThreadReference().getServer()));
modMailModeratorReplyModelBuilder.moderator(memberService.getBotInGuild(modMailMessage.getThreadReference().getServer()));
} else {
modMailModeratorReplyModelBuilder.moderator(editingUser);
}

View File

@@ -14,6 +14,7 @@ import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
@@ -45,7 +46,7 @@ public class ModMailMessageListener implements PrivateMessageReceivedListener {
if(message.getAuthor().isBot()) {
return;
}
AUser user = userManagementService.loadUser(message.getAuthor().getIdLong());
AUser user = userManagementService.loadOrCreateUser(message.getAuthor().getIdLong());
if(modMailThreadManagementService.hasOpenModMailThread(user)) {
log.trace("User {} has an open modmail thread. Forwarding message {}.", user.getId(), message.getId());
// there is only one open mod mail thread for a user at a time, so we can select the first one

View File

@@ -2,6 +2,8 @@ package dev.sheldan.abstracto.modmail.service;
import dev.sheldan.abstracto.core.models.ServerChannelMessageUser;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
import dev.sheldan.abstracto.modmail.models.dto.LoadedModmailThreadMessage;
@@ -23,9 +25,15 @@ import java.util.concurrent.CompletableFuture;
@Slf4j
public class ModMailMessageServiceBean implements ModMailMessageService {
@Autowired
private MemberService memberService;
@Autowired
private BotService botService;
@Autowired
private ChannelService channelService;
@Override
public LoadedModmailThreadMessageList loadModMailMessages(List<ModMailMessage> modMailMessages) {
if(modMailMessages.isEmpty()) {
@@ -57,7 +65,7 @@ public class ModMailMessageServiceBean implements ModMailMessageService {
// the opening of a private channel is a rest operation it itself, so we need
// to create the promises here already, else the list is empty for example
modMailMessages.forEach(modMailMessage -> messageFutures.add(getLoadedModmailThreadMessage()));
Optional<TextChannel> textChannelFromServer = botService.getTextChannelFromServerOptional(thread.getServer().getId(), thread.getChannel().getId());
Optional<TextChannel> textChannelFromServer = channelService.getTextChannelFromServerOptional(thread.getServer().getId(), thread.getChannel().getId());
if(textChannelFromServer.isPresent()) {
TextChannel modMailThread = textChannelFromServer.get();
Long userId = thread.getUser().getUserReference().getId();
@@ -66,11 +74,11 @@ public class ModMailMessageServiceBean implements ModMailMessageService {
messageIds.forEach(serverChannelMessage -> {
log.trace("Loading message {}.", serverChannelMessage.getMessageId());
CompletableFuture<Message> messageFuture;
CompletableFuture<Member> memberFuture = botService.getMemberInServerAsync(serverChannelMessage.getServerId(), serverChannelMessage.getUserId());
CompletableFuture<Member> memberFuture = memberService.getMemberInServerAsync(serverChannelMessage.getServerId(), serverChannelMessage.getUserId());
if(serverChannelMessage.getChannelId() == null){
messageFuture = privateChannel.retrieveMessageById(serverChannelMessage.getMessageId()).submit();
messageFuture = channelService.retrieveMessageInChannel(privateChannel, serverChannelMessage.getMessageId());
} else {
messageFuture = modMailThread.retrieveMessageById(serverChannelMessage.getMessageId()).submit();
messageFuture = channelService.retrieveMessageInChannel(modMailThread, serverChannelMessage.getMessageId());
}
CompletableFuture.allOf(messageFuture, memberFuture).whenComplete((aVoid, throwable) -> {
LoadedModmailThreadMessage next = iterator.next();

View File

@@ -4,6 +4,9 @@ import com.jagrosh.jdautilities.commons.waiter.EventWaiter;
import com.jagrosh.jdautilities.menu.ButtonMenu;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.metrics.service.CounterMetric;
import dev.sheldan.abstracto.core.metrics.service.MetricService;
import dev.sheldan.abstracto.core.metrics.service.MetricTag;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.FullGuild;
import dev.sheldan.abstracto.core.models.FullUserInServer;
@@ -15,12 +18,15 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
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.config.ModMailFeature;
import dev.sheldan.abstracto.modmail.config.ModMailFeatures;
import dev.sheldan.abstracto.modmail.config.ModMailMode;
import dev.sheldan.abstracto.modmail.config.ModMailPostTargets;
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.*;
import dev.sheldan.abstracto.modmail.models.dto.LoadedModmailThreadMessageList;
import dev.sheldan.abstracto.modmail.models.dto.ServerChoice;
import dev.sheldan.abstracto.modmail.models.template.*;
import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService;
@@ -37,13 +43,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct;
import java.time.Instant;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
@Transactional
public class ModMailThreadServiceBean implements ModMailThreadService {
/**
@@ -76,7 +82,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
private UserInServerManagementService userInServerManagementService;
@Autowired
private BotService botService;
private MemberService memberService;
@Autowired
private TemplateService templateService;
@@ -90,6 +96,12 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Autowired
private PostTargetService postTargetService;
@Autowired
private ReactionService reactionService;
@Autowired
private GuildService guildService;
@Autowired
private MessageService messageService;
@@ -123,6 +135,37 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Autowired
private ModMailThreadServiceBean self;
@Autowired
private MetricService metricService;
public static final String MODMAIL_THREAD_METRIC = "modmail.threads";
public static final String MODMAIL_MESSAGE_METRIC = "modmail.messges";
public static final String ACTION = "action";
public static final String MESSAGE_DIRECTION = "direction";
private static final CounterMetric MODMAIL_THREAD_CREATED_COUNTER =
CounterMetric
.builder()
.name(MODMAIL_THREAD_METRIC)
.tagList(Arrays.asList(MetricTag.getTag(ACTION, "created")))
.build();
private static final CounterMetric MODMAIL_THREAD_CLOSED_COUNTER =
CounterMetric
.builder()
.name(MODMAIL_THREAD_METRIC)
.tagList(Arrays.asList(MetricTag.getTag(ACTION, "closed")))
.build();
private static final CounterMetric MDOMAIL_THREAD_MESSAGE_RECEIVED =
CounterMetric
.builder().name(MODMAIL_MESSAGE_METRIC)
.tagList(Arrays.asList(MetricTag.getTag(MESSAGE_DIRECTION, "received")))
.build();
private static final CounterMetric MDOMAIL_THREAD_MESSAGE_SENT =
CounterMetric
.builder()
.name(MODMAIL_MESSAGE_METRIC)
.tagList(Arrays.asList(MetricTag.getTag(MESSAGE_DIRECTION, "sent")))
.build();
/**
* The emoji used when the user can decide for a server to open a mod mail thread in.
*/
@@ -137,6 +180,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
Long serverId = member.getGuild().getIdLong();
Long categoryId = configService.getLongValue(MODMAIL_CATEGORY, serverId);
AServer server = serverManagementService.loadServer(member.getGuild().getIdLong());
metricService.incrementCounter(MODMAIL_THREAD_CREATED_COUNTER);
User user = member.getUser();
log.info("Creating modmail channel for user {} in category {} on server {}.", user.getId(), categoryId, serverId);
CompletableFuture<TextChannel> textChannelFuture = channelService.createTextChannel(user.getName() + user.getDiscriminator(), server, categoryId);
@@ -182,7 +226,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Transactional
public void setupModMailThreadInDB(Message initialMessage, TextChannel channel, Member member, Message sendMessage) {
log.info("Persisting info about modmail thread {} in database.", channel.getIdLong());
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(member);
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
ModMailThread thread = createThreadObject(channel, aUserInAServer);
if(initialMessage != null) {
log.trace("Adding initial message {} to modmail thread in channel {}.", initialMessage.getId(), channel.getId());
@@ -251,7 +295,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
AServer serverReference = aUserInAServer.getServerReference();
FullGuild guild = FullGuild
.builder()
.guild(botService.getGuildById(serverReference.getId()))
.guild(guildService.getGuildById(serverReference.getId()))
.server(serverReference)
.build();
// TODO support more than this limited amount of servers
@@ -276,7 +320,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.setAction(reactionEmote -> {
Long chosenServerId = choices.get(reactionEmote.getEmoji());
log.trace("Executing action for creationg a modmail thread in server {} for user {}.", chosenServerId, initialMessage.getAuthor().getIdLong());
botService.getMemberInServerAsync(chosenServerId, initialMessage.getAuthor().getIdLong()).thenCompose(member ->
memberService.getMemberInServerAsync(chosenServerId, initialMessage.getAuthor().getIdLong()).thenCompose(member ->
self.createModMailThreadForUser(member, initialMessage, initialMessage.getChannel(), true, new ArrayList<>()).exceptionally(throwable -> {
log.error("Failed to setup thread correctly", throwable);
return null;
@@ -290,7 +334,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
// if exactly one server is available, open the thread directly
Long chosenServerId = choices.get(availableGuilds.get(0).getReactionEmote());
log.info("Only one server available to modmail. Directly opening modmail thread for user {} in server {}.", initialMessage.getAuthor().getId(), chosenServerId);
botService.getMemberInServerAsync(chosenServerId, initialMessage.getAuthor().getIdLong()).thenCompose(member ->
memberService.getMemberInServerAsync(chosenServerId, initialMessage.getAuthor().getIdLong()).thenCompose(member ->
self.createModMailThreadForUser(member, initialMessage, initialMessage.getChannel(), true, new ArrayList<>()).exceptionally(throwable -> {
log.error("Failed to setup thread correctly", throwable);
return null;
@@ -315,7 +359,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
*/
private CompletableFuture<Void> sendModMailHeader(TextChannel channel, Member member) {
log.trace("Sending modmail thread header for tread in channel {} on server {}.", channel.getIdLong(), channel.getGuild().getId());
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(member);
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
ModMailThread latestThread = modMailThreadManagementService.getLatestModMailThread(aUserInAServer);
List<ModMailThread> oldThreads = modMailThreadManagementService.getModMailThreadForUser(aUserInAServer);
ModMailThreaderHeader header = ModMailThreaderHeader
@@ -333,9 +377,10 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
Long serverId = modMailThread.getServer().getId();
Long channelId = modMailThread.getChannel().getId();
Long modmailThreadId = modMailThread.getId();
metricService.incrementCounter(MDOMAIL_THREAD_MESSAGE_RECEIVED);
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);
return memberService.getMemberInServerAsync(modMailThread.getServer().getId(), messageFromUser.getAuthor().getIdLong()).thenCompose(member -> {
Optional<TextChannel> textChannelFromServer = channelService.getTextChannelFromServerOptional(serverId, channelId);
if(textChannelFromServer.isPresent()) {
TextChannel textChannel = textChannelFromServer.get();
return self.sendUserReply(textChannel, modmailThreadId, messageFromUser, member, true);
@@ -344,7 +389,8 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
// 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 messageFromUser.getChannel().sendMessage(templateService.renderTemplate("modmail_failed_to_forward_message", new Object())).submit();
String textToSend = templateService.renderTemplate("modmail_failed_to_forward_message", new Object());
return channelService.sendTextToChannel(textToSend, messageFromUser.getChannel());
}
});
@@ -367,7 +413,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
ModMailThread modMailThread = modMailThreadManagementService.getById(modMailThreadId);
List<ModMailThreadSubscriber> subscriberList = modMailSubscriberManagementService.getSubscribersForThread(modMailThread);
subscriberList.forEach(modMailThreadSubscriber ->
subscriberMemberFutures.add(botService.getMemberInServerAsync(modMailThreadSubscriber.getSubscriber()))
subscriberMemberFutures.add(memberService.getMemberInServerAsync(modMailThreadSubscriber.getSubscriber()))
);
if(subscriberList.isEmpty()) {
subscriberMemberFutures.add(CompletableFuture.completedFuture(null));
@@ -389,7 +435,7 @@ 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(), messageFromUser);
return reactionService.addReactionToMessageAsync("readReaction", textChannel.getGuild().getIdLong(), messageFromUser);
})
.thenApply(aVoid -> {
if(modMailThreadExists) {
@@ -426,7 +472,8 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override
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());
AUserInAServer moderator = userInServerManagementService.loadOrCreateUser(replyCommandMessage.getMember());
metricService. incrementCounter(MDOMAIL_THREAD_MESSAGE_SENT);
ModMailThread modMailThread = modMailThreadManagementService.getById(modmailThreadId);
FullUserInServer fullThreadUser = FullUserInServer
.builder()
@@ -442,10 +489,10 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.threadUser(fullThreadUser);
if(anonymous) {
log.trace("Message is sent anonymous.");
modMailModeratorReplyModelBuilder.moderator(botService.getBotInGuild(modMailThread.getServer()));
modMailModeratorReplyModelBuilder.moderator(memberService.getBotInGuild(modMailThread.getServer()));
} else {
// should be loaded, because we are currently processing a command caused by the message
Member moderatorMember = botService.getMemberInServer(moderator);
Member moderatorMember = memberService.getMemberInServer(moderator);
modMailModeratorReplyModelBuilder.moderator(moderatorMember);
}
ModMailModeratorReplyModel modMailUserReplyModel = modMailModeratorReplyModelBuilder.build();
@@ -471,6 +518,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override
public CompletableFuture<Void> closeModMailThread(ModMailThread modMailThread, String note, boolean notifyUser, boolean logThread, List<UndoActionInstance> undoActions) {
metricService.incrementCounter(MODMAIL_THREAD_CREATED_COUNTER);
Long modMailThreadId = modMailThread.getId();
log.info("Starting closing procedure for thread {}", modMailThread.getId());
List<ModMailMessage> modMailMessages = modMailThread.getMessages();
@@ -486,7 +534,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
} else {
log.trace("Not logging modmail thread {}.", modMailThreadId);
return botService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
return memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
self.afterSuccessfulLog(modMailThreadId, notifyUser, member, undoActions)
);
}
@@ -500,7 +548,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override
public boolean isModMailThread(Long channelId) {
AChannel channel = channelManagementService.loadChannel(channelId);
return modMailThreadManagementService.getByChannelOptional(channel).isPresent();
return isModMailThread(channel);
}
/**
@@ -522,9 +570,9 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
return list.getMainFuture().thenCompose(avoid -> {
list.getFutures().forEach(messageCompletableFuture -> {
Message message = messageCompletableFuture.join();
undoActions.add(UndoActionInstance.getMessageDeleteAction(messageCompletableFuture.join().getChannel().getIdLong(), message.getIdLong()));
undoActions.add(UndoActionInstance.getMessageDeleteAction(message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong()));
});
return botService.getMemberInServerAsync(serverId, userId).thenCompose(member ->
return memberService.getMemberInServerAsync(serverId, userId).thenCompose(member ->
self.afterSuccessfulLog(modMailThreadId, notifyUser, member, undoActions)
);
});
@@ -727,4 +775,12 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
throw new ModMailThreadNotFoundException(modMailThreadId);
}
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(MODMAIL_THREAD_CREATED_COUNTER, "Mod mail threads created");
metricService.registerCounter(MODMAIL_THREAD_CLOSED_COUNTER, "Mod mail threads closed");
metricService.registerCounter(MDOMAIL_THREAD_MESSAGE_RECEIVED, "Mod mail messages received");
metricService.registerCounter(MDOMAIL_THREAD_MESSAGE_SENT, "Mod mail messages sent");
}
}

View File

@@ -5,8 +5,8 @@ import dev.sheldan.abstracto.core.models.AServerChannelUserId;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.GuildService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.ConfigManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -56,7 +56,7 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup {
private ModMailFeatureValidator modMailFeatureValidator;
@Autowired
private BotService botService;
private GuildService guildService;
/**
* This setup method loads the existing mod mail category (if anything) and populates the model used to render the prompt.
@@ -78,7 +78,7 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup {
.builder()
.build();
if(configManagementService.configExists(user.getGuildId(), ModMailThreadServiceBean.MODMAIL_CATEGORY)) {
Guild guild = botService.getGuildById(user.getGuildId());
Guild guild = guildService.getGuildById(user.getGuildId());
Long categoryId = configService.getLongValue(ModMailThreadServiceBean.MODMAIL_CATEGORY, user.getGuildId());
log.trace("Previous modmail category exists for server {}. Loading value {}.", guild.getId(), categoryId);
Category category = guild.getCategoryById(categoryId);
@@ -88,7 +88,7 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup {
String messageText = templateService.renderTemplate(messageTemplateKey, model);
AChannel channel = channelManagementService.loadChannel(user.getChannelId());
CompletableFuture<SetupStepResult> future = new CompletableFuture<>();
AUserInAServer aUserInAServer = userInServerManagementService.loadUser(user.getGuildId(), user.getUserId());
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(user.getGuildId(), user.getUserId());
Runnable finalAction = getTimeoutRunnable(user.getGuildId(), user.getChannelId());
Consumer<MessageReceivedEvent> configAction = (MessageReceivedEvent event) -> {
@@ -104,7 +104,7 @@ public class ModMailCategorySetupBean implements ModMailCategorySetup {
String messageContent = event.getMessage().getContentRaw();
// directly parse the long from the message, for *now*, only the category ID is supported
Long categoryId = Long.parseLong(messageContent);
Guild guild = botService.getGuildById(user.getGuildId());
Guild guild = guildService.getGuildById(user.getGuildId());
FeatureValidationResult featureValidationResult = FeatureValidationResult.builder().validationResult(true).build();
// directly validate whether or not the given category ID is a valid value
modMailFeatureValidator.validateModMailCategory(featureValidationResult, guild, categoryId);

View File

@@ -3,9 +3,9 @@ package dev.sheldan.abstracto.modmail.validator;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ConfigService;
import dev.sheldan.abstracto.core.service.FeatureValidatorService;
import dev.sheldan.abstracto.core.service.GuildService;
import dev.sheldan.abstracto.modmail.models.template.ModMailCategoryValidationErrorModel;
import dev.sheldan.abstracto.modmail.service.ModMailThreadServiceBean;
import lombok.extern.slf4j.Slf4j;
@@ -26,7 +26,7 @@ import java.util.Optional;
public class ModMailFeatureValidatorBean implements ModMailFeatureValidator {
@Autowired
private BotService botService;
private GuildService guildService;
@Autowired
private ConfigService configService;
@@ -42,7 +42,7 @@ public class ModMailFeatureValidatorBean implements ModMailFeatureValidator {
*/
@Override
public void featureIsSetup(FeatureConfig featureConfig, AServer server, FeatureValidationResult validationResult) {
Optional<Guild> guildById = botService.getGuildByIdOptional(server.getId());
Optional<Guild> guildById = guildService.getGuildByIdOptional(server.getId());
if(guildById.isPresent()) {
Guild guild = guildById.get();
boolean checkSucceeded = featureValidatorService.checkSystemConfig(ModMailThreadServiceBean.MODMAIL_CATEGORY, server, validationResult);

View File

@@ -5,7 +5,7 @@ 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.MemberService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
@@ -40,7 +40,7 @@ public class ModMailMessageDeletedListenerTest {
private ModMailMessageDeletedListener self;
@Mock
private BotService botService;
private MemberService memberService;
@Mock
private CachedMessage deletedMessage;
@@ -72,7 +72,7 @@ public class ModMailMessageDeletedListenerTest {
when(deletedMessage.getMessageId()).thenReturn(DELETED_MESSAGE_ID);
when(modMailMessageManagementService.getByMessageIdOptional(DELETED_MESSAGE_ID)).thenReturn(Optional.empty());
testUnit.execute(deletedMessage);
verify(botService, times(0)).getMemberInServerAsync(anyLong(), anyLong());
verify(memberService, times(0)).getMemberInServerAsync(anyLong(), anyLong());
}
@Test
@@ -92,7 +92,7 @@ public class ModMailMessageDeletedListenerTest {
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(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
when(messageService.deleteMessageInChannelWithUser(targetUser, CREATED_MESSAGE_ID_2)).thenReturn(CompletableFuture.completedFuture(null));
testUnit.execute(deletedMessage);
verify(messageService, times(0)).deleteMessageInChannelInServer(eq(SERVER_ID), anyLong(), any());
@@ -118,7 +118,7 @@ public class ModMailMessageDeletedListenerTest {
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(memberService.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);

View File

@@ -7,8 +7,8 @@ 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.MemberService;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.modmail.models.database.ModMailMessage;
import dev.sheldan.abstracto.modmail.models.database.ModMailThread;
@@ -28,7 +28,6 @@ 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;
@@ -55,7 +54,7 @@ public class ModMailMessageEditedListenerTest {
private CommandService commandService;
@Mock
private BotService botService;
private MemberService memberService;
@Mock
private TemplateService templateService;
@@ -159,8 +158,8 @@ public class ModMailMessageEditedListenerTest {
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, loadedMessage)).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));
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
testUnit.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
verify(self, times(1)).updateMessageInThread(loadedMessage, parsedParameters, targetMember, authorMember);
}
@@ -187,8 +186,8 @@ public class ModMailMessageEditedListenerTest {
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, loadedMessage)).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));
when(memberService.getMemberInServerAsync(SERVER_ID, USER_ID)).thenReturn(CompletableFuture.completedFuture(targetMember));
when(memberService.getMemberInServerAsync(SERVER_ID, AUTHOR_USER_ID)).thenReturn(CompletableFuture.completedFuture(authorMember));
testUnit.executeMessageUpdatedLogic(messageBefore, messageAfter, loadedMessage);
verify(self, times(1)).updateMessageInThread(loadedMessage, parsedParameters, targetMember, authorMember);
}

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.modmail.models.database;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import lombok.*;
import org.hibernate.annotations.CacheConcurrencyStrategy;

View File

@@ -2,7 +2,6 @@ package dev.sheldan.abstracto.modmail.models.template.exception;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;