From d4f07bd7197c5e3f5b817c171a57b9d70128375d Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Thu, 28 Dec 2023 22:27:33 +0100 Subject: [PATCH] [AB-xxx] adding wikipedia and dictionary features --- .../webservices/webservices-impl/pom.xml | 5 - .../DictionaryApiDefinitionCommand.java | 137 +++++++++++++++ .../service/DictionaryApiServiceBean.java | 73 ++++++++ .../command/OpenWeatherMap.java | 1 - .../WikipediaArticleSummaryCommand.java | 158 ++++++++++++++++++ .../service/WikipediaServiceBean.java | 64 +++++++ .../migrations/1.5.20/collection.xml | 10 ++ .../migrations/1.5.20/seedData/command.xml | 26 +++ .../migrations/1.5.20/seedData/data.xml | 11 ++ .../migrations/1.5.20/seedData/feature.xml | 17 ++ .../migrations/webservices-changeLog.xml | 1 + .../resources/webservices-config.properties | 15 +- .../config/WebServicesSlashCommandNames.java | 2 + .../config/WebserviceFeatureDefinition.java | 4 +- .../config/DictionaryApiFeatureConfig.java | 16 ++ .../DictionaryApiRequestException.java | 21 +++ ...DictionaryApiDefinitionFoundException.java | 20 +++ .../dictionaryapi/model/WordDefinition.java | 22 +++ .../dictionaryapi/model/WordMeaning.java | 15 ++ .../model/api/DictionaryApiResponseItem.java | 16 ++ .../api/DictionaryApiWordDefinition.java | 13 ++ .../model/api/DictionaryApiWordMeaning.java | 15 ++ .../model/template/DictionaryDefinition.java | 20 +++ .../model/template/DictionaryMeaning.java | 13 ++ .../service/DictionaryApiService.java | 9 + .../config/WikipediaFeatureConfig.java | 24 +++ .../NoWikipediaArticleFoundException.java | 20 +++ .../exception/WikipediaRequestException.java | 21 +++ .../model/WikipediaArticleSummary.java | 14 ++ .../model/api/WikipediaResponse.java | 13 ++ .../model/api/WikipediaResponsePage.java | 25 +++ .../model/api/WikipediaResponseQuery.java | 14 ++ .../WikipediaArticleSummaryModel.java | 14 ++ .../wikipedia/service/WikipediaService.java | 9 + 34 files changed, 850 insertions(+), 8 deletions(-) create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/command/DictionaryApiDefinitionCommand.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiServiceBean.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/command/WikipediaArticleSummaryCommand.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaServiceBean.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/collection.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/command.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/data.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/feature.xml create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/config/DictionaryApiFeatureConfig.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/DictionaryApiRequestException.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/NoDictionaryApiDefinitionFoundException.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordDefinition.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordMeaning.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiResponseItem.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordDefinition.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordMeaning.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryDefinition.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryMeaning.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiService.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/config/WikipediaFeatureConfig.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/NoWikipediaArticleFoundException.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/WikipediaRequestException.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/WikipediaArticleSummary.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponse.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponsePage.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponseQuery.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/template/WikipediaArticleSummaryModel.java create mode 100644 abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaService.java diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/pom.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/pom.xml index 94ec58895..ab2d34d11 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-impl/pom.xml +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/pom.xml @@ -9,11 +9,6 @@ webservices-impl - - 8 - 8 - - diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/command/DictionaryApiDefinitionCommand.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/command/DictionaryApiDefinitionCommand.java new file mode 100644 index 000000000..c83468cea --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/command/DictionaryApiDefinitionCommand.java @@ -0,0 +1,137 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.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.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.interaction.InteractionService; +import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig; +import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService; +import dev.sheldan.abstracto.core.service.ChannelService; +import dev.sheldan.abstracto.core.templating.model.MessageToSend; +import dev.sheldan.abstracto.core.templating.service.TemplateService; +import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.webservices.config.WebServicesSlashCommandNames; +import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.template.DictionaryMeaning; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.template.DictionaryDefinition; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.WordMeaning; +import dev.sheldan.abstracto.webservices.dictionaryapi.service.DictionaryApiService; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@Component +public class DictionaryApiDefinitionCommand extends AbstractConditionableCommand { + + private static final String DICTIONARY_DEFINITION_RESPONSE_MODEL_TEMPLATE_KEY = "dictionaryDefinition_response"; + private static final String DICTIONARY_DEFINITION_COMMAND = "dictionaryDefinition"; + private static final String SEARCH_QUERY_PARAMETER = "searchQuery"; + + @Autowired + private TemplateService templateService; + + @Autowired + private ChannelService channelService; + + @Autowired + private SlashCommandParameterService slashCommandParameterService; + + @Autowired + private InteractionService interactionService; + + @Autowired + private DictionaryApiService dictionaryApiService; + + @Override + public CompletableFuture executeAsync(CommandContext commandContext) { + String parameter = (String) commandContext.getParameters().getParameters().get(0); + try { + MessageToSend message = getMessageToSend(commandContext.getGuild().getIdLong(), parameter); + return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(message, commandContext.getChannel())) + .thenApply(unused -> CommandResult.fromSuccess()); + } catch (IOException e) { + throw new AbstractoRunTimeException(e); + } + } + + @Override + public CompletableFuture executeSlash(SlashCommandInteractionEvent event) { + String query = slashCommandParameterService.getCommandOption(SEARCH_QUERY_PARAMETER, event, String.class); + try { + MessageToSend messageToSend = getMessageToSend(event.getGuild().getIdLong(), query); + return interactionService.replyMessageToSend(messageToSend, event) + .thenApply(interactionHook -> CommandResult.fromSuccess()); + } catch (IOException e) { + throw new AbstractoRunTimeException(e); + } + } + + private MessageToSend getMessageToSend(Long serverId, String searchInput) throws IOException { + WordMeaning meaning = dictionaryApiService.getDefinitions(searchInput); + List definitions = meaning + .getDefinitions() + .stream().map(DictionaryDefinition::fromWordDefinition).toList(); + DictionaryMeaning model = DictionaryMeaning + .builder() + .definitions(definitions) + .word(meaning.getWord()) + .build(); + return templateService.renderEmbedTemplate(DICTIONARY_DEFINITION_RESPONSE_MODEL_TEMPLATE_KEY, model, serverId); + } + + @Override + public CommandConfiguration getConfiguration() { + List parameters = new ArrayList<>(); + Parameter searchQueryParameter = Parameter + .builder() + .name(SEARCH_QUERY_PARAMETER) + .type(String.class) + .templated(true) + .remainder(true) + .build(); + parameters.add(searchQueryParameter); + HelpInfo helpInfo = HelpInfo + .builder() + .templated(true) + .build(); + + List aliases = Arrays.asList("dict"); + + SlashCommandConfig slashCommandConfig = SlashCommandConfig + .builder() + .enabled(true) + .rootCommandName(WebServicesSlashCommandNames.DICTIONARY) + .commandName("definition") + .build(); + + return CommandConfiguration.builder() + .name(DICTIONARY_DEFINITION_COMMAND) + .module(UtilityModuleDefinition.UTILITY) + .templated(true) + .slashCommandConfig(slashCommandConfig) + .async(true) + .aliases(aliases) + .supportsEmbedException(true) + .causesReaction(false) + .parameters(parameters) + .help(helpInfo) + .build(); + } + + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.DICTIONARY; + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiServiceBean.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiServiceBean.java new file mode 100644 index 000000000..44b8e2f5f --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiServiceBean.java @@ -0,0 +1,73 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.service; + +import com.google.api.client.http.HttpStatusCodes; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import dev.sheldan.abstracto.webservices.dictionaryapi.exception.DictionaryApiRequestException; +import dev.sheldan.abstracto.webservices.dictionaryapi.exception.NoDictionaryApiDefinitionFoundException; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.WordDefinition; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.WordMeaning; +import dev.sheldan.abstracto.webservices.dictionaryapi.model.api.DictionaryApiResponseItem; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.List; + +@Component +@Slf4j +public class DictionaryApiServiceBean implements DictionaryApiService { + + @Autowired + private OkHttpClient okHttpClient; + + @Value("${abstracto.feature.webservices.dictionaryapi.definitionURL}") + private String dictionaryDefinitionURL; + + @Autowired + private Gson gson; + + @Override + public WordMeaning getDefinitions(String query) throws IOException { + String formattedUrl = dictionaryDefinitionURL.replace("{1}", query); + Request request = new Request.Builder() + .url(formattedUrl) + .get() + .build(); + Response response = okHttpClient.newCall(request).execute(); + if(response.code() == HttpStatusCodes.STATUS_CODE_NOT_FOUND) { + throw new NoDictionaryApiDefinitionFoundException(); + } + if(!response.isSuccessful()) { + if(log.isDebugEnabled()) { + log.error("Failed to retrieve dictionary api definition. Response had code {} with body {}.", + response.code(), response.body()); + } + throw new DictionaryApiRequestException(response.code()); + } + List dictionaryapiResponse = gson.fromJson(response.body().string(), new TypeToken>(){}.getType()); + DictionaryApiResponseItem selectedWord = dictionaryapiResponse.get(0); + if(dictionaryapiResponse.size() > 1) { + log.warn("Dictionary had multiple words. One example {}.", selectedWord.getWord()); + } + List wordDefinitions = selectedWord + .getMeanings() + .stream() + .flatMap(dictionaryApiWordMeaning -> + dictionaryApiWordMeaning + .getDefinitions() + .stream() + .map(WordDefinition::fromResponseDefinition)) + .toList(); + return WordMeaning + .builder() + .word(selectedWord.getWord()) + .definitions(wordDefinitions) + .build(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/openeweathermap/command/OpenWeatherMap.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/openeweathermap/command/OpenWeatherMap.java index e23103369..c04875b77 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/openeweathermap/command/OpenWeatherMap.java +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/openeweathermap/command/OpenWeatherMap.java @@ -26,7 +26,6 @@ import dev.sheldan.abstracto.webservices.openweathermap.service.OpenWeatherMapSe import dev.sheldan.abstracto.webservices.openweathermap.service.WeatherService; import lombok.extern.slf4j.Slf4j; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; -import org.checkerframework.checker.index.qual.SameLen; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/command/WikipediaArticleSummaryCommand.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/command/WikipediaArticleSummaryCommand.java new file mode 100644 index 000000000..b40fed25a --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/command/WikipediaArticleSummaryCommand.java @@ -0,0 +1,158 @@ +package dev.sheldan.abstracto.webservices.wikipedia.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.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.interaction.InteractionService; +import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig; +import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService; +import dev.sheldan.abstracto.core.service.ChannelService; +import dev.sheldan.abstracto.core.service.ConfigService; +import dev.sheldan.abstracto.core.templating.model.MessageToSend; +import dev.sheldan.abstracto.core.templating.service.TemplateService; +import dev.sheldan.abstracto.core.utils.FutureUtils; +import dev.sheldan.abstracto.webservices.config.WebServicesSlashCommandNames; +import dev.sheldan.abstracto.webservices.config.WebserviceFeatureDefinition; +import dev.sheldan.abstracto.webservices.wikipedia.config.WikipediaFeatureConfig; +import dev.sheldan.abstracto.webservices.wikipedia.model.WikipediaArticleSummary; +import dev.sheldan.abstracto.webservices.wikipedia.model.template.WikipediaArticleSummaryModel; +import dev.sheldan.abstracto.webservices.wikipedia.service.WikipediaService; +import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +@Component +public class WikipediaArticleSummaryCommand extends AbstractConditionableCommand { + + private static final String WIKIPEDIA_ARTICLE_SUMMARY_RESPONSE_MODEL_TEMPLATE_KEY = "wikipediaArticleSummary_response"; + private static final String WIKIPEDIA_ARTICLE_SUMMARY_COMMAND = "wikipediaArticleSummary"; + private static final String SEARCH_QUERY_PARAMETER = "searchQuery"; + private static final String LANGUAGE_PARAMETER = "language"; + + @Autowired + private WikipediaService wikipediaService; + + @Autowired + private TemplateService templateService; + + @Autowired + private ChannelService channelService; + + @Autowired + private SlashCommandParameterService slashCommandParameterService; + + @Autowired + private InteractionService interactionService; + + @Autowired + private ConfigService configService; + + @Override + public CompletableFuture executeAsync(CommandContext commandContext) { + String parameter = (String) commandContext.getParameters().getParameters().get(0); + try { + MessageToSend message = getMessageToSend(commandContext.getGuild().getIdLong(), parameter, null); + return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(message, commandContext.getChannel())) + .thenApply(unused -> CommandResult.fromSuccess()); + } catch (IOException e) { + throw new AbstractoRunTimeException(e); + } + } + + @Override + public CompletableFuture executeSlash(SlashCommandInteractionEvent event) { + String query = slashCommandParameterService.getCommandOption(SEARCH_QUERY_PARAMETER, event, String.class); + String language; + if(slashCommandParameterService.hasCommandOption(LANGUAGE_PARAMETER, event)) { + language = slashCommandParameterService.getCommandOption(LANGUAGE_PARAMETER, event, String.class); + } else { + language = null; + } + try { + MessageToSend messageToSend = getMessageToSend(event.getGuild().getIdLong(), query, language); + return interactionService.replyMessageToSend(messageToSend, event) + .thenApply(interactionHook -> CommandResult.fromSuccess()); + } catch (IOException e) { + throw new AbstractoRunTimeException(e); + } + } + + private MessageToSend getMessageToSend(Long serverId, String searchInput, String language) throws IOException { + String languageKey = language != null ? language : + configService.getStringValueOrConfigDefault(WikipediaFeatureConfig.WIKIPEDIA_LANGUAGE_KEY_SYSTEM_CONFIG_KEY, serverId); + WikipediaArticleSummary definition = wikipediaService.getSummary(searchInput, languageKey); + WikipediaArticleSummaryModel model = WikipediaArticleSummaryModel + .builder() + .summary(definition.getSummary()) + .fullURL(definition.getFullURL()) + .title(definition.getTitle()) + .build(); + return templateService.renderEmbedTemplate(WIKIPEDIA_ARTICLE_SUMMARY_RESPONSE_MODEL_TEMPLATE_KEY, model, serverId); + } + + @Override + public CommandConfiguration getConfiguration() { + List parameters = new ArrayList<>(); + Parameter searchQueryParameter = Parameter + .builder() + .name(SEARCH_QUERY_PARAMETER) + .type(String.class) + .remainder(true) + .templated(true) + .build(); + parameters.add(searchQueryParameter); + Parameter languageParameter = Parameter + .builder() + .name(LANGUAGE_PARAMETER) + .type(String.class) + .slashCommandOnly(true) + .optional(true) + .templated(true) + .build(); + parameters.add(languageParameter); + HelpInfo helpInfo = HelpInfo + .builder() + .templated(true) + .build(); + + List aliases = Arrays.asList("wiki"); + + SlashCommandConfig slashCommandConfig = SlashCommandConfig + .builder() + .enabled(true) + .rootCommandName(WebServicesSlashCommandNames.WIKIPEDIA) + .groupName("article") + .commandName("summary") + .build(); + + return CommandConfiguration.builder() + .name(WIKIPEDIA_ARTICLE_SUMMARY_COMMAND) + .module(UtilityModuleDefinition.UTILITY) + .templated(true) + .slashCommandConfig(slashCommandConfig) + .async(true) + .aliases(aliases) + .supportsEmbedException(true) + .causesReaction(false) + .parameters(parameters) + .help(helpInfo) + .build(); + } + + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.WIKIPEDIA; + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaServiceBean.java b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaServiceBean.java new file mode 100644 index 000000000..eccb8db0e --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaServiceBean.java @@ -0,0 +1,64 @@ +package dev.sheldan.abstracto.webservices.wikipedia.service; + +import com.google.gson.Gson; +import dev.sheldan.abstracto.webservices.wikipedia.exception.NoWikipediaArticleFoundException; +import dev.sheldan.abstracto.webservices.wikipedia.exception.WikipediaRequestException; +import dev.sheldan.abstracto.webservices.wikipedia.model.WikipediaArticleSummary; +import dev.sheldan.abstracto.webservices.wikipedia.model.api.WikipediaResponse; +import dev.sheldan.abstracto.webservices.wikipedia.model.api.WikipediaResponsePage; +import lombok.extern.slf4j.Slf4j; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +@Slf4j +public class WikipediaServiceBean implements WikipediaService { + + @Autowired + private OkHttpClient okHttpClient; + + @Value("${abstracto.feature.webservices.wikipedia.summaryURL}") + private String articleSummaryUrl; + + @Autowired + private Gson gson; + + @Override + public WikipediaArticleSummary getSummary(String query, String language) throws IOException { + String formattedUrl = articleSummaryUrl.replace("{1}", language).replace("{2}", query); + Request request = new Request.Builder() + .url(formattedUrl) + .get() + .build(); + Response response = okHttpClient.newCall(request).execute(); + if(!response.isSuccessful()) { + if(log.isDebugEnabled()) { + log.error("Failed to retrieve wikipedia summary. Response had code {} with body {}.", + response.code(), response.body()); + } + throw new WikipediaRequestException(response.code()); + } + WikipediaResponse wikipediaResponse = gson.fromJson(response.body().string(), WikipediaResponse.class); + if(wikipediaResponse.getQuery() == null + || wikipediaResponse.getQuery().getPages() == null + || (wikipediaResponse.getQuery().getPages().stream().anyMatch(wikipediaResponsePageModel -> wikipediaResponsePageModel.getPageId().equals(-1L)) + && wikipediaResponse.getQuery().getPages().size() == 1) + ) { + throw new NoWikipediaArticleFoundException(); + } else { + WikipediaResponsePage page = wikipediaResponse.getQuery().getPages().get(0); + return WikipediaArticleSummary + .builder() + .title(page.getTitle()) + .summary(page.getExtract()) + .fullURL(page.getFullUrl()) + .build(); + } + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/collection.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/collection.xml new file mode 100644 index 000000000..29116ec67 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/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.5.20/seedData/command.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/command.xml new file mode 100644 index 000000000..6b5ebb40a --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/command.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/data.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/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.5.20/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.5.20/seedData/feature.xml b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/feature.xml new file mode 100644 index 000000000..1c6cd9f12 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-impl/src/main/resources/migrations/1.5.20/seedData/feature.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + \ 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 ba4363854..ead5748e6 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 @@ -9,4 +9,5 @@ + \ 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 7057b9511..0299ed368 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 @@ -27,4 +27,17 @@ abstracto.featureFlags.openWeatherMap.featureName=openWeatherMap abstracto.featureFlags.openWeatherMap.enabled=false abstracto.systemConfigs.openWeatherMapLanguageKey.name=openWeatherMapLanguageKey -abstracto.systemConfigs.openWeatherMapLanguageKey.stringValue=en \ No newline at end of file +abstracto.systemConfigs.openWeatherMapLanguageKey.stringValue=en + +abstracto.featureFlags.wikipedia.featureName=wikipedia +abstracto.featureFlags.wikipedia.enabled=false + +abstracto.feature.webservices.wikipedia.summaryURL=https://{1}.wikipedia.org/w/api.php?action=query&format=json&prop=pageprops%7Cextracts%7Cinfo&list=&meta=&inprop=url&redirects=1&formatversion=2&ppprop=disambiguation&exintro=1&explaintext=1&titles={2} + +abstracto.systemConfigs.wikipediaLanguageKey.name=wikipediaLanguageKey +abstracto.systemConfigs.wikipediaLanguageKey.stringValue=en + +abstracto.featureFlags.dictionary.featureName=dictionary +abstracto.featureFlags.dictionary.enabled=false + +abstracto.feature.webservices.dictionaryapi.definitionURL=https://api.dictionaryapi.dev/api/v2/entries/en/{1} \ No newline at end of file diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebServicesSlashCommandNames.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebServicesSlashCommandNames.java index b461637dc..9f5195e71 100644 --- a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebServicesSlashCommandNames.java +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/config/WebServicesSlashCommandNames.java @@ -4,4 +4,6 @@ public class WebServicesSlashCommandNames { public static final String YOUTUBE = "youtube"; public static final String URBAN = "urban"; public static final String WEATHER = "weather"; + public static final String WIKIPEDIA = "wikipedia"; + public static final String DICTIONARY = "dictionary"; } 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 36631bfa8..fa9edb685 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 @@ -8,7 +8,9 @@ public enum WebserviceFeatureDefinition implements FeatureDefinition { YOUTUBE("youtube"), URBAN_DICTIONARY("urban"), THREAD_READER("threadReader"), - OPEN_WEATHER_MAP("openWeatherMap"); + OPEN_WEATHER_MAP("openWeatherMap"), + WIKIPEDIA("wikipedia"), + DICTIONARY("dictionary"); private String key; diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/config/DictionaryApiFeatureConfig.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/config/DictionaryApiFeatureConfig.java new file mode 100644 index 000000000..23148f0c0 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/config/DictionaryApiFeatureConfig.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.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 DictionaryApiFeatureConfig implements FeatureConfig { + + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.DICTIONARY; + } + +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/DictionaryApiRequestException.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/DictionaryApiRequestException.java new file mode 100644 index 000000000..6e00e8c45 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/DictionaryApiRequestException.java @@ -0,0 +1,21 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.exception; + +import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.templating.Templatable; + +public class DictionaryApiRequestException extends AbstractoRunTimeException implements Templatable { + + public DictionaryApiRequestException(Integer responseCode) { + super(String.format("Request failure towards dictionary api %s.", responseCode)); + } + + @Override + public String getTemplateName() { + return "dictionary_api_request_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/dictionaryapi/exception/NoDictionaryApiDefinitionFoundException.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/NoDictionaryApiDefinitionFoundException.java new file mode 100644 index 000000000..5722d26da --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/exception/NoDictionaryApiDefinitionFoundException.java @@ -0,0 +1,20 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.exception; + +import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.templating.Templatable; + +public class NoDictionaryApiDefinitionFoundException extends AbstractoRunTimeException implements Templatable { + public NoDictionaryApiDefinitionFoundException() { + super("No dictionary api definition found."); + } + + @Override + public String getTemplateName() { + return "no_dictionary_api_definition_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/dictionaryapi/model/WordDefinition.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordDefinition.java new file mode 100644 index 000000000..856593697 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordDefinition.java @@ -0,0 +1,22 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model; + +import dev.sheldan.abstracto.webservices.dictionaryapi.model.api.DictionaryApiWordDefinition; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Builder +@Setter +public class WordDefinition { + private String definition; + private String example; + + public static WordDefinition fromResponseDefinition(DictionaryApiWordDefinition responseItem) { + return WordDefinition + .builder() + .example(responseItem.getExample()) + .definition(responseItem.getDefinition()) + .build(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordMeaning.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordMeaning.java new file mode 100644 index 000000000..026e04a58 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/WordMeaning.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Builder +@Setter +public class WordMeaning { + private String word; + private List definitions; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiResponseItem.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiResponseItem.java new file mode 100644 index 000000000..784be9f7e --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiResponseItem.java @@ -0,0 +1,16 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model.api; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Builder +@Setter +public class DictionaryApiResponseItem { + private String word; + private String origin; + private List meanings; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordDefinition.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordDefinition.java new file mode 100644 index 000000000..8b67c7b50 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordDefinition.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model.api; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class DictionaryApiWordDefinition { + private String definition; + private String example; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordMeaning.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordMeaning.java new file mode 100644 index 000000000..b7ffde8db --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/api/DictionaryApiWordMeaning.java @@ -0,0 +1,15 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model.api; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Builder +public class DictionaryApiWordMeaning { + private String partOfSpeech; + private List definitions; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryDefinition.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryDefinition.java new file mode 100644 index 000000000..4155ff148 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryDefinition.java @@ -0,0 +1,20 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model.template; + +import dev.sheldan.abstracto.webservices.dictionaryapi.model.WordDefinition; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class DictionaryDefinition { + private String definition; + private String example; + + public static DictionaryDefinition fromWordDefinition(WordDefinition definition) { + return DictionaryDefinition + .builder() + .example(definition.getExample()) + .definition(definition.getDefinition()) + .build(); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryMeaning.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryMeaning.java new file mode 100644 index 000000000..2fea7f7ab --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/model/template/DictionaryMeaning.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.model.template; + +import lombok.Builder; +import lombok.Getter; + +import java.util.List; + +@Getter +@Builder +public class DictionaryMeaning { + private String word; + private List definitions; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiService.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiService.java new file mode 100644 index 000000000..5819a25ac --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/dictionaryapi/service/DictionaryApiService.java @@ -0,0 +1,9 @@ +package dev.sheldan.abstracto.webservices.dictionaryapi.service; + +import dev.sheldan.abstracto.webservices.dictionaryapi.model.WordMeaning; + +import java.io.IOException; + +public interface DictionaryApiService { + WordMeaning getDefinitions(String query) throws IOException; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/config/WikipediaFeatureConfig.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/config/WikipediaFeatureConfig.java new file mode 100644 index 000000000..e4a4d3d18 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/config/WikipediaFeatureConfig.java @@ -0,0 +1,24 @@ +package dev.sheldan.abstracto.webservices.wikipedia.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; + +import java.util.Arrays; +import java.util.List; + +@Component +public class WikipediaFeatureConfig implements FeatureConfig { + + public static final String WIKIPEDIA_LANGUAGE_KEY_SYSTEM_CONFIG_KEY = "wikipediaLanguageKey"; + @Override + public FeatureDefinition getFeature() { + return WebserviceFeatureDefinition.WIKIPEDIA; + } + + @Override + public List getRequiredSystemConfigKeys() { + return Arrays.asList(WIKIPEDIA_LANGUAGE_KEY_SYSTEM_CONFIG_KEY); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/NoWikipediaArticleFoundException.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/NoWikipediaArticleFoundException.java new file mode 100644 index 000000000..34ff1ea2d --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/NoWikipediaArticleFoundException.java @@ -0,0 +1,20 @@ +package dev.sheldan.abstracto.webservices.wikipedia.exception; + +import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.templating.Templatable; + +public class NoWikipediaArticleFoundException extends AbstractoRunTimeException implements Templatable { + public NoWikipediaArticleFoundException() { + super("No wikipedia article found."); + } + + @Override + public String getTemplateName() { + return "no_wikipedia_article_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/wikipedia/exception/WikipediaRequestException.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/WikipediaRequestException.java new file mode 100644 index 000000000..143c556e9 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/exception/WikipediaRequestException.java @@ -0,0 +1,21 @@ +package dev.sheldan.abstracto.webservices.wikipedia.exception; + +import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; +import dev.sheldan.abstracto.core.templating.Templatable; + +public class WikipediaRequestException extends AbstractoRunTimeException implements Templatable { + + public WikipediaRequestException(Integer responseCode) { + super(String.format("Request failure towards wikipedia %s.", responseCode)); + } + + @Override + public String getTemplateName() { + return "wikipedia_request_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/wikipedia/model/WikipediaArticleSummary.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/WikipediaArticleSummary.java new file mode 100644 index 000000000..1817229ac --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/WikipediaArticleSummary.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.webservices.wikipedia.model; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class WikipediaArticleSummary { + private String title; + private String summary; + private String fullURL; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponse.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponse.java new file mode 100644 index 000000000..6f719fddc --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponse.java @@ -0,0 +1,13 @@ +package dev.sheldan.abstracto.webservices.wikipedia.model.api; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class WikipediaResponse { + private WikipediaResponseQuery query; +} + diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponsePage.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponsePage.java new file mode 100644 index 000000000..be87ad4bb --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponsePage.java @@ -0,0 +1,25 @@ +package dev.sheldan.abstracto.webservices.wikipedia.model.api; + +import com.google.gson.annotations.SerializedName; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.Map; + +@Getter +@Setter +@Builder +public class WikipediaResponsePage { + @SerializedName("pageid") + private Long pageId; + private String title; + private String extract; + @SerializedName("fullurl") + private String fullUrl; + private Map pageprops; + + public boolean isDisambiguation() { + return pageprops != null && pageprops.containsKey("disambiguation"); + } +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponseQuery.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponseQuery.java new file mode 100644 index 000000000..e07785d69 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/api/WikipediaResponseQuery.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.webservices.wikipedia.model.api; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@Builder +public class WikipediaResponseQuery { + private List pages; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/template/WikipediaArticleSummaryModel.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/template/WikipediaArticleSummaryModel.java new file mode 100644 index 000000000..24a92917b --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/model/template/WikipediaArticleSummaryModel.java @@ -0,0 +1,14 @@ +package dev.sheldan.abstracto.webservices.wikipedia.model.template; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder +public class WikipediaArticleSummaryModel { + private String summary; + private String title; + private String fullURL; +} diff --git a/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaService.java b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaService.java new file mode 100644 index 000000000..4214337f8 --- /dev/null +++ b/abstracto-application/abstracto-modules/webservices/webservices-int/src/main/java/dev/sheldan/abstracto/webservices/wikipedia/service/WikipediaService.java @@ -0,0 +1,9 @@ +package dev.sheldan.abstracto.webservices.wikipedia.service; + +import dev.sheldan.abstracto.webservices.wikipedia.model.WikipediaArticleSummary; + +import java.io.IOException; + +public interface WikipediaService { + WikipediaArticleSummary getSummary(String query, String language) throws IOException; +}