mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-14 19:56:29 +00:00
[AB-89] adding command to retrieve weather data
This commit is contained in:
@@ -0,0 +1,176 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openeweathermap.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.openweathermap.config.OpenWeatherMapConfig;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.exception.LocationNotFoundException;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.*;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.service.OpenWeatherMapService;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class OpenWeatherMap extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
private static final String OPEN_WEATHER_MAP_COMMAND = "openWeatherMap";
|
||||||
|
private static final String SEARCH_QUERY_PARAMETER = "searchQuery";
|
||||||
|
private static final String OPEN_WEATHER_MAP_RESPONSE_TEMPLATE_KEY = "openWeatherMap_command_response";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SlashCommandParameterService slashCommandParameterService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InteractionService interactionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OpenWeatherMapService openWeatherMapService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WeatherService weatherService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
|
String parameter = (String) commandContext.getParameters().getParameters().get(0);
|
||||||
|
MessageToSend message = getMessageToSend(commandContext.getGuild().getIdLong(), parameter);
|
||||||
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(message, commandContext.getChannel()))
|
||||||
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
|
String query = slashCommandParameterService.getCommandOption(SEARCH_QUERY_PARAMETER, event, String.class);
|
||||||
|
MessageToSend messageToSend = getMessageToSend(event.getGuild().getIdLong(), query);
|
||||||
|
return interactionService.replyMessageToSend(messageToSend, event)
|
||||||
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
private MessageToSend getMessageToSend(Long serverId, String parameter) {
|
||||||
|
try {
|
||||||
|
GeoCodingResult geoCodingResult = openWeatherMapService.searchForLocation(parameter);
|
||||||
|
if(geoCodingResult.getResults().isEmpty()) {
|
||||||
|
throw new LocationNotFoundException();
|
||||||
|
}
|
||||||
|
String languageKey = configService.getStringValueOrConfigDefault(OpenWeatherMapConfig.OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY, serverId);
|
||||||
|
GeoCodingLocation chosenLocation = geoCodingResult.getResults().get(0);
|
||||||
|
WeatherResult weatherResult = openWeatherMapService.retrieveWeatherForLocation(chosenLocation, languageKey);
|
||||||
|
WeatherResponseModel.WeatherResponseModelBuilder builder = WeatherResponseModel
|
||||||
|
.builder()
|
||||||
|
.description(weatherResult.getWeathers() != null && !weatherResult.getWeathers().isEmpty()
|
||||||
|
? weatherResult.getWeathers().get(0).getDescription() : null)
|
||||||
|
.mainWeather(weatherResult.getWeathers() != null && !weatherResult.getWeathers().isEmpty()
|
||||||
|
? weatherResult.getWeathers().get(0).getMain() : null)
|
||||||
|
.clouds(weatherResult.getCloudInfo() != null ? weatherResult.getCloudInfo().getAll() : null)
|
||||||
|
.rain1H(weatherResult.getRainInfo() != null ? weatherResult.getRainInfo().getRain1H() : null)
|
||||||
|
.rain3H(weatherResult.getRainInfo() != null ? weatherResult.getRainInfo().getRain3H() : null)
|
||||||
|
.snow1H(weatherResult.getSnowInfo() != null ? weatherResult.getSnowInfo().getSnow1H() : null)
|
||||||
|
.snow3H(weatherResult.getSnowInfo() != null ? weatherResult.getSnowInfo().getSnow3H() : null)
|
||||||
|
.visibility(weatherResult.getVisibility())
|
||||||
|
.locationName(chosenLocation.getName())
|
||||||
|
.countryKey(chosenLocation.getCountryKey())
|
||||||
|
.dataCalculationTime(weatherResult.getDayTime() != null ? Instant.ofEpochSecond(weatherResult.getDayTime()) : null);
|
||||||
|
Color embedColor = null;
|
||||||
|
WeatherResultMain mainWeather = weatherResult.getMainWeather();
|
||||||
|
if(mainWeather != null) {
|
||||||
|
builder.feelsLikeTemperature(mainWeather.getFeelsLikeTemperature())
|
||||||
|
.temperature(mainWeather.getTemperature())
|
||||||
|
.maxTemperature(mainWeather.getMaxTemperature())
|
||||||
|
.minTemperature(mainWeather.getMinTemperature())
|
||||||
|
.pressure(mainWeather.getPressure())
|
||||||
|
.seaLevelPressure(mainWeather.getSeaLevelPressure())
|
||||||
|
.groundLevelPressure(mainWeather.getGroundLevelPressure())
|
||||||
|
.humidity(mainWeather.getHumidity());
|
||||||
|
embedColor = weatherService.getColorForTemperature(mainWeather.getFeelsLikeTemperature());
|
||||||
|
}
|
||||||
|
builder.embedColor(embedColor);
|
||||||
|
WeatherResultSystem systemInfo = weatherResult.getSystemInfo();
|
||||||
|
if(systemInfo != null) {
|
||||||
|
builder.sunset(systemInfo.getSunset() != null ? Instant.ofEpochSecond(systemInfo.getSunset()) : null);
|
||||||
|
builder.sunset(systemInfo.getSunrise() != null ? Instant.ofEpochSecond(systemInfo.getSunrise()) : null);
|
||||||
|
}
|
||||||
|
return templateService.renderEmbedTemplate(OPEN_WEATHER_MAP_RESPONSE_TEMPLATE_KEY, builder.build(), serverId);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Failed to load weather in server {}", serverId, e);
|
||||||
|
throw new AbstractoRunTimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return WebserviceFeatureDefinition.OPEN_WEATHER_MAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
List<Parameter> parameters = new ArrayList<>();
|
||||||
|
Parameter searchQueryParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.name(SEARCH_QUERY_PARAMETER)
|
||||||
|
.type(String.class)
|
||||||
|
.remainder(true)
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
parameters.add(searchQueryParameter);
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||||
|
.builder()
|
||||||
|
.enabled(true)
|
||||||
|
.rootCommandName(WebServicesSlashCommandNames.WEATHER)
|
||||||
|
.commandName("search")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name(OPEN_WEATHER_MAP_COMMAND)
|
||||||
|
.module(UtilityModuleDefinition.UTILITY)
|
||||||
|
.templated(true)
|
||||||
|
.slashCommandConfig(slashCommandConfig)
|
||||||
|
.async(true)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.causesReaction(false)
|
||||||
|
.parameters(parameters)
|
||||||
|
.help(helpInfo)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openeweathermap.service;
|
||||||
|
|
||||||
|
import com.google.common.reflect.TypeToken;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingLocation;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingResult;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.WeatherResult;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.service.OpenWeatherMapService;
|
||||||
|
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.lang.reflect.Type;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class OpenWeatherMapServiceBean implements OpenWeatherMapService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
|
@Value("${abstracto.feature.webservices.openweatherMap.apiKey}")
|
||||||
|
private String apiKey;
|
||||||
|
|
||||||
|
@Value("${abstracto.feature.webservices.openweathermap.geocodingURL}")
|
||||||
|
private String geoCodingURL;
|
||||||
|
|
||||||
|
@Value("${abstracto.feature.webservices.openweathermap.weatherDataURL}")
|
||||||
|
private String weatherDataURL;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Gson gson;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GeoCodingResult searchForLocation(String query) throws IOException {
|
||||||
|
Type geoCodingType = new TypeToken<ArrayList<GeoCodingLocation>>() {}.getType();
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(String.format(geoCodingURL, query, 5, apiKey))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = okHttpClient.newCall(request).execute();
|
||||||
|
List<GeoCodingLocation> result = gson.fromJson(response.body().string(), geoCodingType);
|
||||||
|
return GeoCodingResult
|
||||||
|
.builder()
|
||||||
|
.results(result)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WeatherResult retrieveWeatherForLocation(GeoCodingLocation location, String languageKey) throws IOException {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(String.format(weatherDataURL, location.getLatitude(), location.getLongitude(), apiKey, languageKey))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
Response response = okHttpClient.newCall(request).execute();
|
||||||
|
return gson.fromJson(response.body().string(), WeatherResult.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openeweathermap.service;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.service.WeatherService;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class WeatherServiceBean implements WeatherService {
|
||||||
|
|
||||||
|
private static final Map<Pair<Integer, Integer>, String> TEMPERATURE_COLOR_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
// source for colors: https://www.esri.com/arcgis-blog/products/arcgis-pro/mapping/a-meaningful-temperature-palette/
|
||||||
|
static {
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-100, -48), "#E4EFFF");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-48, -45), "#DCE9FA");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-45, -42), "#D3E2F7");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-42, -40), "#CBDBF4");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-40, -37), "#C0D4ED");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-37, -34), "#B8CDEA");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-34, -31), "#AFC6E6");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-31, -28), "#A7BFE3");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-28, -26), "#9CB8DF");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-26, -23), "#93B1D6");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-23, -20), "#89A4CD");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-20, -17), "#7F9BC3");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-17, -15), "#7590B9");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-15, -12), "#617AA8");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-12, -9), "#56719C");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-9, -6), "#4D6591");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-6, -3), "#415C87");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-3, -1), "#39517F");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(-1, 1), "#2F4577");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(1, 4), "#26436F");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(4, 7), "#254F77");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(7, 10), "#275B80");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(10, 12), "#27678A");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(12, 15), "#287593");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(15, 18), "#438190");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(18, 21), "#648C89");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(21, 23), "#879A84");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(23, 26), "#ABA87D");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(26, 29), "#C2A875");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(29, 32), "#C19D61");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(32, 35), "#C38A53");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(35, 37), "#BE704C");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(37, 40), "#AF4D4C");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(40, 43), "#9F294C");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(43, 46), "#87203E");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(46, 48), "#631531");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(48, 65), "#560C25");
|
||||||
|
TEMPERATURE_COLOR_MAP.put(Pair.of(65, 100), "#3D0216");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getColorForTemperature(Float temperature) {
|
||||||
|
return Color.decode(TEMPERATURE_COLOR_MAP.get(TEMPERATURE_COLOR_MAP
|
||||||
|
.keySet()
|
||||||
|
.stream()
|
||||||
|
.filter(pair -> pair.getLeft() < temperature && pair.getRight() > temperature)
|
||||||
|
.findFirst().orElse(TEMPERATURE_COLOR_MAP.keySet().iterator().next())));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd">
|
||||||
|
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
|
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||||
|
<property name="openWeatherMapFeature" value="(SELECT id FROM feature WHERE key = 'openWeatherMap')"/>
|
||||||
|
|
||||||
|
<changeSet author="Sheldan" id="openWeatherMap-command">
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="openWeatherMap"/>
|
||||||
|
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${openWeatherMapFeature}"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
|
<include file="feature.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||||
|
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||||
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
|
<changeSet author="Sheldan" id="openWeatherMap_feature-insertion">
|
||||||
|
<insert tableName="feature">
|
||||||
|
<column name="key" value="openWeatherMap"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -8,4 +8,5 @@
|
|||||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||||
<include file="1.2.5-webservices/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.2.5-webservices/collection.xml" relativeToChangelogFile="true"/>
|
||||||
<include file="1.4.7/collection.xml" relativeToChangelogFile="true"/>
|
<include file="1.4.7/collection.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="1.4.22/collection.xml" relativeToChangelogFile="true"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
@@ -15,4 +15,16 @@ abstracto.featureModes.videoDetails.mode=videoDetails
|
|||||||
abstracto.featureModes.videoDetails.enabled=false
|
abstracto.featureModes.videoDetails.enabled=false
|
||||||
|
|
||||||
abstracto.featureFlags.threadReader.featureName=threadReader
|
abstracto.featureFlags.threadReader.featureName=threadReader
|
||||||
abstracto.featureFlags.threadReader.enabled=false
|
abstracto.featureFlags.threadReader.enabled=false
|
||||||
|
|
||||||
|
|
||||||
|
abstracto.feature.webservices.openweathermap.geocodingURL=http://api.openweathermap.org/geo/1.0/direct?q=%s&limit=%s&appid=%s
|
||||||
|
abstracto.feature.webservices.openweathermap.weatherDataURL=https://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s&appid=%s&units=metric&lang=%s
|
||||||
|
|
||||||
|
abstracto.feature.webservices.openweatherMap.apiKey=${OPEN_WEATHER_MAP_API_KEY}
|
||||||
|
|
||||||
|
abstracto.featureFlags.openWeatherMap.featureName=openWeatherMap
|
||||||
|
abstracto.featureFlags.openWeatherMap.enabled=false
|
||||||
|
|
||||||
|
abstracto.systemConfigs.openWeatherMapLanguageKey.name=openWeatherMapLanguageKey
|
||||||
|
abstracto.systemConfigs.openWeatherMapLanguageKey.stringValue=en
|
||||||
@@ -14,4 +14,11 @@
|
|||||||
<maven.compiler.target>8</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -3,4 +3,5 @@ package dev.sheldan.abstracto.webservices.config;
|
|||||||
public class WebServicesSlashCommandNames {
|
public class WebServicesSlashCommandNames {
|
||||||
public static final String YOUTUBE = "youtube";
|
public static final String YOUTUBE = "youtube";
|
||||||
public static final String URBAN = "urban";
|
public static final String URBAN = "urban";
|
||||||
|
public static final String WEATHER = "weather";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import lombok.Getter;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public enum WebserviceFeatureDefinition implements FeatureDefinition {
|
public enum WebserviceFeatureDefinition implements FeatureDefinition {
|
||||||
YOUTUBE("youtube"), URBAN_DICTIONARY("urban"), THREAD_READER("threadReader");
|
YOUTUBE("youtube"),
|
||||||
|
URBAN_DICTIONARY("urban"),
|
||||||
|
THREAD_READER("threadReader"),
|
||||||
|
OPEN_WEATHER_MAP("openWeatherMap");
|
||||||
|
|
||||||
private String key;
|
private String key;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.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 OpenWeatherMapConfig implements FeatureConfig {
|
||||||
|
|
||||||
|
public static final String OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY = "openWeatherMapLanguageKey";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return WebserviceFeatureDefinition.OPEN_WEATHER_MAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getRequiredSystemConfigKeys() {
|
||||||
|
return Arrays.asList(OPEN_WEATHER_MAP_LANGUAGE_KEY_SYSTEM_CONFIG_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.exception;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||||
|
|
||||||
|
public class LocationNotFoundException extends AbstractoTemplatableException {
|
||||||
|
@Override
|
||||||
|
public String getTemplateName() {
|
||||||
|
return "no_weather_location_found_exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTemplateModel() {
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GeoCodingLocation {
|
||||||
|
@SerializedName("name")
|
||||||
|
private String name;
|
||||||
|
@SerializedName("lat")
|
||||||
|
private Double latitude;
|
||||||
|
@SerializedName("lon")
|
||||||
|
private Double longitude;
|
||||||
|
@SerializedName("country")
|
||||||
|
private String countryKey;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class GeoCodingResult {
|
||||||
|
private List<GeoCodingLocation> results;
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class WeatherResponseModel {
|
||||||
|
private Float temperature;
|
||||||
|
private Float minTemperature;
|
||||||
|
private Float maxTemperature;
|
||||||
|
private String mainWeather;
|
||||||
|
private String description;
|
||||||
|
private Float feelsLikeTemperature;
|
||||||
|
private Integer humidity;
|
||||||
|
private Integer pressure;
|
||||||
|
private Integer seaLevelPressure;
|
||||||
|
private Integer groundLevelPressure;
|
||||||
|
private Float rain1H;
|
||||||
|
private Float rain3H;
|
||||||
|
private Float snow1H;
|
||||||
|
private Float snow3H;
|
||||||
|
private Integer clouds;
|
||||||
|
private Instant sunrise;
|
||||||
|
private Instant sunset;
|
||||||
|
private Integer visibility;
|
||||||
|
private Instant dataCalculationTime;
|
||||||
|
private String locationName;
|
||||||
|
private String countryKey;
|
||||||
|
private Color embedColor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResult {
|
||||||
|
@SerializedName("coord")
|
||||||
|
private WeatherResultCoordinates coordinates;
|
||||||
|
@SerializedName("weather")
|
||||||
|
private List<WeatherResultWeatherDescription> weathers;
|
||||||
|
@SerializedName("visibility")
|
||||||
|
private Integer visibility;
|
||||||
|
@SerializedName("main")
|
||||||
|
private WeatherResultMain mainWeather;
|
||||||
|
@SerializedName("rain")
|
||||||
|
private WeatherResultRain rainInfo;
|
||||||
|
@SerializedName("snow")
|
||||||
|
private WeatherResultSnow snowInfo;
|
||||||
|
@SerializedName("dt")
|
||||||
|
private Long dayTime;
|
||||||
|
@SerializedName("clouds")
|
||||||
|
private WeatherResultClouds cloudInfo;
|
||||||
|
@SerializedName("sys")
|
||||||
|
private WeatherResultSystem systemInfo;
|
||||||
|
@SerializedName("timezone")
|
||||||
|
private Long timezoneShift;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultClouds {
|
||||||
|
private Integer all;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultCoordinates {
|
||||||
|
@SerializedName("lon")
|
||||||
|
private Float longitude;
|
||||||
|
@SerializedName("lat")
|
||||||
|
private Float latitude;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultMain {
|
||||||
|
@SerializedName("temp")
|
||||||
|
private Float temperature;
|
||||||
|
@SerializedName("feels_like")
|
||||||
|
private Float feelsLikeTemperature;
|
||||||
|
@SerializedName("temp_min")
|
||||||
|
private Float minTemperature;
|
||||||
|
@SerializedName("temp_max")
|
||||||
|
private Float maxTemperature;
|
||||||
|
@SerializedName("pressure")
|
||||||
|
private Integer pressure;
|
||||||
|
@SerializedName("humidity")
|
||||||
|
private Integer humidity;
|
||||||
|
@SerializedName("sea_level")
|
||||||
|
private Integer seaLevelPressure;
|
||||||
|
@SerializedName("grnd_level")
|
||||||
|
private Integer groundLevelPressure;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultRain {
|
||||||
|
@SerializedName("1h")
|
||||||
|
private Float rain1H;
|
||||||
|
|
||||||
|
@SerializedName("3h")
|
||||||
|
private Float rain3H;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultSnow {
|
||||||
|
@SerializedName("1h")
|
||||||
|
private Float snow1H;
|
||||||
|
|
||||||
|
@SerializedName("3h")
|
||||||
|
private Float snow3H;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultSystem {
|
||||||
|
@SerializedName("country")
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
@SerializedName("sunrise")
|
||||||
|
private Long sunrise;
|
||||||
|
|
||||||
|
@SerializedName("sunset")
|
||||||
|
private Long sunset;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultWeatherDescription {
|
||||||
|
private Long id;
|
||||||
|
private String main;
|
||||||
|
private String description;
|
||||||
|
private String icon;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.model;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class WeatherResultWind {
|
||||||
|
@SerializedName("speed")
|
||||||
|
private Float speed;
|
||||||
|
@SerializedName("deg")
|
||||||
|
private Integer degrees;
|
||||||
|
@SerializedName("gust")
|
||||||
|
private Float gust;
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.service;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingLocation;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.GeoCodingResult;
|
||||||
|
import dev.sheldan.abstracto.webservices.openweathermap.model.WeatherResult;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface OpenWeatherMapService {
|
||||||
|
GeoCodingResult searchForLocation(String query) throws IOException;
|
||||||
|
WeatherResult retrieveWeatherForLocation(GeoCodingLocation geoCodingLocation, String languageKey) throws IOException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package dev.sheldan.abstracto.webservices.openweathermap.service;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public interface WeatherService {
|
||||||
|
Color getColorForTemperature(Float temperature);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user