diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageDeletedListener.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageDeletedListener.java index 9087540a1..6f1598431 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageDeletedListener.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageDeletedListener.java @@ -1,11 +1,13 @@ package dev.sheldan.abstracto.moderation.listener; +import dev.sheldan.abstracto.core.models.CachedMessage; import dev.sheldan.abstracto.core.utils.ContextUtils; import dev.sheldan.abstracto.core.service.MessageCache; import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.moderation.models.template.listener.MessageDeletedAttachmentLog; import dev.sheldan.abstracto.moderation.models.template.listener.MessageDeletedLog; import dev.sheldan.abstracto.templating.TemplateService; +import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.events.message.guild.GuildMessageDeleteEvent; @@ -15,8 +17,10 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; @Component +@Slf4j public class MessageDeletedListener extends ListenerAdapter { private static final String DELETE_LOG_TARGET = "deleteLog"; @@ -38,18 +42,22 @@ public class MessageDeletedListener extends ListenerAdapter { @Override @Transactional public void onGuildMessageDelete(@Nonnull GuildMessageDeleteEvent event) { - Message messageFromCache = messageCache.getMessageFromCache(event.getMessageIdLong(), - event.getChannel().getIdLong(), event.getGuild().getIdLong()); + CachedMessage messageFromCache = null; + try { + messageFromCache = messageCache.getMessageFromCache(event.getGuild().getIdLong(), event.getChannel().getIdLong(), event.getMessageIdLong()); + } catch (ExecutionException | InterruptedException e) { + log.warn("Failed to load message.", e); + return; + } MessageDeletedLog logModel = (MessageDeletedLog) contextUtils.fromMessage(messageFromCache, MessageDeletedLog.class); logModel.setMessage(messageFromCache); String simpleMessageUpdatedMessage = templateService.renderTemplate(MESSAGE_DELETED_TEMPLATE, logModel); postTargetService.sendTextInPostTarget(simpleMessageUpdatedMessage, DELETE_LOG_TARGET, event.getGuild().getIdLong()); MessageEmbed embed = templateService.renderEmbedTemplate(MESSAGE_DELETED_TEMPLATE, logModel); postTargetService.sendEmbedInPostTarget(embed, DELETE_LOG_TARGET, event.getGuild().getIdLong()); - for (int i = 0; i < messageFromCache.getAttachments().size(); i++) { - Message.Attachment attachment = messageFromCache.getAttachments().get(i); + for (int i = 0; i < messageFromCache.getAttachmentUrls().size(); i++) { MessageDeletedAttachmentLog log = (MessageDeletedAttachmentLog) contextUtils.fromMessage(messageFromCache, MessageDeletedAttachmentLog.class); - log.setImageUrl(attachment.getProxyUrl()); + log.setImageUrl(messageFromCache.getAttachmentUrls().get(i)); log.setCounter(i + 1); MessageEmbed attachmentEmbed = templateService.renderEmbedTemplate(MESSAGE_DELETED_ATTACHMENT_TEMPLATE, log); postTargetService.sendEmbedInPostTarget(attachmentEmbed, DELETE_LOG_TARGET, event.getGuild().getIdLong()); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageEditedListener.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageEditedListener.java index e9fed29f8..f62070ab0 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageEditedListener.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/listener/MessageEditedListener.java @@ -1,6 +1,7 @@ package dev.sheldan.abstracto.moderation.listener; import dev.sheldan.abstracto.core.MessageTextUpdatedListener; +import dev.sheldan.abstracto.core.models.CachedMessage; import dev.sheldan.abstracto.core.service.MessageCache; import dev.sheldan.abstracto.core.service.PostTargetService; import dev.sheldan.abstracto.moderation.models.template.listener.MessageEditedLog; @@ -30,8 +31,8 @@ public class MessageEditedListener implements MessageTextUpdatedListener { @Override @Transactional - public void execute(Message messageBefore, Message messageAfter) { - if(messageBefore.getContentRaw().equals(messageAfter.getContentRaw())){ + public void execute(CachedMessage messageBefore, Message messageAfter) { + if(messageBefore.getContent().equals(messageAfter.getContentRaw())){ log.debug("Message content was the same. Possible reason was: message was not in cache."); return; } @@ -45,7 +46,7 @@ public class MessageEditedListener implements MessageTextUpdatedListener { String simpleMessageUpdatedMessage = templateService.renderTemplate(MESSAGE_EDITED_TEMPLATE, log); postTargetService.sendTextInPostTarget(simpleMessageUpdatedMessage, EDIT_LOG_TARGET, messageAfter.getGuild().getIdLong()); MessageEmbed embed = templateService.renderEmbedTemplate(MESSAGE_EDITED_TEMPLATE, log); - postTargetService.sendEmbedInPostTarget(embed, EDIT_LOG_TARGET, messageBefore.getGuild().getIdLong()); + postTargetService.sendEmbedInPostTarget(embed, EDIT_LOG_TARGET, messageBefore.getServerId()); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java index 5432aad2a..865e15891 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/BanServiceBean.java @@ -41,12 +41,8 @@ public class BanServiceBean implements BanService { } private void banUser(Long guildId, Long userId, String reason) { - Guild guildById = bot.getInstance().getGuildById(guildId); - if(guildById != null) { - log.info("Banning user {} in guild {}.", userId, guildId); - guildById.ban(userId.toString(), 0, reason).queue(); - } else { - log.warn("Guild id {} from member was not found.", guildId); - } + Guild guildById = bot.getGuildById(guildId); + log.info("Banning user {} in guild {}.", userId, guildId); + guildById.ban(userId.toString(), 0, reason).queue(); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java index 8e0275753..ec2e6e9a4 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/KickServiceBean.java @@ -27,13 +27,9 @@ public class KickServiceBean implements KickService { @Override public void kickMember(Member member, String reason, KickLogModel kickLogModel) { - Guild guildById = bot.getInstance().getGuildById(member.getGuild().getIdLong()); - if(guildById != null) { - guildById.kick(member, reason).queue(); - this.sendKickLog(kickLogModel); - } else { - log.warn("Failed to kick member {} from guild {}. Guild was not found.", member.getId(), member.getGuild().getId()); - } + Guild guildById = bot.getGuildById(kickLogModel.getGuild().getIdLong()); + guildById.kick(member, reason).queue(); + this.sendKickLog(kickLogModel); } private void sendKickLog(KickLogModel kickLogModel) { diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/SlowModeServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/SlowModeServiceBean.java index 050656e4f..f1a5cf91f 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/SlowModeServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/SlowModeServiceBean.java @@ -29,17 +29,7 @@ public class SlowModeServiceBean implements SlowModeService { @Override public void setSlowMode(AChannel channel, Duration duration) { - JDA jpaInstance = bot.getInstance(); - Guild guild = jpaInstance.getGuildById(channel.getServer().getId()); - if(guild != null) { - TextChannel textChannelById = guild.getTextChannelById(channel.getId()); - if(textChannelById != null) { - this.setSlowMode(textChannelById, duration); - } else { - log.warn("Channel {} was not found in guild {} when trying to set a slow mode.", channel.getId(), channel.getServer().getId()); - } - } else { - log.warn("Guild {} was not found when trying to set slow mode.", channel.getServer().getId()); - } + TextChannel textChannel = bot.getTextChannelFromServer(channel.getServer().getId(), channel.getId()); + this.setSlowMode(textChannel, duration); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java index 3df13795c..2cab207c5 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/service/WarnServiceBean.java @@ -57,7 +57,7 @@ public class WarnServiceBean implements WarnService { Warning warning = warnManagementService.createWarning(warnedAUserInAServer, warningAUserInAServer, reason); JDA instance = bot.getInstance(); User userBeingWarned = instance.getUserById(warnedAUser.getId()); - Guild guildById = instance.getGuildById(serverOfWarning.getId()); + Guild guildById = bot.getGuildById(serverOfWarning.getId()); String guildName = ""; if(guildById != null) { guildName = guildById.getName(); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_embed_en_US.ftl b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_embed_en_US.ftl index 8b94e56b1..221583259 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_embed_en_US.ftl +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_embed_en_US.ftl @@ -12,11 +12,11 @@ "fields": [ { "name": ":x: Original Message: ", - "value": "${message.contentRaw}" + "value": "${message.content}" }, { "name": "Link", - "value": "[${textChannel.name}](${message.jumpUrl})" + "value": "[${textChannel.name}](${message.messageUrl})" } ] } \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_en_US.ftl b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_en_US.ftl index 26e364d77..9fc75f94f 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_en_US.ftl +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/resources/templates/listener/message_deleted/message_deleted_en_US.ftl @@ -1,2 +1,2 @@ Message from ${member.effectiveName} (${member.idLong?c}) deleted in ${textChannel.asMention}. -Message: ${message.contentRaw} +Message: ${message.content} diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageDeletedLog.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageDeletedLog.java index d5847b6cd..251618c3b 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageDeletedLog.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageDeletedLog.java @@ -1,12 +1,12 @@ package dev.sheldan.abstracto.moderation.models.template.listener; +import dev.sheldan.abstracto.core.models.CachedMessage; import dev.sheldan.abstracto.core.models.UserInitiatedServerContext; import lombok.Getter; import lombok.Setter; import lombok.experimental.SuperBuilder; -import net.dv8tion.jda.api.entities.Message; @Getter @Setter @SuperBuilder public class MessageDeletedLog extends UserInitiatedServerContext { - private Message message; + private CachedMessage message; } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageEditedLog.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageEditedLog.java index ba59aaf33..c27fdb88e 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageEditedLog.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/models/template/listener/MessageEditedLog.java @@ -1,5 +1,6 @@ package dev.sheldan.abstracto.moderation.models.template.listener; +import dev.sheldan.abstracto.core.models.CachedMessage; import dev.sheldan.abstracto.core.models.UserInitiatedServerContext; import lombok.Getter; import lombok.Setter; @@ -9,5 +10,5 @@ import net.dv8tion.jda.api.entities.Message; @Getter @Setter @SuperBuilder public class MessageEditedLog extends UserInitiatedServerContext { private Message messageAfter; - private Message messageBefore; + private CachedMessage messageBefore; } diff --git a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/SuggestionServiceBean.java b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/SuggestionServiceBean.java index 78ec4779f..417fb3078 100644 --- a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/SuggestionServiceBean.java +++ b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/SuggestionServiceBean.java @@ -10,13 +10,16 @@ import dev.sheldan.abstracto.templating.TemplateService; import dev.sheldan.abstracto.utility.models.Suggestion; import dev.sheldan.abstracto.utility.models.SuggestionState; import dev.sheldan.abstracto.utility.models.template.SuggestionLog; -import dev.sheldan.abstracto.utility.service.management.AsyncSuggestionServiceBean; import dev.sheldan.abstracto.utility.service.management.SuggestionManagementService; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; @Component @Slf4j @@ -38,15 +41,15 @@ public class SuggestionServiceBean implements SuggestionService { @Autowired private Bot botService; - @Autowired - private AsyncSuggestionServiceBean suggestionServiceBean; - @Autowired private EmoteManagementService emoteManagementService; @Autowired private MessageService messageService; + @Autowired + private SuggestionServiceBean self; + @Override public void createSuggestion(Member member, String text, SuggestionLog suggestionLog) { Suggestion suggestion = suggestionManagementService.createSuggestion(member, text); @@ -93,13 +96,25 @@ public class SuggestionServiceBean implements SuggestionService { TextChannel textChannelById = guildById.getTextChannelById(channelId); if(textChannelById != null) { textChannelById.retrieveMessageById(originalMessageId).queue(message -> { - suggestionServiceBean.updateSuggestionMessageText(text, suggestionLog, message); + self.updateSuggestionMessageText(text, suggestionLog, message); }); } } } } + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void updateSuggestionMessageText(String text, SuggestionLog suggestionLog, Message message) { + Optional embedOptional = message.getEmbeds().stream().filter(embed -> embed.getDescription() != null).findFirst(); + if(embedOptional.isPresent()) { + MessageEmbed suggestionEmbed = embedOptional.get(); + suggestionLog.setReason(text); + suggestionLog.setText(suggestionEmbed.getDescription()); + MessageEmbed embed = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog); + postTargetService.sendEmbedInPostTarget(embed, SUGGESTIONS_TARGET, suggestionLog.getServer().getId()); + } + } + @Override public void rejectSuggestion(Long suggestionId, String text, SuggestionLog log) { Suggestion suggestion = suggestionManagementService.getSuggestion(suggestionId); diff --git a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/AsyncSuggestionServiceBean.java b/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/AsyncSuggestionServiceBean.java deleted file mode 100644 index 52ac0ec35..000000000 --- a/abstracto-application/abstracto-modules/utility/utility-impl/src/main/java/dev/sheldan/abstracto/utility/service/management/AsyncSuggestionServiceBean.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.sheldan.abstracto.utility.service.management; - -import dev.sheldan.abstracto.core.service.PostTargetService; -import dev.sheldan.abstracto.templating.TemplateService; -import dev.sheldan.abstracto.utility.models.template.SuggestionLog; -import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.entities.Message; -import net.dv8tion.jda.api.entities.MessageEmbed; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; - -import java.util.Optional; - -import static dev.sheldan.abstracto.utility.service.SuggestionServiceBean.SUGGESTION_LOG_TEMPLATE; -import static dev.sheldan.abstracto.utility.service.SuggestionServiceBean.SUGGESTIONS_TARGET; - -@Component -@Slf4j -public class AsyncSuggestionServiceBean { - - @Autowired - private TemplateService templateService; - - @Autowired - private PostTargetService postTargetService; - - @Transactional(propagation = Propagation.REQUIRES_NEW) - public void updateSuggestionMessageText(String text, SuggestionLog suggestionLog, Message message) { - Optional embedOptional = message.getEmbeds().stream().filter(embed -> embed.getDescription() != null).findFirst(); - if(embedOptional.isPresent()) { - MessageEmbed suggestionEmbed = embedOptional.get(); - suggestionLog.setReason(text); - suggestionLog.setText(suggestionEmbed.getDescription()); - MessageEmbed embed = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog); - postTargetService.sendEmbedInPostTarget(embed, SUGGESTIONS_TARGET, suggestionLog.getServer().getId()); - } - } - -} diff --git a/abstracto-application/core/core-impl/pom.xml b/abstracto-application/core/core-impl/pom.xml index b50686454..f2642e3cb 100644 --- a/abstracto-application/core/core-impl/pom.xml +++ b/abstracto-application/core/core-impl/pom.xml @@ -98,6 +98,11 @@ caffeine + + com.google.code.gson + gson + + \ No newline at end of file diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/CoreConfig.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/CoreConfig.java new file mode 100644 index 000000000..a17efeb24 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/CoreConfig.java @@ -0,0 +1,18 @@ +package dev.sheldan.abstracto.config; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.OffsetDateTime; + +@Configuration +public class CoreConfig { + @Bean + public Gson gson() { + return new GsonBuilder() + .registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeAdapter()) + .setPrettyPrinting().create(); + } +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/OffsetDateTimeAdapter.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/OffsetDateTimeAdapter.java new file mode 100644 index 000000000..88b58178a --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/config/OffsetDateTimeAdapter.java @@ -0,0 +1,20 @@ +package dev.sheldan.abstracto.config; + +import com.google.gson.*; + +import java.lang.reflect.Type; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; + +public class OffsetDateTimeAdapter implements JsonDeserializer { + + @Override + public OffsetDateTime deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + TemporalAccessor ta = DateTimeFormatter.ISO_INSTANT.parse(jsonElement.getAsString()); + Instant i = Instant.from(ta); + return OffsetDateTime.ofInstant(i, ZoneId.systemDefault()); + } +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/BotService.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/BotService.java index 27223b94c..36af00e55 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/BotService.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/BotService.java @@ -1,7 +1,11 @@ package dev.sheldan.abstracto.core.service; +import dev.sheldan.abstracto.core.models.ServerChannelUser; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.utils.cache.CacheFlag; import org.springframework.stereotype.Service; @@ -28,6 +32,50 @@ public class BotService implements Bot { return instance; } + @Override + public ServerChannelUser getServerChannelUser(Long serverId, Long channelId, Long userId) { + TextChannel textChannelById = getTextChannelFromServer(serverId, channelId); + Guild guildById = getGuildById(serverId); + if(textChannelById != null) { + Member member = guildById.getMemberById(userId); + return ServerChannelUser.builder().guild(guildById).textChannel(textChannelById).member(member).build(); + } + throw new RuntimeException(String.format("Member %s or text channel %s not found in guild %s", userId, channelId, serverId)); + } + + + + @Override + public Member getMemberInServer(Long serverId, Long memberId) { + Guild guildById = instance.getGuildById(serverId); + if(guildById != null) { + return guildById.getMemberById(memberId); + } else { + throw new RuntimeException(String.format("Member %s not found in guild %s", memberId, serverId)); + } + } + + @Override + public TextChannel getTextChannelFromServer(Long serverId, Long textChannelId) { + Guild guild = getGuildById(serverId); + TextChannel textChannelById = guild.getTextChannelById(textChannelId); + if(textChannelById != null) { + return textChannelById; + } else { + throw new RuntimeException(String.format("Text channel %s in guild %s not found", textChannelId, serverId)); + } + } + + @Override + public Guild getGuildById(Long serverId) { + Guild guildById = instance.getGuildById(serverId); + if(guildById != null) { + return guildById; + } else { + throw new RuntimeException(String.format("Guild %s not found", serverId)); + } + } + @Override public void shutdown() { diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageCacheBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageCacheBean.java index 0ce5c3640..426caf509 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageCacheBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageCacheBean.java @@ -1,8 +1,10 @@ package dev.sheldan.abstracto.core.service; +import dev.sheldan.abstracto.core.models.CachedMessage; +import dev.sheldan.abstracto.core.models.embed.*; 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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; @@ -10,6 +12,12 @@ import org.springframework.cache.annotation.CachePut; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Component; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + @Component @Slf4j @CacheConfig(cacheNames = {"messages"}) public class MessageCacheBean implements MessageCache { @@ -19,38 +27,110 @@ public class MessageCacheBean implements MessageCache { @Override @CachePut(key = "#message.id") - public Message putMessageInCache(Message message) { + public CachedMessage putMessageInCache(Message message) { log.debug("Adding message {} to cache", message.getId()); + return buildCachedMessageFromMessage(message); + } + + @CachePut(key = "#message.messageId") + public CachedMessage putMessageInCache(CachedMessage message) { return message; } @Override - @Cacheable(key = "#message.id") - public Message getMessageFromCache(Message message) { + public CachedMessage getMessageFromCache(Message message) throws ExecutionException, InterruptedException { log.debug("Retrieving message {}", message.getId()); - return getMessageInTextChannelOfGuild(message.getIdLong(), message.getTextChannel().getIdLong(), message.getGuild().getIdLong()); + return getMessageFromCache(message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong()); } @Override @Cacheable(key = "#messageId.toString()") - public Message getMessageFromCache(Long messageId, Long textChannelId, Long guildId) { + public CachedMessage getMessageFromCache(Long guildId, Long textChannelId, Long messageId) throws ExecutionException, InterruptedException { log.info("Retrieving message with parameters"); - return getMessageInTextChannelOfGuild(messageId, textChannelId, guildId); + + CompletableFuture cachedMessageCompletableFuture = + getMessage(guildId, textChannelId, messageId) + .thenApply(jdaMessage -> { + CachedMessage cachedMessage = buildCachedMessageFromMessage(jdaMessage); + putMessageInCache(cachedMessage); + return cachedMessage; + }); + + return cachedMessageCompletableFuture.get(); } - private Message getMessageInTextChannelOfGuild(Long messageId, Long textChannelId, Long guildId) { - Guild guildById = bot.getInstance().getGuildById(guildId); - if(guildById != null) { - TextChannel textChannelById = guildById.getTextChannelById(textChannelId); - if(textChannelById != null) { - return textChannelById.retrieveMessageById(messageId).complete(); - } else { - log.warn("Failed to load text channel {} of message {} in guild {}", textChannelId, messageId, guildId); - } - } else { - log.warn("Failed to guild {} of message {}", guildId, messageId); + @Override + public CompletableFuture getMessage(Long guildId, Long textChannelId, Long messageId) { + TextChannel textChannelById = bot.getTextChannelFromServer(guildId, textChannelId); + return textChannelById.retrieveMessageById(messageId).submit(); + } + + private CachedMessage buildCachedMessageFromMessage(Message message) { + List attachmentUrls = new ArrayList<>(); + message.getAttachments().forEach(attachment -> { + attachmentUrls.add(attachment.getProxyUrl()); + }); + List embeds = new ArrayList<>(); + message.getEmbeds().forEach(embed -> { + embeds.add(getCachedEmbedFromEmbed(embed)); + }); + return CachedMessage.builder() + .authorId(message.getAuthor().getIdLong()) + .serverId(message.getGuild().getIdLong()) + .channelId(message.getChannel().getIdLong()) + .content(message.getContentRaw()) + .embeds(embeds) + .timeCreated(message.getTimeCreated()) + .attachmentUrls(attachmentUrls) + .build(); + } + + private CachedEmbed getCachedEmbedFromEmbed(MessageEmbed embed) { + CachedEmbed.CachedEmbedBuilder builder = CachedEmbed + .builder(); + MessageEmbed.AuthorInfo author = embed.getAuthor(); + if(author != null) { + builder.author(EmbedAuthor.builder().avatar(author.getProxyIconUrl()).url(author.getUrl()).name(author.getName()).build()); + } + List fields = embed.getFields(); + if(!fields.isEmpty()) { + List embedFields = new ArrayList<>(); + fields.forEach(field -> { + EmbedField build = EmbedField + .builder() + .name(field.getName()) + .value(field.getValue()) + .inline(field.isInline()) + .build(); + embedFields.add(build); + }); + builder.fields(embedFields); + } + MessageEmbed.ImageInfo image = embed.getImage(); + if(image != null) { + builder.imageUrl(image.getProxyUrl()); + } + Color color = embed.getColor(); + if(color != null) { + EmbedColor build = EmbedColor + .builder() + .r(color.getRed()) + .g(color.getGreen()) + .b(color.getBlue()) + .build(); + builder.color(build); + } + builder.description(embed.getDescription()); + MessageEmbed.Footer footer = embed.getFooter(); + if(footer != null) { + EmbedFooter build = EmbedFooter + .builder() + .icon(footer.getProxyIconUrl()) + .text(footer.getText()) + .build(); + builder.footer(build); } - throw new RuntimeException("Message was not found"); - } + return builder.build(); + } } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageServiceBean.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageServiceBean.java index a347419db..66dda695f 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageServiceBean.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/service/MessageServiceBean.java @@ -21,21 +21,17 @@ public class MessageServiceBean implements MessageService { @Override public void addReactionToMessage(String emoteKey, Long serverId, Message message) { - Guild guildById = bot.getInstance().getGuildById(serverId); - if(guildById != null) { - AEmote emote = emoteManagementService.loadEmoteByName(emoteKey, serverId); - if(emote.getCustom()) { - Emote emoteById = guildById.getEmoteById(emote.getEmoteId()); - if(emoteById != null) { - message.addReaction(emoteById).queue(); - } else { - log.warn("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guildById.getId()); - } + Guild guildById = bot.getGuildById(serverId); + AEmote emote = emoteManagementService.loadEmoteByName(emoteKey, serverId); + if(emote.getCustom()) { + Emote emoteById = guildById.getEmoteById(emote.getEmoteId()); + if(emoteById != null) { + message.addReaction(emoteById).queue(); } else { - message.addReaction(emote.getEmoteKey()).queue(); + log.warn("Emote with key {} and id {} for guild {} was not found.", emoteKey, emote.getEmoteId(), guildById.getId()); } } else { - log.warn("Guild {} was not found when trying to react to a message.", serverId); + message.addReaction(emote.getEmoteKey()).queue(); } } } diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageEmbedListener.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageEmbedListener.java new file mode 100644 index 000000000..cb4a5dfa1 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageEmbedListener.java @@ -0,0 +1,118 @@ +package dev.sheldan.abstracto.listener; + +import dev.sheldan.abstracto.core.management.ChannelManagementService; +import dev.sheldan.abstracto.core.management.ServerManagementService; +import dev.sheldan.abstracto.core.management.UserManagementService; +import dev.sheldan.abstracto.core.models.CachedMessage; +import dev.sheldan.abstracto.core.models.database.AChannel; +import dev.sheldan.abstracto.core.models.database.AServer; +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.core.models.listener.MessageEmbeddedModel; +import dev.sheldan.abstracto.core.service.Bot; +import dev.sheldan.abstracto.core.service.MessageCache; +import dev.sheldan.abstracto.templating.TemplateService; +import lombok.extern.slf4j.Slf4j; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.MessageEmbed; +import net.dv8tion.jda.api.events.message.guild.GuildMessageReceivedEvent; +import net.dv8tion.jda.api.hooks.ListenerAdapter; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Component +@Slf4j +public class MessageEmbedListener extends ListenerAdapter { + + @Autowired + private MessageCache messageCache; + + public static final String MESSAGE_EMBED_TEMPLATE = "message"; + + private Pattern messageRegex = Pattern.compile("(?https://discordapp.com/channels/(?\\d+)/(?\\d+)/(?\\d+)(?:.*?))+"); + + @Autowired + private MessageEmbedListener self; + + @Autowired + private ChannelManagementService channelManagementService; + + @Autowired + private ServerManagementService serverManagementService; + + @Autowired + private UserManagementService userManagementService; + + @Autowired + private Bot bot; + + @Autowired + private TemplateService templateService; + + @Override + @Transactional + public void onGuildMessageReceived(@Nonnull GuildMessageReceivedEvent event) { + String messageRaw = event.getMessage().getContentRaw(); + Matcher matcher = messageRegex.matcher(messageRaw); + boolean matched = false; + while(matcher.find()) { + matched = true; + String serverId = matcher.group("server"); + String channelId = matcher.group("channel"); + String messageId = matcher.group("message"); + String wholeLink = matcher.group("whole"); + if(event.getMessage().getGuild().getId().equals(serverId)) { + Long serverIdLong = Long.parseLong(serverId); + Long channelIdLong = Long.parseLong(channelId); + Long messageIdLong = Long.parseLong(messageId); + try { + CachedMessage messageFromCache = messageCache.getMessageFromCache(serverIdLong, channelIdLong, messageIdLong); + messageRaw = messageRaw.replace(wholeLink, ""); + self.createEmbedAndPostEmbed(event, messageFromCache); + } catch (ExecutionException | InterruptedException e) { + log.warn("Failed to load message from cache", e); + } + } + } + if(StringUtils.isBlank(messageRaw) && matched) { + event.getMessage().delete().queue(); + } + } + + @NotNull + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void createEmbedAndPostEmbed(@Nonnull GuildMessageReceivedEvent event, CachedMessage message) { + MessageEmbeddedModel messageEmbeddedModel = buildTemplateParameter(event, message); + MessageEmbed embed = templateService.renderEmbedTemplate(MESSAGE_EMBED_TEMPLATE, messageEmbeddedModel); + event.getChannel().sendMessage(embed).queue(); + } + + private MessageEmbeddedModel buildTemplateParameter(GuildMessageReceivedEvent event, CachedMessage embeddedMessage) { + AChannel channel = channelManagementService.loadChannel(event.getChannel().getIdLong()); + AServer server = serverManagementService.loadServer(event.getGuild().getIdLong()); + AUserInAServer user = userManagementService.loadUser(event.getMember()); + Member author = bot.getMemberInServer(embeddedMessage.getServerId(), embeddedMessage.getAuthorId()); + return MessageEmbeddedModel + .builder() + .channel(channel) + .server(server) + .member(event.getMember()) + .aUserInAServer(user) + .author(author) + .sourceChannel(event.getChannel()) + .embeddingUser(event.getMember()) + .user(user.getUserReference()) + .textChannel(event.getChannel()) + .guild(event.getGuild()) + .embeddedMessage(embeddedMessage) + .build(); + } +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageUpdatedListener.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageUpdatedListener.java index 4125cbfab..0a4182972 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageUpdatedListener.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/listener/MessageUpdatedListener.java @@ -1,7 +1,9 @@ package dev.sheldan.abstracto.listener; import dev.sheldan.abstracto.core.MessageTextUpdatedListener; +import dev.sheldan.abstracto.core.models.CachedMessage; import dev.sheldan.abstracto.core.service.MessageCache; +import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.events.message.guild.GuildMessageUpdateEvent; import net.dv8tion.jda.api.hooks.ListenerAdapter; @@ -10,8 +12,10 @@ import org.springframework.stereotype.Component; import javax.annotation.Nonnull; import java.util.List; +import java.util.concurrent.ExecutionException; @Component +@Slf4j public class MessageUpdatedListener extends ListenerAdapter { @Autowired @@ -22,10 +26,15 @@ public class MessageUpdatedListener extends ListenerAdapter { @Override public void onGuildMessageUpdate(@Nonnull GuildMessageUpdateEvent event) { - Message fromCache = messageCache.getMessageFromCache(event.getMessage()); - listener.forEach(messageTextUpdatedListener -> { - messageTextUpdatedListener.execute(fromCache, event.getMessage()); - }); - messageCache.putMessageInCache(event.getMessage()); + Message message = event.getMessage(); + try { + CachedMessage fromCache = messageCache.getMessageFromCache(message.getGuild().getIdLong(), message.getTextChannel().getIdLong(), event.getMessageIdLong()); + listener.forEach(messageTextUpdatedListener -> { + messageTextUpdatedListener.execute(fromCache, message); + }); + messageCache.putMessageInCache(message); + } catch (ExecutionException | InterruptedException e) { + log.warn("Failed to load message", e); + } } } diff --git a/abstracto-application/core/core-impl/src/main/resources/seedData/templates/coreEvents/message_embed_en_US.ftl b/abstracto-application/core/core-impl/src/main/resources/seedData/templates/coreEvents/message_embed_en_US.ftl new file mode 100644 index 000000000..49a04f655 --- /dev/null +++ b/abstracto-application/core/core-impl/src/main/resources/seedData/templates/coreEvents/message_embed_en_US.ftl @@ -0,0 +1,24 @@ +{ + "author": { + "name": "${author.effectiveName}", + "avatar": "${author.user.avatarUrl}" + }, + "color" : { + "r": 200, + "g": 0, + "b": 255 + }, + <#if embeddedMessage.content?has_content > + "description": "${embeddedMessage.content}", + + <#if embeddedMessage.attachmentUrls?size gt 0> + "imageUrl": "${embeddedMessage.attachmentUrls[0]}", + + "fields": [ + { + "name": "Quoted by", + "value": "${embeddingUser.asMention} from [${sourceChannel.name}](${embeddedMessage.messageUrl})" + } + ], + "timeStamp": "${embeddedMessage.timeCreated}" +} \ No newline at end of file diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/MessageTextUpdatedListener.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/MessageTextUpdatedListener.java index ae390a97a..c0e409975 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/MessageTextUpdatedListener.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/MessageTextUpdatedListener.java @@ -1,7 +1,8 @@ package dev.sheldan.abstracto.core; +import dev.sheldan.abstracto.core.models.CachedMessage; import net.dv8tion.jda.api.entities.Message; public interface MessageTextUpdatedListener { - void execute(Message messageBefore, Message messageAfter); + void execute(CachedMessage messageBefore, Message messageAfter); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/CachedMessage.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/CachedMessage.java new file mode 100644 index 000000000..f4c18589a --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/CachedMessage.java @@ -0,0 +1,28 @@ +package dev.sheldan.abstracto.core.models; + +import dev.sheldan.abstracto.core.models.embed.CachedEmbed; +import dev.sheldan.abstracto.core.utils.MessageUtils; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.OffsetDateTime; +import java.util.List; + +@Getter +@Setter +@Builder +public class CachedMessage { + private Long serverId; + private Long channelId; + private Long messageId; + private Long authorId; + private OffsetDateTime timeCreated; + private String content; + private List embeds; + private List attachmentUrls; + + public String getMessageUrl() { + return MessageUtils.buildMessageUrl(this.serverId ,this.channelId, this.messageId); + } +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/ServerChannelUser.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/ServerChannelUser.java new file mode 100644 index 000000000..c18b187ef --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/ServerChannelUser.java @@ -0,0 +1,17 @@ +package dev.sheldan.abstracto.core.models; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; + +@Getter +@Setter +@Builder +public class ServerChannelUser { + public Guild guild; + private TextChannel textChannel; + private Member member; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/CachedEmbed.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/CachedEmbed.java new file mode 100644 index 000000000..62f9d3551 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/CachedEmbed.java @@ -0,0 +1,23 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.OffsetDateTime; +import java.util.List; + +@Getter +@Setter +@Builder +public class CachedEmbed { + private EmbedAuthor author; + private EmbedTitle title; + private EmbedColor color; + private String description; + private String thumbnail; + private String imageUrl; + private List fields; + private EmbedFooter footer; + private OffsetDateTime timeStamp; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedAuthor.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedAuthor.java new file mode 100644 index 000000000..6ccc5bfc1 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedAuthor.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.core.models.embed; + + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class EmbedAuthor { + private String name; + private String url; + private String avatar; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedColor.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedColor.java new file mode 100644 index 000000000..2354cd14b --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedColor.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +@Builder +public class EmbedColor { + private Integer r; + private Integer g; + private Integer b; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedConfiguration.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedConfiguration.java new file mode 100644 index 000000000..074364aa8 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedConfiguration.java @@ -0,0 +1,20 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Getter; +import lombok.Setter; + +import java.time.OffsetDateTime; +import java.util.List; + +@Getter @Setter +public class EmbedConfiguration { + private EmbedAuthor author; + private EmbedTitle title; + private EmbedColor color; + private String description; + private String thumbnail; + private String imageUrl; + private List fields; + private EmbedFooter footer; + private OffsetDateTime timeStamp; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedField.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedField.java new file mode 100644 index 000000000..0bcf86cf2 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedField.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class EmbedField { + private String name; + private String value; + private Boolean inline; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedFooter.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedFooter.java new file mode 100644 index 000000000..76f9c716a --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedFooter.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class EmbedFooter { + private String text; + private String icon; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedTitle.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedTitle.java new file mode 100644 index 000000000..f522ab343 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/embed/EmbedTitle.java @@ -0,0 +1,10 @@ +package dev.sheldan.abstracto.core.models.embed; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class EmbedTitle { + private String title; + private String url; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/listener/MessageEmbeddedModel.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/listener/MessageEmbeddedModel.java new file mode 100644 index 000000000..70707faa7 --- /dev/null +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/models/listener/MessageEmbeddedModel.java @@ -0,0 +1,19 @@ +package dev.sheldan.abstracto.core.models.listener; + +import dev.sheldan.abstracto.core.models.CachedMessage; +import dev.sheldan.abstracto.core.models.UserInitiatedServerContext; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.SuperBuilder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; + +@Getter +@Setter +@SuperBuilder +public class MessageEmbeddedModel extends UserInitiatedServerContext { + private CachedMessage embeddedMessage; + private TextChannel sourceChannel; + private Member author; + private Member embeddingUser; +} diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/Bot.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/Bot.java index a0811001c..b5b069b5e 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/Bot.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/Bot.java @@ -1,6 +1,10 @@ package dev.sheldan.abstracto.core.service; +import dev.sheldan.abstracto.core.models.ServerChannelUser; import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.TextChannel; import org.springframework.stereotype.Service; import javax.security.auth.login.LoginException; @@ -9,5 +13,9 @@ import javax.security.auth.login.LoginException; public interface Bot { void login() throws LoginException; JDA getInstance(); + ServerChannelUser getServerChannelUser(Long serverId, Long channelId, Long userId); + Member getMemberInServer(Long serverId, Long memberId); + TextChannel getTextChannelFromServer(Long serverId, Long textChannelId); + Guild getGuildById(Long serverId); void shutdown(); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/MessageCache.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/MessageCache.java index 03a6a62b0..9d6c62e26 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/MessageCache.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/service/MessageCache.java @@ -1,9 +1,14 @@ package dev.sheldan.abstracto.core.service; +import dev.sheldan.abstracto.core.models.CachedMessage; import net.dv8tion.jda.api.entities.Message; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + public interface MessageCache { - Message putMessageInCache(Message message); - Message getMessageFromCache(Message message); - Message getMessageFromCache(Long messageId, Long textChannelId, Long guildId); + CachedMessage putMessageInCache(Message message); + CachedMessage getMessageFromCache(Message message) throws ExecutionException, InterruptedException; + CachedMessage getMessageFromCache(Long guildId, Long textChannelId, Long messageId) throws ExecutionException, InterruptedException; + CompletableFuture getMessage(Long serverId, Long textChannelId, Long messageId); } diff --git a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/utils/ContextUtils.java b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/utils/ContextUtils.java index a040cc944..db90551b4 100644 --- a/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/utils/ContextUtils.java +++ b/abstracto-application/core/core-interface/src/main/java/dev/sheldan/abstracto/core/utils/ContextUtils.java @@ -3,10 +3,12 @@ package dev.sheldan.abstracto.core.utils; import dev.sheldan.abstracto.core.management.ChannelManagementService; import dev.sheldan.abstracto.core.management.ServerManagementService; import dev.sheldan.abstracto.core.management.UserManagementService; +import dev.sheldan.abstracto.core.models.CachedMessage; +import dev.sheldan.abstracto.core.models.ServerChannelUser; import dev.sheldan.abstracto.core.models.UserInitiatedServerContext; import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.core.service.Bot; import lombok.extern.slf4j.Slf4j; -import net.dv8tion.jda.api.entities.Message; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,18 +28,22 @@ public class ContextUtils { @Autowired private ServerManagementService serverManagementService; - public UserInitiatedServerContext fromMessage(Message message, Class clazz) { + @Autowired + private Bot bot; + + public UserInitiatedServerContext fromMessage(CachedMessage message, Class clazz) { Method m = null; + ServerChannelUser serverChannelUser = bot.getServerChannelUser(message.getServerId(), message.getChannelId(), message.getAuthorId()); try { m = clazz.getMethod("builder"); UserInitiatedServerContext.UserInitiatedServerContextBuilder builder = (UserInitiatedServerContext.UserInitiatedServerContextBuilder) m.invoke(null, null); - AUserInAServer aUserInAServer = userManagementService.loadUser(message.getMember()); + AUserInAServer aUserInAServer = userManagementService.loadUser(message.getServerId(), message.getAuthorId()); return builder - .member(message.getMember()) - .guild(message.getGuild()) - .textChannel(message.getTextChannel()) - .channel(channelManagementService.loadChannel(message.getTextChannel().getIdLong())) - .server(serverManagementService.loadServer(message.getGuild().getIdLong())) + .member(serverChannelUser.getMember()) + .guild(serverChannelUser.getGuild()) + .textChannel(serverChannelUser.getTextChannel()) + .channel(channelManagementService.loadChannel(message.getChannelId())) + .server(serverManagementService.loadServer(message.getServerId())) .aUserInAServer(aUserInAServer) .user(aUserInAServer.getUserReference()) .build(); diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java index d315d23cd..06386e851 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java @@ -3,6 +3,7 @@ package dev.sheldan.abstracto.templating.embed; import lombok.Getter; import lombok.Setter; +import java.time.OffsetDateTime; import java.util.List; @Getter @Setter @@ -15,4 +16,5 @@ public class EmbedConfiguration { private String imageUrl; private List fields; private EmbedFooter footer; + private OffsetDateTime timeStamp; } diff --git a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/loading/TemplateServiceBean.java b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/loading/TemplateServiceBean.java index b5ec1d33e..1e3873c21 100644 --- a/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/loading/TemplateServiceBean.java +++ b/abstracto-application/templating/templating-impl/src/main/java/dev/sheldan/abstracto/templating/loading/TemplateServiceBean.java @@ -82,6 +82,7 @@ public class TemplateServiceBean implements TemplateService { builder.addField(embedField.getName(), embedField.getValue(), inline); }); } + builder.setTimestamp(configuration.getTimeStamp()); builder.setImage(configuration.getImageUrl()); diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedAuthor.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedAuthor.java new file mode 100644 index 000000000..37a5b8586 --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedAuthor.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.templating.embed; + + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EmbedAuthor { + private String name; + private String url; + private String avatar; +} diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedColor.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedColor.java new file mode 100644 index 000000000..44f736e9c --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedColor.java @@ -0,0 +1,12 @@ +package dev.sheldan.abstracto.templating.embed; + +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class EmbedColor { + private Integer r; + private Integer g; + private Integer b; +} diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java new file mode 100644 index 000000000..5104fa0fb --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedConfiguration.java @@ -0,0 +1,21 @@ +package dev.sheldan.abstracto.templating.embed; + +import lombok.Getter; +import lombok.Setter; + +import java.time.OffsetDateTime; +import java.util.List; + +@Getter +@Setter +public class EmbedConfiguration { + private EmbedAuthor author; + private EmbedTitle title; + private EmbedColor color; + private String description; + private String thumbnail; + private String imageUrl; + private List fields; + private EmbedFooter footer; + private OffsetDateTime timeStamp; +} diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedField.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedField.java new file mode 100644 index 000000000..070646608 --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedField.java @@ -0,0 +1,12 @@ +package dev.sheldan.abstracto.templating.embed; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EmbedField { + private String name; + private String value; + private Boolean inline; +} diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedFooter.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedFooter.java new file mode 100644 index 000000000..bb4e848c5 --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedFooter.java @@ -0,0 +1,11 @@ +package dev.sheldan.abstracto.templating.embed; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EmbedFooter { + private String text; + private String icon; +} diff --git a/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedTitle.java b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedTitle.java new file mode 100644 index 000000000..1d4e2b08c --- /dev/null +++ b/abstracto-application/templating/templating-interface/src/main/java/dev/sheldan/abstracto/templating/embed/EmbedTitle.java @@ -0,0 +1,11 @@ +package dev.sheldan.abstracto.templating.embed; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class EmbedTitle { + private String title; + private String url; +}