From e3dd89b0ef4bc8df4881d81c6e3ed196b051bdea Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Sat, 22 Oct 2022 14:55:18 +0200 Subject: [PATCH] [AB-75] adding thread reader command --- .../command/ThreadReaderCommand.java | 91 +++++++++++++++++++ .../service/ThreadReaderServiceBean.java | 23 +++++ .../resources/migrations/1.4.7/collection.xml | 10 ++ .../migrations/1.4.7/seedData/command.xml | 20 ++++ .../migrations/1.4.7/seedData/data.xml | 11 +++ .../migrations/1.4.7/seedData/feature.xml | 14 +++ .../migrations/webservices-changeLog.xml | 1 + .../resources/webservices-config.properties | 5 +- .../config/WebserviceFeatureDefinition.java | 2 +- .../config/ThreadReaderConfig.java | 14 +++ .../NoTwitterLinkFoundException.java | 15 +++ .../ThreadReaderCommandResponseModel.java | 10 ++ .../service/ThreadReaderService.java | 8 ++ .../core/command/CommandReceivedHandler.java | 7 +- 14 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/command/ThreadReaderCommand.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderServiceBean.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/collection.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/command.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/data.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/feature.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/config/ThreadReaderConfig.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/exception/NoTwitterLinkFoundException.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/model/ThreadReaderCommandResponseModel.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderService.java diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/command/ThreadReaderCommand.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/command/ThreadReaderCommand.java new file mode 100644 index 000000000..67ea45e76 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/command/ThreadReaderCommand.java @@ -0,0 +1,91 @@ +package dev.sheldan.abstracto.webservices.threadreader.command; + +import dev.sheldan.abstracto.core.command.UtilityModuleDefinition; +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.FeatureDefinition; +import dev.sheldan.abstracto.core.service.ChannelService; +import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition; +import dev.sheldan.abstracto.webservices.threadreader.exception.NoTwitterLinkFoundException; +import dev.sheldan.abstracto.webservices.threadreader.model.ThreadReaderCommandResponseModel; +import dev.sheldan.abstracto.webservices.threadreader.service.ThreadReaderService; +import net.dv8tion.jda.api.entities.Message; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +@Component +public class ThreadReaderCommand extends AbstractConditionableCommand { + + public static final String THREAD_READER_RESPONSE_TEMPLATE_KEY = "threadReader_response"; + public static final String THREAD_READER_COMMAND = "threadReader"; + public static final String MESSAGE_PARAMETER = "message"; + + @Autowired + private ThreadReaderService threadReaderService; + + @Autowired + private ChannelService channelService; + + @Override + public CompletableFuture executeAsync(CommandContext commandContext) { + List parameters = commandContext.getParameters().getParameters(); + Message message = (Message) parameters.get(0); + String messageText = message.getContentRaw(); + Optional tweetIdOptional = threadReaderService.extractTweetId(messageText); + if(!tweetIdOptional.isPresent()) { + throw new NoTwitterLinkFoundException(); + } + Long tweetId = tweetIdOptional.get(); + ThreadReaderCommandResponseModel model = ThreadReaderCommandResponseModel + .builder() + .tweetId(tweetId) + .build(); + return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(THREAD_READER_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel())) + .thenApply(unused -> CommandResult.fromSuccess()); + } + + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.THREAD_READER; + } + + @Override + public CommandConfiguration getConfiguration() { + List parameters = new ArrayList<>(); + + Parameter messageParameter = Parameter + .builder() + .name(MESSAGE_PARAMETER) + .type(Message.class) + .remainder(true) + .templated(true) + .build(); + + parameters.add(messageParameter); + + HelpInfo helpInfo = HelpInfo + .builder() + .templated(true) + .build(); + + return CommandConfiguration.builder() + .name(THREAD_READER_COMMAND) + .module(UtilityModuleDefinition.UTILITY) + .templated(true) + .async(true) + .supportsEmbedException(true) + .parameters(parameters) + .help(helpInfo) + .build(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderServiceBean.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderServiceBean.java new file mode 100644 index 000000000..43d6e4fcf --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderServiceBean.java @@ -0,0 +1,23 @@ +package dev.sheldan.abstracto.webservices.threadreader.service; + +import org.springframework.stereotype.Component; + +import java.util.Optional; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@Component +public class ThreadReaderServiceBean implements ThreadReaderService { + private static final Pattern TWITTER_STATUS_REGEX = Pattern.compile(".*?https?://twitter\\.com/(?:#!/)?(\\w+)/status(es)?/(?\\d+).*", Pattern.DOTALL); + + @Override + public boolean containsTwitterLink(String text) { + return TWITTER_STATUS_REGEX.matcher(text).matches(); + } + + @Override + public Optional extractTweetId(String text) { + Matcher matcher = TWITTER_STATUS_REGEX.matcher(text); + return matcher.matches() ? Optional.of(Long.parseLong(matcher.group("tweetId"))) : Optional.empty(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/collection.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/collection.xml new file mode 100644 index 000000000..29116ec67 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/collection.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/command.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/command.xml new file mode 100644 index 000000000..7423dd897 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/command.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/data.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/data.xml new file mode 100644 index 000000000..d492a359d --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/data.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/feature.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/feature.xml new file mode 100644 index 000000000..20226fa28 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.4.7/seedData/feature.xml @@ -0,0 +1,14 @@ + + + + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/webservices-changeLog.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/webservices-changeLog.xml index 13988e728..2dfe95aaf 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/webservices-changeLog.xml +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/webservices-changeLog.xml @@ -7,4 +7,5 @@ http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" > + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/webservices-config.properties b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/webservices-config.properties index 287d4604f..7757e0203 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/webservices-config.properties +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/webservices-config.properties @@ -12,4 +12,7 @@ abstracto.feature.webservices.urban.requestURL=https://api.urbandictionary.com/v abstracto.featureModes.videoDetails.featureName=youtube abstracto.featureModes.videoDetails.mode=videoDetails -abstracto.featureModes.videoDetails.enabled=false \ No newline at end of file +abstracto.featureModes.videoDetails.enabled=false + +abstracto.featureFlags.threadReader.featureName=threadReader +abstracto.featureFlags.threadReader.enabled=false \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebserviceFeatureDefinition.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebserviceFeatureDefinition.java index 2f245f886..efbdf3d7d 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebserviceFeatureDefinition.java +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebserviceFeatureDefinition.java @@ -5,7 +5,7 @@ import lombok.Getter; @Getter public enum WebserviceFeatureDefinition implements FeatureDefinition { - YOUTUBE("youtube"), URBAN_DICTIONARY("urban"); + YOUTUBE("youtube"), URBAN_DICTIONARY("urban"), THREAD_READER("threadReader"); private String key; diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/config/ThreadReaderConfig.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/config/ThreadReaderConfig.java new file mode 100644 index 000000000..c4820f00b --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/config/ThreadReaderConfig.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.webservices.threadreader.config; + +import dev.sheldan.abstracto.core.config.FeatureConfig; +import dev.sheldan.abstracto.core.config.FeatureDefinition; +import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition; +import org.springframework.stereotype.Component; + +@Component +public class ThreadReaderConfig implements FeatureConfig { + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.THREAD_READER; + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/exception/NoTwitterLinkFoundException.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/exception/NoTwitterLinkFoundException.java new file mode 100644 index 000000000..cbbd28bd7 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/exception/NoTwitterLinkFoundException.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.webservices.threadreader.exception; + +import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException; + +public class NoTwitterLinkFoundException extends AbstractoTemplatableException { + @Override + public String getTemplateName() { + return "no_twitter_link_found_exception"; + } + + @Override + public Object getTemplateModel() { + return new Object(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/model/ThreadReaderCommandResponseModel.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/model/ThreadReaderCommandResponseModel.java new file mode 100644 index 000000000..d5d0d8a4a --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/model/ThreadReaderCommandResponseModel.java @@ -0,0 +1,10 @@ +package dev.sheldan.abstracto.webservices.threadreader.model; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ThreadReaderCommandResponseModel { + private Long tweetId; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderService.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderService.java new file mode 100644 index 000000000..9dcb9479a --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/threadreader/service/ThreadReaderService.java @@ -0,0 +1,8 @@ +package dev.sheldan.abstracto.webservices.threadreader.service; + +import java.util.Optional; + +public interface ThreadReaderService { + boolean containsTwitterLink(String text); + Optional extractTweetId(String text); +} diff --git a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/CommandReceivedHandler.java b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/CommandReceivedHandler.java index 58c84129a..d8e135286 100644 --- a/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/CommandReceivedHandler.java +++ b/abstracto-application/core/core-impl/src/main/java/dev/sheldan/abstracto/core/command/CommandReceivedHandler.java @@ -43,6 +43,7 @@ import net.dv8tion.jda.api.hooks.ListenerAdapter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; +import org.springframework.transaction.UnexpectedRollbackException; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; @@ -143,8 +144,10 @@ public class CommandReceivedHandler extends ListenerAdapter { try { self.executeCommand(event, parsedParameters.getCommand(), parsedParameters.getParameters()); } catch (Exception e) { - reportException(event, null, e, String.format("Exception when executing command from message %d in message %d in guild %d." - , message.getIdLong(), event.getChannel().getIdLong(), event.getGuild().getIdLong())); + if(!(e instanceof UnexpectedRollbackException)) { + reportException(event, null, e, String.format("Exception when executing command from message %d in message %d in guild %d." + , message.getIdLong(), event.getChannel().getIdLong(), event.getGuild().getIdLong())); + } } }); parsingFuture.exceptionally(throwable -> {