From a06006d76347d1e2191d0954c43e22fe20ab72e9 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Wed, 6 May 2020 14:17:44 +0200 Subject: [PATCH] added jda utilities dependency added modmail with some simple features (chat between user and moderator), and initial server selection (currently allows all servers, and does not consider the modmail feature) added the initial commands, not all of them hold logic currently added some checks to not crash when a command has null configuration changed systemconfig to also have a long value, because double is not fit for all cases added locking mechanism, to effectively lock the whole table without using the ... proper locking mechanism (needs to be reviewed) changed interface in channel service to be a message channel instead of a textChannel changed starboard post to be a user in a server instead of only user --- .../modmail/modmail-impl/pom.xml | 23 ++ .../abstracto/modmail/commands/AnonReply.java | 43 ++++ .../abstracto/modmail/commands/Close.java | 43 ++++ .../modmail/commands/CloseSilently.java | 43 ++++ .../abstracto/modmail/commands/Contact.java | 28 ++ .../commands/ModMailModuleInterface.java | 22 ++ .../abstracto/modmail/commands/Reply.java | 67 +++++ .../modmail/commands/SetModMailCategory.java | 52 ++++ .../condition/RequiresModMailCondition.java | 26 ++ .../modmail/config/ModMailFeature.java | 13 + .../modmail/config/ModMailFeatures.java | 18 ++ .../listener/ModMailMessageListener.java | 52 ++++ .../repository/ModMailMessageRepository.java | 9 + .../repository/ModMailThreadRepository.java | 22 ++ .../service/ModMailThreadServiceBean.java | 243 ++++++++++++++++++ .../ModMailMessageManagementServiceBean.java | 30 +++ .../ModMailThreadManagementServiceBean.java | 70 +++++ .../modmail_modal_server_choice_en_US.ftl | 5 + .../modmail_staff_message_embed_en_US.ftl | 20 ++ .../modmail_user_message_embed_en_US.ftl | 20 ++ .../modmail_welcome_message_en_US.ftl | 1 + .../modmail/modmail-int/pom.xml | 22 ++ .../models/database/ModMailMessage.java | 32 +++ .../models/database/ModMailThread.java | 62 +++++ .../models/database/ModMailThreadState.java | 16 ++ .../modmail/models/dto/ServerChoice.java | 14 + .../template/ModMailModeratorReplyModel.java | 18 ++ .../template/ModMailServerChooserModel.java | 15 ++ .../template/ModMailUserReplyModel.java | 17 ++ .../modmail/service/ModMailThreadService.java | 22 ++ .../ModMailMessageManagementService.java | 10 + .../ModMailThreadManagementService.java | 21 ++ .../abstracto-modules/modmail/pom.xml | 29 +++ .../abstracto-modules/pom.xml | 1 + .../StarboardPostDeletedListener.java | 3 +- .../StarboardPostManagementServiceBean.java | 2 +- .../models/database/StarboardPost.java | 4 +- .../command/config/CommandConfigListener.java | 8 +- .../config/CommandCreationListener.java | 6 + .../core/command/service/CommandManager.java | 6 +- .../command/service/CommandServiceBean.java | 6 + .../config/{SetNumber.java => SetFloat.java} | 4 +- .../core/commands/config/SetLong.java | 53 ++++ .../core/listener/ChannelListener.java | 2 +- .../listener/MessageReceivedListenerBean.java | 23 +- .../abstracto/core/model/database/ALock.java | 21 ++ .../core/repository/LockRepository.java | 18 ++ .../repository/UserInServerRepository.java | 4 + .../core/service/ChannelServiceBean.java | 30 ++- .../core/service/ConfigServiceBean.java | 23 ++ .../core/service/LockServiceBean.java | 19 ++ .../core/service/StartupServiceBean.java | 2 +- .../ChannelManagementServiceBean.java | 33 ++- .../ConfigManagementServiceBean.java | 20 ++ .../UserInServerManagementServiceBean.java | 8 + .../core/command/models/TableLocks.java | 5 + .../PrivateMessageReceivedListener.java | 7 + .../abstracto/core/models/FullGuild.java | 15 ++ .../core/models/database/AChannel.java | 9 - .../core/models/database/AChannelType.java | 14 +- .../core/models/database/AConfig.java | 4 + .../core/service/ChannelService.java | 14 +- .../abstracto/core/service/ConfigService.java | 3 + .../abstracto/core/service/LockService.java | 7 + .../management/ChannelManagementService.java | 1 + .../management/ConfigManagementService.java | 2 + .../UserInServerManagementService.java | 3 + abstracto-application/executable/pom.xml | 6 + abstracto-application/pom.xml | 6 + .../help/setFloat_description_en_US.ftl} | 0 .../help/setFloat_long_help_en_US.ftl} | 0 .../help/setFloat_usage_en_US.ftl} | 0 .../help/setLong_description_en_US.ftl | 1 + .../setLong/help/setLong_long_help_en_US.ftl | 1 + .../core/setLong/help/setLong_usage_en_US.ftl | 1 + .../help/anonReply_description_en_US.ftl | 1 + .../help/anonReply_long_help_en_US.ftl | 1 + .../anonReply/help/anonReply_usage_en_US.ftl | 1 + .../close/help/close_description_en_US.ftl | 1 + .../close/help/close_long_help_en_US.ftl | 1 + .../modmail/close/help/close_usage_en_US.ftl | 1 + .../help/closeSilently_description_en_US.ftl | 1 + .../help/closeSilently_long_help_en_US.ftl | 1 + .../help/closeSilently_usage_en_US.ftl | 1 + .../help/contact_description_en_US.ftl | 1 + .../contact/help/contact_long_help_en_US.ftl | 1 + .../contact/help/contact_usage_en_US.ftl | 1 + .../reply/help/reply_description_en_US.ftl | 1 + .../reply/help/reply_long_help_en_US.ftl | 1 + .../modmail/reply/help/reply_usage_en_US.ftl | 1 + .../setModMailCategory_description_en_US.ftl | 1 + .../setModMailCategory_long_help_en_US.ftl | 1 + .../help/setModMailCategory_usage_en_US.ftl | 1 + .../en_US/config/modmail_feature_en_US.ftl | 1 + ..._chooser_server_list_description_en_US.ftl | 2 + ...dmail_thread_staff_message_title_en_US.ftl | 1 + ...odmail_thread_user_message_title_en_US.ftl | 1 + .../templating/templating-interface/pom.xml | 5 + pom.xml | 3 +- 99 files changed, 1506 insertions(+), 48 deletions(-) create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/pom.xml create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/AnonReply.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Close.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/CloseSilently.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Contact.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/ModMailModuleInterface.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Reply.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/SetModMailCategory.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/condition/RequiresModMailCondition.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeature.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeatures.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/listener/ModMailMessageListener.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailMessageRepository.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailThreadRepository.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadServiceBean.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementServiceBean.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementServiceBean.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/serverChooser/modmail_modal_server_choice_en_US.ftl create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_staff_message_embed_en_US.ftl create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_user_message_embed_en_US.ftl create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/welcomeMessage/modmail_welcome_message_en_US.ftl create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/pom.xml create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailMessage.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThread.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThreadState.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/dto/ServerChoice.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailModeratorReplyModel.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailServerChooserModel.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailUserReplyModel.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadService.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementService.java create mode 100644 abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementService.java create mode 100644 abstracto-application/abstracto-modules/modmail/pom.xml rename abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/{SetNumber.java => SetFloat.java} (95%) create mode 100644 abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetLong.java create mode 100644 abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/model/database/ALock.java create mode 100644 abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/LockRepository.java create mode 100644 abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/LockServiceBean.java create mode 100644 abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/command/models/TableLocks.java create mode 100644 abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/listener/PrivateMessageReceivedListener.java create mode 100644 abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/FullGuild.java create mode 100644 abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/LockService.java rename abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/{setNumber/help/setNumber_description_en_US.ftl => setFloat/help/setFloat_description_en_US.ftl} (100%) rename abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/{setNumber/help/setNumber_long_help_en_US.ftl => setFloat/help/setFloat_long_help_en_US.ftl} (100%) rename abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/{setNumber/help/setNumber_usage_en_US.ftl => setFloat/help/setFloat_usage_en_US.ftl} (100%) create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_long_help_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_usage_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/config/modmail_feature_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/listener/server_chooser/server_chooser_server_list_description_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_staff_message_title_en_US.ftl create mode 100644 abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_user_message_title_en_US.ftl diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/pom.xml b/abstracto-application/abstracto-modules/modmail/modmail-impl/pom.xml new file mode 100644 index 000000000..63fc4ca07 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/pom.xml @@ -0,0 +1,23 @@ + + + + dev.sheldan.abstracto.modules + utility + 1.0-SNAPSHOT + + 4.0.0 + + modmail-impl + + + + dev.sheldan.abstracto.modules + modmail-int + ${project.version} + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/AnonReply.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/AnonReply.java new file mode 100644 index 000000000..420ef6eb7 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/AnonReply.java @@ -0,0 +1,43 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.condition.CommandCondition; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.commands.condition.RequiresModMailCondition; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class AnonReply extends AbstractConditionableCommand { + + @Autowired + private RequiresModMailCondition requiresModMailCondition; + + @Override + public CommandResult execute(CommandContext commandContext) { + return null; + } + + @Override + public CommandConfiguration getConfiguration() { + return null; + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } + + @Override + public List getConditions() { + List conditions = super.getConditions(); + conditions.add(requiresModMailCondition); + return conditions; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Close.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Close.java new file mode 100644 index 000000000..acd34da6f --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Close.java @@ -0,0 +1,43 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.condition.CommandCondition; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.commands.condition.RequiresModMailCondition; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class Close extends AbstractConditionableCommand { + + @Autowired + private RequiresModMailCondition requiresModMailCondition; + + @Override + public CommandResult execute(CommandContext commandContext) { + return null; + } + + @Override + public CommandConfiguration getConfiguration() { + return null; + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } + + @Override + public List getConditions() { + List conditions = super.getConditions(); + conditions.add(requiresModMailCondition); + return conditions; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/CloseSilently.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/CloseSilently.java new file mode 100644 index 000000000..64a4d5d9d --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/CloseSilently.java @@ -0,0 +1,43 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.condition.CommandCondition; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.commands.condition.RequiresModMailCondition; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Component +public class CloseSilently extends AbstractConditionableCommand { + + @Autowired + private RequiresModMailCondition requiresModMailCondition; + + @Override + public CommandResult execute(CommandContext commandContext) { + return null; + } + + @Override + public CommandConfiguration getConfiguration() { + return null; + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } + + @Override + public List getConditions() { + List conditions = super.getConditions(); + conditions.add(requiresModMailCondition); + return conditions; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Contact.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Contact.java new file mode 100644 index 000000000..2f9c0c005 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Contact.java @@ -0,0 +1,28 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import org.springframework.stereotype.Component; + +@Component +public class Contact extends AbstractConditionableCommand { + @Override + public CommandResult execute(CommandContext commandContext) { + return null; + } + + @Override + public CommandConfiguration getConfiguration() { + return null; + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } + +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/ModMailModuleInterface.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/ModMailModuleInterface.java new file mode 100644 index 000000000..915fe0e18 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/ModMailModuleInterface.java @@ -0,0 +1,22 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.config.ModuleInfo; +import dev.sheldan.abstracto.core.command.config.ModuleInterface; +import org.springframework.stereotype.Component; + +@Component +public class ModMailModuleInterface implements ModuleInterface { + + public static final String MODMAIL = "modMail"; + + @Override + public ModuleInfo getInfo() { + return ModuleInfo.builder().name(MODMAIL).description("Commands to be used for modmail.").build(); + } + + + @Override + public String getParentModule() { + return "default"; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Reply.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Reply.java new file mode 100644 index 000000000..46aa83832 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/Reply.java @@ -0,0 +1,67 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.condition.CommandCondition; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.config.HelpInfo; +import dev.sheldan.abstracto.core.command.config.Parameter; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.commands.condition.RequiresModMailCondition; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.service.ModMailThreadService; +import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +@Component +public class Reply extends AbstractConditionableCommand { + + @Autowired + private RequiresModMailCondition requiresModMailCondition; + + @Autowired + private ModMailThreadService modMailThreadService; + + @Autowired + private ModMailThreadManagementService modMailThreadManagementService; + + @Override + public CommandResult execute(CommandContext commandContext) { + ModMailThread thread = modMailThreadManagementService.getByChannel(commandContext.getUserInitiatedContext().getChannel()); + modMailThreadService.relayMessageToDm(thread, commandContext.getMessage()); + return CommandResult.fromSuccess(); + } + + @Override + public CommandConfiguration getConfiguration() { + Parameter responseText = Parameter.builder().name("text").type(String.class).description("The text to reply with").build(); + List parameters = Arrays.asList(responseText); + HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); + return CommandConfiguration.builder() + .name("reply") + .module(ModMailModuleInterface.MODMAIL) + .parameters(parameters) + .help(helpInfo) + .templated(true) + .causesReaction(true) + .build(); + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } + + @Override + public List getConditions() { + List conditions = super.getConditions(); + conditions.add(requiresModMailCondition); + return conditions; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/SetModMailCategory.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/SetModMailCategory.java new file mode 100644 index 000000000..f6b185326 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/SetModMailCategory.java @@ -0,0 +1,52 @@ +package dev.sheldan.abstracto.modmail.commands; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.config.HelpInfo; +import dev.sheldan.abstracto.core.command.config.Parameter; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import dev.sheldan.abstracto.modmail.service.ModMailThreadService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +@Component +public class SetModMailCategory extends AbstractConditionableCommand { + + @Autowired + private ModMailThreadService modMailThreadService; + + @Override + public CommandResult execute(CommandContext commandContext) { + Long categoryId = (Long) commandContext.getParameters().getParameters().get(0); + modMailThreadService.setModMailCategoryTo(commandContext.getUserInitiatedContext().getServer(), categoryId); + return CommandResult.fromSuccess(); + } + + @Override + public CommandConfiguration getConfiguration() { + Parameter categoryId = Parameter.builder().name("categoryId").type(Long.class).description("The category id to be used for modmail.").build(); + List parameters = Arrays.asList(categoryId); + HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); + List aliases = Arrays.asList("modMailCat"); + return CommandConfiguration.builder() + .name("setModMailCategory") + .module(ModMailModuleInterface.MODMAIL) + .aliases(aliases) + .parameters(parameters) + .help(helpInfo) + .templated(true) + .causesReaction(true) + .build(); + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/condition/RequiresModMailCondition.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/condition/RequiresModMailCondition.java new file mode 100644 index 000000000..e69fd2a31 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/commands/condition/RequiresModMailCondition.java @@ -0,0 +1,26 @@ +package dev.sheldan.abstracto.modmail.commands.condition; + +import dev.sheldan.abstracto.core.command.Command; +import dev.sheldan.abstracto.core.command.condition.CommandCondition; +import dev.sheldan.abstracto.core.command.condition.ConditionResult; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class RequiresModMailCondition implements CommandCondition { + + @Autowired + private ModMailThreadManagementService modMailThreadManagementService; + + @Override + public ConditionResult shouldExecute(CommandContext commandContext, Command command) { + ModMailThread thread = modMailThreadManagementService.getByChannel(commandContext.getUserInitiatedContext().getChannel()); + if(thread != null) { + return ConditionResult.builder().result(true).build(); + } + return ConditionResult.builder().result(false).reason("Not in a mod mail thread.").build(); + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeature.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeature.java new file mode 100644 index 000000000..5fc2b3239 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeature.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.modmail.config; + +import dev.sheldan.abstracto.core.config.FeatureConfig; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import org.springframework.stereotype.Component; + +@Component +public class ModMailFeature implements FeatureConfig { + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeatures.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeatures.java new file mode 100644 index 000000000..8f3e18a8e --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/config/ModMailFeatures.java @@ -0,0 +1,18 @@ +package dev.sheldan.abstracto.modmail.config; + +import dev.sheldan.abstracto.core.config.FeatureEnum; + +public enum ModMailFeatures implements FeatureEnum { + MODMAIL("modmail"); + + private String key; + + ModMailFeatures(String key) { + this.key = key; + } + + @Override + public String getKey() { + return this.key; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/listener/ModMailMessageListener.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/listener/ModMailMessageListener.java new file mode 100644 index 000000000..efee69997 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/listener/ModMailMessageListener.java @@ -0,0 +1,52 @@ +package dev.sheldan.abstracto.modmail.listener; + +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.core.listener.PrivateMessageReceivedListener; +import dev.sheldan.abstracto.core.models.database.AUser; +import dev.sheldan.abstracto.core.service.management.UserManagementService; +import dev.sheldan.abstracto.modmail.config.ModMailFeature; +import dev.sheldan.abstracto.modmail.config.ModMailFeatures; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.service.ModMailThreadService; +import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; +import dev.sheldan.abstracto.templating.service.TemplateService; +import 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.Transactional; + +@Component +@Slf4j +public class ModMailMessageListener implements PrivateMessageReceivedListener { + + @Autowired + private ModMailThreadService modMailThreadService; + + @Autowired + private ModMailThreadManagementService modMailThreadManagementService; + + @Autowired + private UserManagementService userManagementService; + + + @Autowired + private TemplateService templateService; + + @Override + @Transactional + public void execute(Message message) { + AUser user = userManagementService.loadUser(message.getAuthor().getIdLong()); + ModMailThread existingThread = modMailThreadManagementService.getOpenModmailThreadForUser(user); + if(existingThread != null) { + modMailThreadService.relayMessageToModMailThread(existingThread, message); + } else { + modMailThreadService.createModMailPrompt(user, message.getChannel()); + } + } + + @Override + public FeatureEnum getFeature() { + return ModMailFeatures.MODMAIL; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailMessageRepository.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailMessageRepository.java new file mode 100644 index 000000000..d572d05ec --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailMessageRepository.java @@ -0,0 +1,9 @@ +package dev.sheldan.abstracto.modmail.repository; + +import dev.sheldan.abstracto.modmail.models.database.ModMailMessage; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ModMailMessageRepository extends JpaRepository { +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailThreadRepository.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailThreadRepository.java new file mode 100644 index 000000000..0dc2403dc --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/repository/ModMailThreadRepository.java @@ -0,0 +1,22 @@ +package dev.sheldan.abstracto.modmail.repository; + +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.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.models.database.ModMailThreadState; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ModMailThreadRepository extends JpaRepository { + ModMailThread findByChannel(AChannel channel); + List findByUser(AUserInAServer aUserInAServer); + ModMailThread findByUser_UserReferenceAndStateNot(AUser user, ModMailThreadState state); + List findByServerAndState(AServer server, ModMailThreadState state); + ModMailThread findByUserAndStateNot(AUserInAServer userInAServer, ModMailThreadState state); + List findByUserAndState(AUserInAServer userInAServer, ModMailThreadState state); +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadServiceBean.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadServiceBean.java new file mode 100644 index 000000000..a5296d4f1 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadServiceBean.java @@ -0,0 +1,243 @@ +package dev.sheldan.abstracto.modmail.service; + +import com.jagrosh.jdautilities.commons.waiter.EventWaiter; +import com.jagrosh.jdautilities.menu.ButtonMenu; +import dev.sheldan.abstracto.core.models.FullGuild; +import dev.sheldan.abstracto.core.models.FullUser; +import dev.sheldan.abstracto.core.models.cache.CachedReaction; +import dev.sheldan.abstracto.core.models.database.*; +import dev.sheldan.abstracto.core.service.BotService; +import dev.sheldan.abstracto.core.service.ChannelService; +import dev.sheldan.abstracto.core.service.ConfigService; +import dev.sheldan.abstracto.core.service.management.ChannelManagementService; +import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.models.dto.ServerChoice; +import dev.sheldan.abstracto.modmail.models.template.ModMailModeratorReplyModel; +import dev.sheldan.abstracto.modmail.models.template.ModMailServerChooserModel; +import dev.sheldan.abstracto.modmail.service.management.ModMailMessageManagementService; +import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; +import dev.sheldan.abstracto.templating.model.MessageToSend; +import dev.sheldan.abstracto.templating.service.TemplateService; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.entities.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +@Component +@Slf4j +public class ModMailThreadServiceBean implements ModMailThreadService { + + public static final String MODMAIL_CATEGORY = "modmailCategory"; + @Autowired + private ModMailThreadManagementService modMailThreadManagementService; + + @Autowired + private ConfigService configService; + + @Autowired + private ChannelService channelService; + + @Autowired + private ChannelManagementService channelManagementService; + + @Autowired + private UserInServerManagementService userInServerManagementService; + + @Autowired + private BotService botService; + + @Autowired + private TemplateService templateService; + + @Autowired + private ModMailMessageManagementService modMailMessageManagementService; + + @Autowired + private ModMailThreadServiceBean self; + + private List NUMBER_EMOJI = Arrays.asList("\u0031\u20e3", "\u0032\u20e3", "\u0033\u20e3", + "\u0034\u20e3", "\u0035\u20e3", "\u0036\u20e3", + "\u0037\u20e3", "\u0038\u20e3", "\u0039\u20e3", + "\u0040\u20e3"); + + + @Override + public void createModMailThreadForUser(FullUser aUserInAServer) { + Long categoryId = configService.getLongValue(MODMAIL_CATEGORY, aUserInAServer.getAUserInAServer().getServerReference().getId()); + User user = aUserInAServer.getMember().getUser(); + CompletableFuture textChannel = channelService.createTextChannel(user.getName() + user.getDiscriminator(), aUserInAServer.getAUserInAServer().getServerReference(), categoryId); + + textChannel.thenAccept(channel -> { + self.createThreadObject(channel, aUserInAServer); + self.sendWelcomeMessage(channel, aUserInAServer); + }); + } + + @Transactional + public void createThreadObject(TextChannel channel, FullUser user) { + AChannel channel2 = channelManagementService.createChannel(channel.getIdLong(), AChannelType.TEXT, user.getAUserInAServer().getServerReference()); + log.info("Creating mod mail thread in channel {} with db channel {}", channel.getIdLong(), channel2.getId()); + modMailThreadManagementService.createModMailThread(user.getAUserInAServer(), channel2); + } + + @Override + public boolean hasOpenThread(AUserInAServer aUserInAServer) { + return modMailThreadManagementService.getOpenModmailThreadForUser(aUserInAServer) != null; + } + + @Override + public boolean hasOpenThread(AUser user) { + return modMailThreadManagementService.getOpenModmailThreadForUser(user) != null; + } + + @Override + public void setModMailCategoryTo(AServer server, Long categoryId) { + configService.setLongValue(MODMAIL_CATEGORY, server.getId(), categoryId); + } + + @Override + public void createModMailPrompt(AUser user, MessageChannel channel) { + List knownServers = userInServerManagementService.getUserInAllServers(user.getId()); + if(knownServers.size() > 0) { + List availableGuilds = new ArrayList<>(); + HashMap choices = new HashMap<>(); + for (int i = 0; i < knownServers.size(); i++) { + AUserInAServer aUserInAServer = knownServers.get(i); + AServer serverReference = aUserInAServer.getServerReference(); + FullGuild guild = FullGuild + .builder() + .guild(botService.getGuildByIdNullable(serverReference.getId())) + .server(serverReference) + .build(); + String reactionEmote = NUMBER_EMOJI.get(i); + ServerChoice serverChoice = ServerChoice.builder().guild(guild).reactionEmote(reactionEmote).build(); + choices.put(reactionEmote, aUserInAServer); + availableGuilds.add(serverChoice); + } + ModMailServerChooserModel modMailServerChooserModel = ModMailServerChooserModel + .builder() + .commonGuilds(availableGuilds) + .build(); + + String text = templateService.renderTemplate("modmail_modal_server_choice", modMailServerChooserModel); + // todo dont instantiate directly + EventWaiter waiter = new EventWaiter(); + botService.getInstance().addEventListener(waiter); + ButtonMenu menu = new ButtonMenu.Builder() + .setChoices(choices.keySet().toArray(new String[0])) + .setEventWaiter(waiter) + .setDescription(text) + .setAction(reactionEmote -> { + AUserInAServer chosenServer = choices.get(reactionEmote.getEmoji()); + Member memberInServer = botService.getMemberInServer(chosenServer); + FullUser fullUser = FullUser.builder().member(memberInServer).aUserInAServer(chosenServer).build(); + self.createModMailThreadForUser(fullUser); + botService.getInstance().removeEventListener(waiter); + }) + .build(); + menu.display(channel); + } + } + + @Override + public void sendWelcomeMessage(TextChannel channel, FullUser aUserInAServer) { + String text = templateService.renderTemplate("modmail_welcome_message", new Object()); + channel.sendMessage(text).queue(); + } + + @Override + public void relayMessageToModMailThread(ModMailThread modMailThread, Message message) { + Optional textChannelFromServer = botService.getTextChannelFromServer(modMailThread.getServer().getId(), modMailThread.getChannel().getId()); + if(textChannelFromServer.isPresent()) { + TextChannel textChannel = textChannelFromServer.get(); + self.sendUserReply(textChannel, modMailThread, message); + } + } + + @Transactional + public void sendUserReply(TextChannel textChannel, ModMailThread modMailThread, Message message) { + FullUser fullUser = FullUser + .builder() + .aUserInAServer(modMailThread.getUser()) + .member(botService.getMemberInServer(modMailThread.getUser())) + .build(); + ModMailModeratorReplyModel modMailUserReplyModel = ModMailModeratorReplyModel + .builder() + .modMailThread(modMailThread) + .postedMessage(message) + .threadUser(fullUser) + .build(); + MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_moderator_message", modMailUserReplyModel); + List> completableFutures = channelService.sendMessageToEndInTextChannel(messageToSend, textChannel); + List messages = new ArrayList<>(); + completableFutures.forEach(messageCompletableFuture -> { + try { + Message messageToAdd = messageCompletableFuture.get(); + messages.add(messageToAdd); + } catch (InterruptedException | ExecutionException e) { + log.error("Error while executing future to retrieve reaction.", e); + } + self.saveMessageIds(messages, modMailThread, modMailThread.getUser(), false); + }); + } + + @Override + public void relayMessageToDm(ModMailThread modMailThread, Message message) { + User userById = botService.getInstance().getUserById(modMailThread.getUser().getUserReference().getId()); + if(userById != null) { + userById.openPrivateChannel().queue(privateChannel -> { + self.sendReply(modMailThread, message, privateChannel); + }); + } + } + + @Transactional + public void sendReply(ModMailThread modMailThread, Message message, PrivateChannel privateChannel) { + AUserInAServer moderator = userInServerManagementService.loadUser(message.getMember()); + Member userInGuild = botService.getMemberInServer(modMailThread.getUser()); + FullUser moderatorUser = FullUser + .builder() + .aUserInAServer(moderator) + .member(message.getMember()) + .build(); + FullUser fullThreadUser = FullUser + .builder() + .aUserInAServer(modMailThread.getUser()) + .member(userInGuild) + .build(); + ModMailModeratorReplyModel modMailUserReplyModel = ModMailModeratorReplyModel + .builder() + .modMailThread(modMailThread) + .postedMessage(message) + .threadUser(fullThreadUser) + .moderator(moderatorUser) + .build(); + MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_staff_message", modMailUserReplyModel); + List> completableFutures = channelService.sendMessageToEndInTextChannel(messageToSend, privateChannel); + CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> { + List messages = new ArrayList<>(); + completableFutures.forEach(messageCompletableFuture -> { + try { + Message messageToAdd = messageCompletableFuture.get(); + messages.add(messageToAdd); + } catch (InterruptedException | ExecutionException e) { + log.error("Error while executing send message to reply to user.", e); + } + }); + self.saveMessageIds(messages, modMailThread, moderator, false); + }); + } + + @Transactional + public void saveMessageIds(List messages, ModMailThread modMailThread, AUserInAServer author, Boolean anonymous) { + messages.forEach(message -> { + modMailMessageManagementService.addMessageToThread(modMailThread, message, author, false); + }); + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementServiceBean.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementServiceBean.java new file mode 100644 index 000000000..8c26929de --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementServiceBean.java @@ -0,0 +1,30 @@ +package dev.sheldan.abstracto.modmail.service.management; + +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.modmail.models.database.ModMailMessage; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.repository.ModMailMessageRepository; +import net.dv8tion.jda.api.entities.Message; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class ModMailMessageManagementServiceBean implements ModMailMessageManagementService { + + @Autowired + private ModMailMessageRepository modMailMessageRepository; + + @Override + public ModMailMessage addMessageToThread(ModMailThread modMailThread, Message message, AUserInAServer author, Boolean anonymous) { + ModMailMessage modMailMessage = ModMailMessage + .builder() + .author(author) + .messageId(message.getIdLong()) + .threadReference(modMailThread) + .anonymous(anonymous) + .build(); + + modMailMessageRepository.save(modMailMessage); + return modMailMessage; + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementServiceBean.java b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementServiceBean.java new file mode 100644 index 000000000..a301a2b7a --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementServiceBean.java @@ -0,0 +1,70 @@ +package dev.sheldan.abstracto.modmail.service.management; + +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.models.database.ModMailThread; +import dev.sheldan.abstracto.modmail.models.database.ModMailThreadState; +import dev.sheldan.abstracto.modmail.repository.ModMailThreadRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.List; + +@Component +public class ModMailThreadManagementServiceBean implements ModMailThreadManagementService { + + @Autowired + private ModMailThreadRepository modMailThreadRepository; + + @Autowired + private ChannelManagementService channelManagementService; + + @Override + public ModMailThread getByChannelId(Long channelId) { + AChannel channel = channelManagementService.loadChannel(channelId); + return getByChannel(channel); + } + + @Override + public ModMailThread getByChannel(AChannel channel) { + return modMailThreadRepository.findByChannel(channel); + } + + @Override + public List getThreadByUserAndState(AUserInAServer userInAServer, ModMailThreadState state) { + return modMailThreadRepository.findByUserAndState(userInAServer, state); + } + + @Override + public ModMailThread getOpenModmailThreadForUser(AUserInAServer userInAServer) { + return modMailThreadRepository.findByUserAndStateNot(userInAServer, ModMailThreadState.CLOSED); + } + + @Override + public ModMailThread getOpenModmailThreadForUser(AUser user) { + return modMailThreadRepository.findByUser_UserReferenceAndStateNot(user, ModMailThreadState.CLOSED); + } + + @Override + public List getModMailThreadForUser(AUserInAServer aUserInAServer) { + return modMailThreadRepository.findByUser(aUserInAServer); + } + + @Override + public void createModMailThread(AUserInAServer userInAServer, AChannel channel) { + ModMailThread thread = ModMailThread + .builder() + .channel(channel) + .created(Instant.now()) + .user(userInAServer) + .server(userInAServer.getServerReference()) + .state(ModMailThreadState.INITIAL) + .updated(Instant.now()) + .build(); + + modMailThreadRepository.save(thread); + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/serverChooser/modmail_modal_server_choice_en_US.ftl b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/serverChooser/modmail_modal_server_choice_en_US.ftl new file mode 100644 index 000000000..e40aba800 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/serverChooser/modmail_modal_server_choice_en_US.ftl @@ -0,0 +1,5 @@ +<#include "server_chooser_server_list_description"> + +<#list commonGuilds as guild> + ${guild.reactionEmote} ${guild.guild.guild.name} + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_staff_message_embed_en_US.ftl b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_staff_message_embed_en_US.ftl new file mode 100644 index 000000000..aeacafc66 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_staff_message_embed_en_US.ftl @@ -0,0 +1,20 @@ +{ + "author": { + "name": "${threadUser.member.effectiveName}", + "avatar": "${threadUser.member.user.effectiveAvatarUrl}" + }, + "title": { + "title": "<#include "modmail_thread_staff_message_title">" + }, + "color" : { + "r": 200, + "g": 0, + "b": 255 + }, + <#if postedMessage.contentRaw?has_content> + "description": "${postedMessage.contentRaw}" + + <#if postedMessage.attachments?size gt 0> + ,"imageUrl": "${postedMessage.attachments[0].proxyUrl}" + +} \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_user_message_embed_en_US.ftl b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_user_message_embed_en_US.ftl new file mode 100644 index 000000000..a8bd51305 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/threadContent/modmail_user_message_embed_en_US.ftl @@ -0,0 +1,20 @@ +{ + "author": { + "name": "${threadUser.member.effectiveName}", + "avatar": "${threadUser.member.user.effectiveAvatarUrl}" + }, + "title": { + "title": "<#include "modmail_thread_user_message_title">" + }, + "color" : { + "r": 200, + "g": 0, + "b": 255 + }, + <#if postedMessage.contentRaw?has_content> + "description": "${postedMessage.contentRaw}" + + <#if postedMessage.attachments?size gt 0> + ,"imageUrl": "${postedMessage.attachments[0].proxyUrl}" + +} \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/welcomeMessage/modmail_welcome_message_en_US.ftl b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/welcomeMessage/modmail_welcome_message_en_US.ftl new file mode 100644 index 000000000..dd117fc58 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-impl/src/main/resources/templates/welcomeMessage/modmail_welcome_message_en_US.ftl @@ -0,0 +1 @@ +You opened a mod mail thread on the server reply in this channel to send messages to a staff only channel. \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/pom.xml b/abstracto-application/abstracto-modules/modmail/modmail-int/pom.xml new file mode 100644 index 000000000..2779c72e8 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/pom.xml @@ -0,0 +1,22 @@ + + + + dev.sheldan.abstracto.modules + utility + 1.0-SNAPSHOT + + 4.0.0 + + modmail-int + + + + dev.sheldan.abstracto.templating + templating-interface + ${project.version} + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailMessage.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailMessage.java new file mode 100644 index 000000000..3c23a0d8a --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailMessage.java @@ -0,0 +1,32 @@ +package dev.sheldan.abstracto.modmail.models.database; + +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import lombok.*; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import javax.persistence.*; + +@Builder +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "modmail_messages") +@Cacheable +@Getter +@Setter +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +public class ModMailMessage { + + @Id + private Long messageId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "modmail_message_author", nullable = false) + private AUserInAServer author; + + @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) + @JoinColumn(name = "threadReference", nullable = false) + private ModMailThread threadReference; + + private Boolean anonymous; +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThread.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThread.java new file mode 100644 index 000000000..d5df152c4 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThread.java @@ -0,0 +1,62 @@ +package dev.sheldan.abstracto.modmail.models.database; + +import dev.sheldan.abstracto.core.models.database.*; +import lombok.*; +import net.dv8tion.jda.api.entities.ChannelType; +import org.hibernate.annotations.CacheConcurrencyStrategy; + +import javax.persistence.*; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +@Builder +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "modmail_threads") +@Cacheable +@Getter +@Setter +@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) +public class ModMailThread { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "modmail_user", nullable = false) + private AUserInAServer user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "modmail_thread_channel", nullable = false) + private AChannel channel; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "modmail_thread_server", nullable = false) + private AServer server; + + @Column + private Instant created; + + @Column + private Instant updated; + + @Column + private Instant closed; + + @OneToMany( + fetch = FetchType.LAZY, + cascade = {CascadeType.PERSIST, CascadeType.MERGE}, + orphanRemoval = true) + @JoinColumn(name = "threadReference") + @Builder.Default + @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) + private List messages = new ArrayList<>(); + + @Enumerated(EnumType.STRING) + @Column + private ModMailThreadState state; + +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThreadState.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThreadState.java new file mode 100644 index 000000000..0b09e2ebb --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/database/ModMailThreadState.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.modmail.models.database; + +public enum ModMailThreadState { + INITIAL, USER_REPLIED, MOD_REPLIED, CLOSED, CLOSING; + + public static ModMailThreadState getState(ModMailThreadState type) { + switch (type) { + case INITIAL: return ModMailThreadState.INITIAL; + case USER_REPLIED: return ModMailThreadState.USER_REPLIED; + case CLOSED: return ModMailThreadState.CLOSED; + case CLOSING: return ModMailThreadState.CLOSING; + default: + case MOD_REPLIED: return ModMailThreadState.MOD_REPLIED; + } + } +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/dto/ServerChoice.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/dto/ServerChoice.java new file mode 100644 index 000000000..278f68791 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/dto/ServerChoice.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.modmail.models.dto; + +import dev.sheldan.abstracto.core.models.FullGuild; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class ServerChoice { + private FullGuild guild; + private String reactionEmote; +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailModeratorReplyModel.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailModeratorReplyModel.java new file mode 100644 index 000000000..4df512247 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailModeratorReplyModel.java @@ -0,0 +1,18 @@ +package dev.sheldan.abstracto.modmail.models.template; + +import dev.sheldan.abstracto.core.models.FullUser; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Message; + +@Getter +@Setter +@Builder +public class ModMailModeratorReplyModel { + private FullUser threadUser; + private FullUser moderator; + private Message postedMessage; + private ModMailThread modMailThread; +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailServerChooserModel.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailServerChooserModel.java new file mode 100644 index 000000000..9147b790b --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailServerChooserModel.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.modmail.models.template; + +import dev.sheldan.abstracto.modmail.models.dto.ServerChoice; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Builder +public class ModMailServerChooserModel { + private List commonGuilds; +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailUserReplyModel.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailUserReplyModel.java new file mode 100644 index 000000000..3cc4b2477 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/models/template/ModMailUserReplyModel.java @@ -0,0 +1,17 @@ +package dev.sheldan.abstracto.modmail.models.template; + +import dev.sheldan.abstracto.core.models.FullUser; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Message; + +@Getter +@Setter +@Builder +public class ModMailUserReplyModel { + private FullUser threadUser; + private Message postedMessage; + private ModMailThread modMailThread; +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadService.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadService.java new file mode 100644 index 000000000..93080d5d8 --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/ModMailThreadService.java @@ -0,0 +1,22 @@ +package dev.sheldan.abstracto.modmail.service; + + +import dev.sheldan.abstracto.core.models.FullUser; +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.modmail.models.database.ModMailThread; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; +import net.dv8tion.jda.api.entities.TextChannel; + +public interface ModMailThreadService { + void createModMailThreadForUser(FullUser userInAServer); + boolean hasOpenThread(AUserInAServer aUserInAServer); + boolean hasOpenThread(AUser user); + void setModMailCategoryTo(AServer server, Long categoryId); + void createModMailPrompt(AUser user, MessageChannel messageChannel); + void sendWelcomeMessage(TextChannel channel, FullUser aUserInAServer); + void relayMessageToModMailThread(ModMailThread modMailThread, Message message); + void relayMessageToDm(ModMailThread modMailThread, Message message); +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementService.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementService.java new file mode 100644 index 000000000..273ca69fa --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailMessageManagementService.java @@ -0,0 +1,10 @@ +package dev.sheldan.abstracto.modmail.service.management; + +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.modmail.models.database.ModMailMessage; +import dev.sheldan.abstracto.modmail.models.database.ModMailThread; +import net.dv8tion.jda.api.entities.Message; + +public interface ModMailMessageManagementService { + ModMailMessage addMessageToThread(ModMailThread modMailThread, Message message, AUserInAServer author, Boolean anonymous); +} diff --git a/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementService.java b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementService.java new file mode 100644 index 000000000..1d614716e --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/modmail-int/src/main/java/dev/sheldan/abstracto/modmail/service/management/ModMailThreadManagementService.java @@ -0,0 +1,21 @@ +package dev.sheldan.abstracto.modmail.service.management; + +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; +import dev.sheldan.abstracto.modmail.models.database.ModMailThreadState; +import net.dv8tion.jda.api.entities.TextChannel; + +import java.util.List; + +public interface ModMailThreadManagementService { + ModMailThread getByChannelId(Long channelId); + ModMailThread getByChannel(AChannel channel); + List getThreadByUserAndState(AUserInAServer userInAServer, ModMailThreadState state); + ModMailThread getOpenModmailThreadForUser(AUserInAServer userInAServer); + ModMailThread getOpenModmailThreadForUser(AUser user); + List getModMailThreadForUser(AUserInAServer aUserInAServer); + void createModMailThread(AUserInAServer userInAServer, AChannel channel); + +} diff --git a/abstracto-application/abstracto-modules/modmail/pom.xml b/abstracto-application/abstracto-modules/modmail/pom.xml new file mode 100644 index 000000000..4e26d118f --- /dev/null +++ b/abstracto-application/abstracto-modules/modmail/pom.xml @@ -0,0 +1,29 @@ + + + + dev.sheldan.abstracto + abstracto-modules + 1.0-SNAPSHOT + + 4.0.0 + + dev.sheldan.abstracto.modules + modmail + pom + + + modmail-int + modmail-impl + + + + + dev.sheldan.abstracto.core + core-interface + ${project.version} + compile + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/pom.xml b/abstracto-application/abstracto-modules/pom.xml index 4f75f0029..94bb2bd2f 100644 --- a/abstracto-application/abstracto-modules/pom.xml +++ b/abstracto-application/abstracto-modules/pom.xml @@ -15,6 +15,7 @@ moderation utility experience-tracking + modmail diff --git a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/listener/starboard/StarboardPostDeletedListener.java b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/listener/starboard/StarboardPostDeletedListener.java index 1d13d1840..eea1271c5 100644 --- a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/listener/starboard/StarboardPostDeletedListener.java +++ b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/listener/starboard/StarboardPostDeletedListener.java @@ -24,7 +24,8 @@ public class StarboardPostDeletedListener implements MessageDeletedListener { Optional byStarboardPostId = starboardPostManagementService.findByStarboardPostId(messageBefore.getMessageId()); if(byStarboardPostId.isPresent()) { StarboardPost post = byStarboardPostId.get(); - log.info("Removing starboard post: message {}, channel {}, server {}, because the message was deleted", post.getPostMessageId(), post.getSourceChanel().getId(), post.getAuthor().getId()); + log.info("Removing starboard post: message {}, channel {}, server {}, because the message was deleted", + post.getPostMessageId(), post.getSourceChanel().getId(), post.getAuthor().getUserReference().getId()); starboardPostManagementService.setStarboardPostIgnored(messageBefore.getMessageId(), true); } } diff --git a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/StarboardPostManagementServiceBean.java b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/StarboardPostManagementServiceBean.java index c856c7830..411c07f6d 100644 --- a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/StarboardPostManagementServiceBean.java +++ b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/StarboardPostManagementServiceBean.java @@ -25,7 +25,7 @@ public class StarboardPostManagementServiceBean implements StarboardPostManageme public StarboardPost createStarboardPost(CachedMessage starredMessage, AUserInAServer starredUser, AUserInAServer starringUser, AServerAChannelMessage starboardPost) { StarboardPost post = StarboardPost .builder() - .author(starredUser.getUserReference()) + .author(starredUser) .postMessageId(starredMessage.getMessageId()) .starboardMessageId(starboardPost.getMessageId()) .starboardChannel(starboardPost.getChannel()) diff --git a/abstracto-application/abstracto-modules/utility/utility-int/src/main/java/dev/sheldan/abstracto/utility/models/database/StarboardPost.java b/abstracto-application/abstracto-modules/utility/utility-int/src/main/java/dev/sheldan/abstracto/utility/models/database/StarboardPost.java index b3a90a361..fbd019a2f 100644 --- a/abstracto-application/abstracto-modules/utility/utility-int/src/main/java/dev/sheldan/abstracto/utility/models/database/StarboardPost.java +++ b/abstracto-application/abstracto-modules/utility/utility-int/src/main/java/dev/sheldan/abstracto/utility/models/database/StarboardPost.java @@ -1,7 +1,7 @@ package dev.sheldan.abstracto.utility.models.database; 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 lombok.*; import org.hibernate.annotations.CacheConcurrencyStrategy; @@ -27,7 +27,7 @@ public class StarboardPost { @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "poster", nullable = false) - private AUser author; + private AUserInAServer author; @Column private Long starboardMessageId; diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandConfigListener.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandConfigListener.java index 148dc4b39..d0371fd6f 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandConfigListener.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandConfigListener.java @@ -26,9 +26,11 @@ public class CommandConfigListener implements ServerConfigListener { @Override public void updateServerConfig(AServer server) { commandList.forEach(command -> { - ACommand aCommand = commandManagementService.findCommandByName(command.getConfiguration().getName()); - if(!commandInServerManagementService.doesCommandExistInServer(aCommand, server)) { - commandInServerManagementService.crateCommandInServer(aCommand, server); + if(command.getConfiguration() != null) { + ACommand aCommand = commandManagementService.findCommandByName(command.getConfiguration().getName()); + if(!commandInServerManagementService.doesCommandExistInServer(aCommand, server)) { + commandInServerManagementService.crateCommandInServer(aCommand, server); + } } }); } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandCreationListener.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandCreationListener.java index eadff86ac..306621729 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandCreationListener.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/config/CommandCreationListener.java @@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.Command; import dev.sheldan.abstracto.core.command.service.CommandService; import dev.sheldan.abstracto.core.command.service.management.FeatureManagementService; import dev.sheldan.abstracto.core.service.FeatureFlagService; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.EventListener; @@ -13,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional; import java.util.List; @Component +@Slf4j public class CommandCreationListener { @Autowired @@ -38,6 +40,10 @@ public class CommandCreationListener { } }); commandList.forEach(command -> { + if(command.getConfiguration() == null) { + log.warn("Command {} has null configuration.", command); + return; + } if(!commandService.doesCommandExist(command.getConfiguration().getName())) { commandService.createCommand(command.getConfiguration().getName(), command.getConfiguration().getModule(), command.getFeature()); } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandManager.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandManager.java index 81dc11803..d167b54dd 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandManager.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandManager.java @@ -33,6 +33,9 @@ public class CommandManager implements CommandRegistry { public Command findCommandByParameters(String name, UnParsedCommandParameter unParsedCommandParameter) { Optional commandOptional = commands.stream().filter((Command o )-> { CommandConfiguration commandConfiguration = o.getConfiguration(); + if(commandConfiguration == null) { + return false; + } if(!commandNameMatches(name, commandConfiguration)) { return false; } @@ -88,7 +91,8 @@ public class CommandManager implements CommandRegistry { public List getAllCommandsFromModule(ModuleInterface moduleInterface) { List commandsFromModule = new ArrayList<>(); this.getAllCommands().forEach(command -> { - if(command.getConfiguration().getModule().equals(moduleInterface.getInfo().getName())){ + CommandConfiguration configuration = command.getConfiguration(); + if(configuration != null && configuration.getModule().equals(moduleInterface.getInfo().getName())){ commandsFromModule.add(command); } }); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandServiceBean.java index 97cef6b67..52768c10a 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/service/CommandServiceBean.java @@ -11,10 +11,12 @@ import dev.sheldan.abstracto.core.config.FeatureEnum; import dev.sheldan.abstracto.core.models.database.AFeature; import dev.sheldan.abstracto.core.models.database.ARole; import dev.sheldan.abstracto.core.models.database.AServer; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component +@Slf4j public class CommandServiceBean implements CommandService { @Autowired @@ -32,6 +34,10 @@ public class CommandServiceBean implements CommandService { @Override public ACommand createCommand(String name, String moduleName, FeatureEnum featureEnum) { AModule module = moduleManagementService.getOrCreate(moduleName); + if(featureEnum == null) { + log.warn("Command {} in module {} has no feature.", name, moduleName); + return null; + } AFeature feature = featureManagementService.getFeature(featureEnum.getKey()); return commandManagementService.createCommand(name, module, feature); } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetNumber.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetFloat.java similarity index 95% rename from abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetNumber.java rename to abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetFloat.java index d82c564f5..aa84a6926 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetNumber.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetFloat.java @@ -16,7 +16,7 @@ import java.util.Arrays; import java.util.List; @Component -public class SetNumber extends AbstractConditionableCommand { +public class SetFloat extends AbstractConditionableCommand { @Autowired private ConfigService configService; @@ -37,7 +37,7 @@ public class SetNumber extends AbstractConditionableCommand { List parameters = Arrays.asList(channelGroupName, channelToAdd); HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); return CommandConfiguration.builder() - .name("setNumber") + .name("setFloat") .module(ConfigModuleInterface.CONFIG) .parameters(parameters) .templated(true) diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetLong.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetLong.java new file mode 100644 index 000000000..1f1e79a15 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/commands/config/SetLong.java @@ -0,0 +1,53 @@ +package dev.sheldan.abstracto.core.commands.config; + +import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand; +import dev.sheldan.abstracto.core.command.config.CommandConfiguration; +import dev.sheldan.abstracto.core.command.config.HelpInfo; +import dev.sheldan.abstracto.core.command.config.Parameter; +import dev.sheldan.abstracto.core.command.execution.CommandContext; +import dev.sheldan.abstracto.core.command.execution.CommandResult; +import dev.sheldan.abstracto.core.config.FeatureEnum; +import dev.sheldan.abstracto.core.config.features.CoreFeatures; +import dev.sheldan.abstracto.core.service.ConfigService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +@Component +public class SetLong extends AbstractConditionableCommand { + + @Autowired + private ConfigService configService; + + @Override + public CommandResult execute(CommandContext commandContext) { + String key = (String) commandContext.getParameters().getParameters().get(0); + Long value = (Long) commandContext.getParameters().getParameters().get(1); + configService.setLongValue(key, commandContext.getGuild().getIdLong(), value); + + return CommandResult.fromSuccess(); + } + + @Override + public CommandConfiguration getConfiguration() { + Parameter channelGroupName = Parameter.builder().name("key").type(String.class).description("The key to change.").build(); + Parameter channelToAdd = Parameter.builder().name("value").type(Long.class).description("The numeric value to use for the config.").build(); + List parameters = Arrays.asList(channelGroupName, channelToAdd); + HelpInfo helpInfo = HelpInfo.builder().templated(true).build(); + return CommandConfiguration.builder() + .name("setLong") + .module(ConfigModuleInterface.CONFIG) + .parameters(parameters) + .templated(true) + .help(helpInfo) + .causesReaction(true) + .build(); + } + + @Override + public FeatureEnum getFeature() { + return CoreFeatures.CORE_FEATURE; + } +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/ChannelListener.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/ChannelListener.java index 612840358..fb132ff3a 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/ChannelListener.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/ChannelListener.java @@ -39,7 +39,7 @@ public class ChannelListener extends ListenerAdapter { log.info("Handling channel created event. Channel {}, Server {}", event.getChannel().getIdLong(), event.getGuild().getIdLong()); AServer serverObject = serverRepository.getOne(event.getGuild().getIdLong()); TextChannel createdChannel = event.getChannel(); - AChannelType type = AChannel.getAChannelType(createdChannel.getType()); + AChannelType type = AChannelType.getAChannelType(createdChannel.getType()); channelManagementService.createChannel(createdChannel.getIdLong(), type, serverObject); } } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/MessageReceivedListenerBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/MessageReceivedListenerBean.java index 27a957ccc..93bdb359a 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/MessageReceivedListenerBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/listener/MessageReceivedListenerBean.java @@ -1,14 +1,15 @@ package dev.sheldan.abstracto.core.listener; import dev.sheldan.abstracto.core.config.FeatureConfig; +import dev.sheldan.abstracto.core.service.BotService; import dev.sheldan.abstracto.core.service.FeatureFlagService; import dev.sheldan.abstracto.core.service.MessageCache; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.events.message.priv.PrivateMessageReceivedEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; import javax.annotation.Nonnull; import java.util.List; @@ -23,9 +24,15 @@ public class MessageReceivedListenerBean extends ListenerAdapter { @Autowired private List listenerList; + @Autowired + private List privateMessageReceivedListeners; + @Autowired private FeatureFlagService featureFlagService; + @Autowired + private BotService botService; + @Override public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) { messageCache.putMessageInCache(event.getMessage()); @@ -42,5 +49,17 @@ public class MessageReceivedListenerBean extends ListenerAdapter { }); } - + @Override + public void onPrivateMessageReceived(@Nonnull PrivateMessageReceivedEvent event) { + if(event.getAuthor().getId().equals(botService.getInstance().getSelfUser().getId())) { + return; + } + privateMessageReceivedListeners.forEach(messageReceivedListener -> { + try { + messageReceivedListener.execute(event.getMessage()); + } catch (Exception e) { + log.error("Listener {} had exception when executing.", messageReceivedListener, e); + } + }); + } } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/model/database/ALock.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/model/database/ALock.java new file mode 100644 index 000000000..68c733b11 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/model/database/ALock.java @@ -0,0 +1,21 @@ +package dev.sheldan.abstracto.core.model.database; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@Table(name = "lock") +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Getter +public class ALock { + @Id + @Column(name = "id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/LockRepository.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/LockRepository.java new file mode 100644 index 000000000..75b2a09c1 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/LockRepository.java @@ -0,0 +1,18 @@ +package dev.sheldan.abstracto.core.repository; + +import dev.sheldan.abstracto.core.model.database.ALock; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Lock; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import javax.persistence.LockModeType; + +@Repository +public interface LockRepository extends JpaRepository { + + @Lock(LockModeType.PESSIMISTIC_WRITE) + @Query("select a from ALock a where a.id = :id") + ALock findArticleForRead(@Param("id") Long id); +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/UserInServerRepository.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/UserInServerRepository.java index 89ecddf56..dd050d1d1 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/UserInServerRepository.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/repository/UserInServerRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.jpa.repository.QueryHints; import org.springframework.stereotype.Repository; import javax.persistence.QueryHint; +import java.util.List; @Repository public interface UserInServerRepository extends JpaRepository { @@ -17,4 +18,7 @@ public interface UserInServerRepository extends JpaRepository findByUserReference(AUser user); } \ No newline at end of file diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ChannelServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ChannelServiceBean.java index 149ba0200..7f6815379 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ChannelServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ChannelServiceBean.java @@ -3,13 +3,11 @@ package dev.sheldan.abstracto.core.service; import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; import dev.sheldan.abstracto.core.exception.ChannelException; import dev.sheldan.abstracto.core.exception.GuildException; +import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.core.models.database.AChannel; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed; -import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.requests.restaction.MessageAction; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -33,7 +31,7 @@ public class ChannelServiceBean implements ChannelService { } @Override - public void sendTextInAChannel(String text, TextChannel channel) { + public void sendTextInAChannel(String text, MessageChannel channel) { sendTextInAChannelFuture(text, channel); } @@ -55,7 +53,7 @@ public class ChannelServiceBean implements ChannelService { } @Override - public CompletableFuture sendTextInAChannelFuture(String text, TextChannel channel) { + public CompletableFuture sendTextInAChannelFuture(String text, MessageChannel channel) { return channel.sendMessage(text).submit(); } @@ -77,7 +75,7 @@ public class ChannelServiceBean implements ChannelService { } @Override - public CompletableFuture sendEmbedInAChannelFuture(MessageEmbed embed, TextChannel channel) { + public CompletableFuture sendEmbedInAChannelFuture(MessageEmbed embed, MessageChannel channel) { return channel.sendMessage(embed).submit(); } @@ -91,7 +89,7 @@ public class ChannelServiceBean implements ChannelService { } @Override - public List> sendMessageToEndInTextChannel(MessageToSend messageToSend, TextChannel textChannel) { + public List> sendMessageToEndInTextChannel(MessageToSend messageToSend, MessageChannel textChannel) { String messageText = messageToSend.getMessage(); List> futures = new ArrayList<>(); if(StringUtils.isBlank(messageText)) { @@ -130,7 +128,7 @@ public class ChannelServiceBean implements ChannelService { } @Override - public void editMessageInAChannel(MessageToSend messageToSend, TextChannel channel, Long messageId) { + public void editMessageInAChannel(MessageToSend messageToSend, MessageChannel channel, Long messageId) { MessageAction messageAction; if(!StringUtils.isBlank(messageToSend.getMessage())) { messageAction = channel.editMessageById(messageId, messageToSend.getMessage()); @@ -146,4 +144,18 @@ public class ChannelServiceBean implements ChannelService { } messageAction.queue(); } + + @Override + public CompletableFuture createTextChannel(String name, AServer server, Long categoryId) { + Optional guildById = botService.getGuildById(server.getId()); + if(guildById.isPresent()) { + Guild guild = guildById.get(); + Category categoryById = guild.getCategoryById(categoryId); + if(categoryById != null) { + return categoryById.createTextChannel(name).submit(); + } + return null; + } + return null; + } } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ConfigServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ConfigServiceBean.java index 7f4bf4972..86143bbd1 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ConfigServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/ConfigServiceBean.java @@ -17,6 +17,11 @@ public class ConfigServiceBean implements ConfigService{ return getDoubleValue(name, serverId, 0D); } + @Override + public Long getLongValue(String name, Long serverId) { + return getLongValue(name, serverId, 0L); + } + @Override public Double getDoubleValue(String name, Long serverId, Double defaultValue) { AConfig config = configManagementService.loadConfig(serverId, name); @@ -35,6 +40,15 @@ public class ConfigServiceBean implements ConfigService{ return config.getStringValue(); } + @Override + public Long getLongValue(String name, Long serverId, Long defaultValue) { + AConfig config = configManagementService.loadConfig(serverId, name); + if(config == null) { + return defaultValue; + } + return config.getLongValue(); + } + @Override public void setDoubleValue(String name, Long serverId, Double value) { if(configManagementService.configExists(serverId, name)) { @@ -44,6 +58,15 @@ public class ConfigServiceBean implements ConfigService{ } } + @Override + public void setLongValue(String name, Long serverId, Long value) { + if(configManagementService.configExists(serverId, name)) { + configManagementService.setLongValue(serverId, name, value); + } else { + throw new ConfigurationException(String.format("Key %s does not exist.", name)); + } + } + @Override public void setStringValue(String name, Long serverId, String value) { if(configManagementService.configExists(serverId, name)) { diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/LockServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/LockServiceBean.java new file mode 100644 index 000000000..d27edabe0 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/LockServiceBean.java @@ -0,0 +1,19 @@ +package dev.sheldan.abstracto.core.service; + +import dev.sheldan.abstracto.core.command.models.TableLocks; +import dev.sheldan.abstracto.core.repository.LockRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class LockServiceBean implements LockService { + + @Autowired + private LockRepository lockRepository; + + @Override + public void lockTable(TableLocks toLock) { + int ordinal = toLock.ordinal(); + lockRepository.findArticleForRead((long) ordinal); + } +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/StartupServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/StartupServiceBean.java index a3a9bd09a..b1b7bb855 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/StartupServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/StartupServiceBean.java @@ -103,7 +103,7 @@ public class StartupServiceBean implements Startup { newChannels.forEach(aLong -> { GuildChannel channel1 = available.stream().filter(channel -> channel.getIdLong() == aLong).findFirst().get(); log.trace("Adding new channel: {}", aLong); - AChannelType type = AChannel.getAChannelType(channel1.getType()); + AChannelType type = AChannelType.getAChannelType(channel1.getType()); channelManagementService.createChannel(channel1.getIdLong(), type, existingServer); }); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementServiceBean.java index 7a6edafe7..f17f352ed 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementServiceBean.java @@ -1,9 +1,11 @@ package dev.sheldan.abstracto.core.service.management; +import dev.sheldan.abstracto.core.command.models.TableLocks; import dev.sheldan.abstracto.core.models.database.AChannel; import dev.sheldan.abstracto.core.models.database.AChannelType; import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.repository.ChannelRepository; +import dev.sheldan.abstracto.core.service.LockService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -15,6 +17,9 @@ public class ChannelManagementServiceBean implements ChannelManagementService { @Autowired private ChannelRepository repository; + @Autowired + private LockService lockService; + @Override public AChannel loadChannel(Long id) { return repository.getOne(id); @@ -22,15 +27,20 @@ public class ChannelManagementServiceBean implements ChannelManagementService { @Override public AChannel createChannel(Long id, AChannelType type, AServer server) { - log.info("Creating channel {} with type {}", id, type); - AChannel build = AChannel - .builder() - .id(id) - .type(type) - .server(server) - .deleted(false) - .build(); - return repository.save(build); + lockService.lockTable(TableLocks.CHANNELS); + if(!channelExists(id)) { + log.info("Creating channel {} with type {}", id, type); + AChannel build = AChannel + .builder() + .id(id) + .type(type) + .server(server) + .deleted(false) + .build(); + return repository.save(build); + } else { + return loadChannel(id); + } } @Override @@ -40,6 +50,11 @@ public class ChannelManagementServiceBean implements ChannelManagementService { return channel; } + @Override + public boolean channelExists(Long id) { + return repository.existsById(id); + } + @Override public void removeChannel(Long id) { log.info("Deleting channel {}", id); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementServiceBean.java index 7682dc9fe..71d16ecf6 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementServiceBean.java @@ -65,6 +65,19 @@ public class ConfigManagementServiceBean implements ConfigManagementService { return config; } + @Override + public AConfig createConfig(Long serverId, String name, Long value) { + AServer server = serverManagementService.loadOrCreate(serverId); + AConfig config = AConfig + .builder() + .longValue(value) + .server(server) + .name(name) + .build(); + configRepository.save(config); + return config; + } + @Override public AConfig createIfNotExists(Long serverId, String name, String value) { AConfig config = loadConfig(serverId, name); @@ -100,6 +113,13 @@ public class ConfigManagementServiceBean implements ConfigManagementService { return config; } + @Override + public AConfig setLongValue(Long serverId, String name, Long value) { + AConfig config = loadConfig(serverId, name); + config.setLongValue(value); + return config; + } + @Override public AConfig setStringValue(Long serverId, String name, String value) { AConfig config = loadConfig(serverId, name); diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementServiceBean.java index 157be0eca..60201bf2b 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementServiceBean.java @@ -9,6 +9,8 @@ import net.dv8tion.jda.api.entities.Member; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.List; + @Component @Slf4j public class UserInServerManagementServiceBean implements UserInServerManagementService { @@ -55,4 +57,10 @@ public class UserInServerManagementServiceBean implements UserInServerManagement userInServerRepository.save(aUserInAServer); return aUserInAServer; } + + @Override + public List getUserInAllServers(Long userId) { + AUser user = userManagementService.loadUser(userId); + return userInServerRepository.findByUserReference(user); + } } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/command/models/TableLocks.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/command/models/TableLocks.java new file mode 100644 index 000000000..d5f9462f3 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/command/models/TableLocks.java @@ -0,0 +1,5 @@ +package dev.sheldan.abstracto.core.command.models; + +public enum TableLocks { + CHANNELS +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/listener/PrivateMessageReceivedListener.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/listener/PrivateMessageReceivedListener.java new file mode 100644 index 000000000..fa18ee289 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/listener/PrivateMessageReceivedListener.java @@ -0,0 +1,7 @@ +package dev.sheldan.abstracto.core.listener; + +import net.dv8tion.jda.api.entities.Message; + +public interface PrivateMessageReceivedListener extends FeatureAware { + void execute(Message message); +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/FullGuild.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/FullGuild.java new file mode 100644 index 000000000..b1e6ca4e4 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/FullGuild.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.core.models; + +import dev.sheldan.abstracto.core.models.database.AServer; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Guild; + +@Setter +@Getter +@Builder +public class FullGuild { + private AServer server; + private Guild guild; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannel.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannel.java index 746860cbf..8a084b271 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannel.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannel.java @@ -43,15 +43,6 @@ public class AChannel implements SnowFlake { @Column private Boolean deleted; - public static AChannelType getAChannelType(ChannelType type) { - switch (type) { - case TEXT: return AChannelType.TEXT; - case PRIVATE: return AChannelType.DM; - case VOICE: return AChannelType.VOICE; - case CATEGORY: return AChannelType.CATEGORY; - default: return AChannelType.UNKOWN; - } - } @Override public boolean equals(Object o) { diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannelType.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannelType.java index 2182b8cdd..0f1d00173 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannelType.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AChannelType.java @@ -1,5 +1,17 @@ package dev.sheldan.abstracto.core.models.database; +import net.dv8tion.jda.api.entities.ChannelType; + public enum AChannelType { - TEXT, DM, VOICE, NEWS, CATEGORY, UNKOWN + TEXT, DM, VOICE, NEWS, CATEGORY, UNKOWN; + + public static AChannelType getAChannelType(ChannelType type) { + switch (type) { + case TEXT: return AChannelType.TEXT; + case PRIVATE: return AChannelType.DM; + case VOICE: return AChannelType.VOICE; + case CATEGORY: return AChannelType.CATEGORY; + default: return AChannelType.UNKOWN; + } + } } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AConfig.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AConfig.java index 554895c0b..9aec3938b 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AConfig.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/database/AConfig.java @@ -31,6 +31,10 @@ public class AConfig { @Setter private Double doubleValue; + @Column + @Setter + private Long longValue; + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "server_id", nullable = false) @Getter diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ChannelService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ChannelService.java index eb105bcb7..9c7a8c1b4 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ChannelService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ChannelService.java @@ -1,8 +1,10 @@ package dev.sheldan.abstracto.core.service; +import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.templating.model.MessageToSend; import dev.sheldan.abstracto.core.models.database.AChannel; import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.MessageChannel; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.TextChannel; @@ -12,14 +14,16 @@ import java.util.concurrent.CompletableFuture; public interface ChannelService { void sendTextInAChannel(String text, AChannel channel); - void sendTextInAChannel(String text, TextChannel channel); + void sendTextInAChannel(String text, MessageChannel channel); CompletableFuture sendTextInAChannelFuture(String text, AChannel channel); - CompletableFuture sendTextInAChannelFuture(String text, TextChannel channel); + CompletableFuture sendTextInAChannelFuture(String text, MessageChannel channel); CompletableFuture sendEmbedInAChannelFuture(MessageEmbed embed, AChannel channel); - CompletableFuture sendEmbedInAChannelFuture(MessageEmbed embed, TextChannel channel); + CompletableFuture sendEmbedInAChannelFuture(MessageEmbed embed, MessageChannel channel); List> sendMessageToEndInAChannel(MessageToSend messageToSend, AChannel channel); - List> sendMessageToEndInTextChannel(MessageToSend messageToSend, TextChannel textChannel); + List> sendMessageToEndInTextChannel(MessageToSend messageToSend, MessageChannel textChannel); Optional getTextChannelInGuild(Long serverId, Long channelId); void editMessageInAChannel(MessageToSend messageToSend, AChannel channel, Long messageId); - void editMessageInAChannel(MessageToSend messageToSend, TextChannel channel, Long messageId); + void editMessageInAChannel(MessageToSend messageToSend, MessageChannel channel, Long messageId); + + CompletableFuture createTextChannel(String name, AServer server, Long categoryId); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ConfigService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ConfigService.java index a07bcc0be..dd2529a69 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ConfigService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/ConfigService.java @@ -2,9 +2,12 @@ package dev.sheldan.abstracto.core.service; public interface ConfigService { Double getDoubleValue(String name, Long serverId); + Long getLongValue(String name, Long serverId); Double getDoubleValue(String name, Long serverId, Double defaultValue); String getStringValue(String name, Long serverId, String defaultValue); + Long getLongValue(String name, Long serverId, Long defaultValue); void setDoubleValue(String name, Long serverId, Double value); + void setLongValue(String name, Long serverId, Long value); void setStringValue(String name, Long serverId, String value); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/LockService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/LockService.java new file mode 100644 index 000000000..5c44743b1 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/LockService.java @@ -0,0 +1,7 @@ +package dev.sheldan.abstracto.core.service; + +import dev.sheldan.abstracto.core.command.models.TableLocks; + +public interface LockService { + void lockTable(TableLocks toLock); +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementService.java index 3542f5764..19be169ff 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ChannelManagementService.java @@ -8,5 +8,6 @@ public interface ChannelManagementService { AChannel loadChannel(Long id); AChannel createChannel(Long id, AChannelType type, AServer server); AChannel markAsDeleted(Long id); + boolean channelExists(Long id); void removeChannel(Long id); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementService.java index 57da10ef2..4ff5c896a 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/ConfigManagementService.java @@ -7,10 +7,12 @@ public interface ConfigManagementService { AConfig setOrCreateDoubleValue(Long serverId, String name, Double value); AConfig createConfig(Long serverId, String name, String value); AConfig createConfig(Long serverId, String name, Double value); + AConfig createConfig(Long serverId, String name, Long value); AConfig createIfNotExists(Long serverId, String name, String value); AConfig createIfNotExists(Long serverId, String name, Double value); AConfig loadConfig(Long serverId, String name); boolean configExists(Long serverId, String name); AConfig setDoubleValue(Long serverId, String name, Double value); + AConfig setLongValue(Long serverId, String name, Long value); AConfig setStringValue(Long serverId, String name, String value); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementService.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementService.java index 511ce56f1..7b0c72cbc 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementService.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/management/UserInServerManagementService.java @@ -5,10 +5,13 @@ import dev.sheldan.abstracto.core.models.database.AUser; import dev.sheldan.abstracto.core.models.database.AUserInAServer; import net.dv8tion.jda.api.entities.Member; +import java.util.List; + public interface UserInServerManagementService { AUserInAServer loadUser(Long serverId, Long userId); AUserInAServer loadUser(AServer server, AUser user); AUserInAServer loadUser(Member member); AUserInAServer createUserInServer(Member member); AUserInAServer createUserInServer(Long guildId, Long userId); + List getUserInAllServers(Long userId); } diff --git a/abstracto-application/executable/pom.xml b/abstracto-application/executable/pom.xml index d3557f365..8a03f681c 100644 --- a/abstracto-application/executable/pom.xml +++ b/abstracto-application/executable/pom.xml @@ -63,6 +63,12 @@ ${project.version} + + dev.sheldan.abstracto.modules + modmail-impl + ${project.version} + + dev.sheldan.abstracto.modules utility-impl diff --git a/abstracto-application/pom.xml b/abstracto-application/pom.xml index ec4969802..b2a239a76 100644 --- a/abstracto-application/pom.xml +++ b/abstracto-application/pom.xml @@ -37,6 +37,12 @@ + + com.jagrosh + jda-utilities-menu + ${jda.utilities.version} + compile + org.apache.commons commons-lang3 diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_description_en_US.ftl similarity index 100% rename from abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_description_en_US.ftl rename to abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_description_en_US.ftl diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_long_help_en_US.ftl similarity index 100% rename from abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_long_help_en_US.ftl rename to abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_long_help_en_US.ftl diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_usage_en_US.ftl similarity index 100% rename from abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setNumber/help/setNumber_usage_en_US.ftl rename to abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setFloat/help/setFloat_usage_en_US.ftl diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_description_en_US.ftl new file mode 100644 index 000000000..cd98b92a6 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_description_en_US.ftl @@ -0,0 +1 @@ +Changes the value of a numerical value of the bots configuration \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_long_help_en_US.ftl new file mode 100644 index 000000000..a62f53500 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_long_help_en_US.ftl @@ -0,0 +1 @@ +Sets a numerical value in the bots configuration to the given value. \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_usage_en_US.ftl new file mode 100644 index 000000000..cab8588e0 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/core/setLong/help/setLong_usage_en_US.ftl @@ -0,0 +1 @@ +setNumber \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_usage_en_US.ftl new file mode 100644 index 000000000..b675504f6 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/anonReply/help/anonReply_usage_en_US.ftl @@ -0,0 +1 @@ +setModMailCategory \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_usage_en_US.ftl new file mode 100644 index 000000000..f8b4a41ef --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/close/help/close_usage_en_US.ftl @@ -0,0 +1 @@ +close [note] \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_usage_en_US.ftl new file mode 100644 index 000000000..94547b312 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/closeSilently/help/closeSilently_usage_en_US.ftl @@ -0,0 +1 @@ +closeSilenty [note] \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_usage_en_US.ftl new file mode 100644 index 000000000..0aea4edc2 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/contact/help/contact_usage_en_US.ftl @@ -0,0 +1 @@ +contact \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_usage_en_US.ftl new file mode 100644 index 000000000..21145747a --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/reply/help/reply_usage_en_US.ftl @@ -0,0 +1 @@ +reply \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_description_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_description_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_long_help_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_long_help_en_US.ftl new file mode 100644 index 000000000..f3a34851d --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_long_help_en_US.ftl @@ -0,0 +1 @@ +text \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_usage_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_usage_en_US.ftl new file mode 100644 index 000000000..b675504f6 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/commands/modmail/setModMailCategory/help/setModMailCategory_usage_en_US.ftl @@ -0,0 +1 @@ +setModMailCategory \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/config/modmail_feature_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/config/modmail_feature_en_US.ftl new file mode 100644 index 000000000..076a26637 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/config/modmail_feature_en_US.ftl @@ -0,0 +1 @@ +Mod mail \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/listener/server_chooser/server_chooser_server_list_description_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/listener/server_chooser/server_chooser_server_list_description_en_US.ftl new file mode 100644 index 000000000..b9e29496f --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/listener/server_chooser/server_chooser_server_list_description_en_US.ftl @@ -0,0 +1,2 @@ +For which server do you want to open a modmail? +The available servers are: \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_staff_message_title_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_staff_message_title_en_US.ftl new file mode 100644 index 000000000..36aef3c39 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_staff_message_title_en_US.ftl @@ -0,0 +1 @@ +Moderator replied \ No newline at end of file diff --git a/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_user_message_title_en_US.ftl b/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_user_message_title_en_US.ftl new file mode 100644 index 000000000..0c0611288 --- /dev/null +++ b/abstracto-application/template-config/src/main/resources/templates/en_US/modMail/modmail_thread_user_message_title_en_US.ftl @@ -0,0 +1 @@ +User replied \ No newline at end of file diff --git a/abstracto-application/templating/templating-interface/pom.xml b/abstracto-application/templating/templating-interface/pom.xml index 1057af57a..34d6028d3 100644 --- a/abstracto-application/templating/templating-interface/pom.xml +++ b/abstracto-application/templating/templating-interface/pom.xml @@ -22,6 +22,11 @@ JDA + + com.jagrosh + jda-utilities-menu + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 06b8208fd..1d3037a89 100644 --- a/pom.xml +++ b/pom.xml @@ -18,7 +18,8 @@ - 4.0.0_73 + 4.1.1_126 + 3.0.3