mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-28 19:35:23 +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" >
|
||||
<include file="1.2.5-webservices/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.7/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.22/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -15,4 +15,16 @@ abstracto.featureModes.videoDetails.mode=videoDetails
|
||||
abstracto.featureModes.videoDetails.enabled=false
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user