You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
12 KiB
290 lines
12 KiB
|
11 years ago
|
package org.telegram.services;
|
||
|
|
|
||
|
|
import org.apache.http.HttpResponse;
|
||
|
|
import org.apache.http.client.HttpClient;
|
||
|
|
import org.apache.http.client.methods.HttpGet;
|
||
|
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||
|
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||
|
|
import org.json.JSONObject;
|
||
|
|
import org.telegram.BuildVars;
|
||
|
|
import org.telegram.database.DatabaseManager;
|
||
|
|
|
||
|
|
import java.io.BufferedReader;
|
||
|
|
import java.io.IOException;
|
||
|
|
import java.io.InputStreamReader;
|
||
|
|
import java.io.UnsupportedEncodingException;
|
||
|
|
import java.net.URLEncoder;
|
||
|
|
import java.time.Instant;
|
||
|
|
import java.time.LocalDate;
|
||
|
|
import java.time.ZoneId;
|
||
|
|
import java.time.format.DateTimeFormatter;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @author Ruben Bermudez
|
||
|
|
* @version 1.0
|
||
|
|
* @brief Weather service
|
||
|
|
* @date 20 of June of 2015
|
||
|
|
*/
|
||
|
|
public class WeatherService {
|
||
|
|
private static final String BASEURL = "http://api.openweathermap.org/data/2.5/"; ///< Base url for REST
|
||
|
|
private static final String FORECASTPATH = "forecast/daily";
|
||
|
|
private static final String CURRENTPATH = "weather";
|
||
|
|
private static final String APIIDEND = "&APPID=" + BuildVars.OPENWEATHERAPIKEY;
|
||
|
|
private static final String FORECASTPARAMS = "&cnt=3&units=metric";
|
||
|
|
private static final String CURRENTPARAMS = "&cnt=1&units=metric";
|
||
|
|
private static final DateTimeFormatter dateFormaterFromDate = DateTimeFormatter.ofPattern("dd/MM/yyyy"); ///< Date to text formater
|
||
|
|
private static volatile WeatherService instance; ///< Instance of this class
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Constructor (private due to singleton pattern)
|
||
|
|
*/
|
||
|
|
private WeatherService() {
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Singleton
|
||
|
|
*
|
||
|
|
* @return Return the instance of this class
|
||
|
|
*/
|
||
|
|
public static WeatherService getInstance() {
|
||
|
|
WeatherService currentInstance;
|
||
|
|
if (instance == null) {
|
||
|
|
synchronized (WeatherService.class) {
|
||
|
|
if (instance == null) {
|
||
|
|
instance = new WeatherService();
|
||
|
|
}
|
||
|
|
currentInstance = instance;
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
currentInstance = instance;
|
||
|
|
}
|
||
|
|
return currentInstance;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch the weather of a city
|
||
|
|
*
|
||
|
|
* @param city City to get the weather
|
||
|
|
* @return userHash to be send to use
|
||
|
|
* @note Forecast for the following 3 days
|
||
|
|
*/
|
||
|
|
public String fetchWeatherForecast(String city, Integer userId) {
|
||
|
|
String cityFound;
|
||
|
|
String responseToUser;
|
||
|
|
try {
|
||
|
|
String completURL = BASEURL + FORECASTPATH + "?" + getCityQuery(city) + FORECASTPARAMS + APIIDEND;
|
||
|
|
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
|
||
|
|
HttpGet request = new HttpGet(completURL);
|
||
|
|
HttpResponse response = client.execute(request);
|
||
|
|
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
|
||
|
|
String line;
|
||
|
|
String responseString = "";
|
||
|
|
while ((line = rd.readLine()) != null) {
|
||
|
|
responseString += line;
|
||
|
|
}
|
||
|
|
|
||
|
|
JSONObject jsonObject = new JSONObject(responseString);
|
||
|
|
if (jsonObject.getInt("cod") == 200) {
|
||
|
|
cityFound = jsonObject.getJSONObject("city").getString("name") + " (" +
|
||
|
|
jsonObject.getJSONObject("city").getString("country") + ")";
|
||
|
|
saveRecentWeather(userId, cityFound, jsonObject.getJSONObject("city").getInt("id"));
|
||
|
|
responseToUser = "The weather for " + cityFound + " will be:\n\n";
|
||
|
|
responseToUser += convertListOfForecastToString(jsonObject);
|
||
|
|
responseToUser += "Thank you for using our Weather Bot.\n\n" +
|
||
|
|
"Your Telegram Team";
|
||
|
|
} else {
|
||
|
|
responseToUser = "City not found";
|
||
|
|
}
|
||
|
|
} catch (IOException e) {
|
||
|
|
responseToUser = "Error fetching weather info";
|
||
|
|
}
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch the weather of a city
|
||
|
|
*
|
||
|
|
* @return userHash to be send to use
|
||
|
|
* @note Forecast for the following 3 days
|
||
|
|
*/
|
||
|
|
public String fetchWeatherForecastByLocation(Double longitude, Double latitude, Integer userId) {
|
||
|
|
String cityFound;
|
||
|
|
String responseToUser;
|
||
|
|
try {
|
||
|
|
String completURL = BASEURL + FORECASTPATH + "?lat=" + URLEncoder.encode(latitude + "", "UTF-8") + "&lon=" + URLEncoder.encode(longitude + "", "UTF-8") + FORECASTPARAMS + APIIDEND;;
|
||
|
|
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
|
||
|
|
HttpGet request = new HttpGet(completURL);
|
||
|
|
HttpResponse response = client.execute(request);
|
||
|
|
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
|
||
|
|
String line;
|
||
|
|
String responseString = "";
|
||
|
|
while ((line = rd.readLine()) != null) {
|
||
|
|
responseString += line;
|
||
|
|
}
|
||
|
|
|
||
|
|
JSONObject jsonObject = new JSONObject(responseString);
|
||
|
|
if (jsonObject.getInt("cod") == 200) {
|
||
|
|
cityFound = jsonObject.getJSONObject("city").getString("name") + " (" +
|
||
|
|
jsonObject.getJSONObject("city").getString("country") + ")";
|
||
|
|
saveRecentWeather(userId, cityFound, jsonObject.getJSONObject("city").getInt("id"));
|
||
|
|
responseToUser = "The weather for " + cityFound + " will be:\n\n";
|
||
|
|
responseToUser += convertListOfForecastToString(jsonObject);
|
||
|
|
responseToUser += "Thank you for using our Weather Bot.\n\n" +
|
||
|
|
"Your Telegram Team";
|
||
|
|
} else {
|
||
|
|
responseToUser = "City not found";
|
||
|
|
}
|
||
|
|
} catch (IOException e) {
|
||
|
|
responseToUser = "Error fetching weather info";
|
||
|
|
}
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch the weather of a city
|
||
|
|
*
|
||
|
|
* @param city City to get the weather
|
||
|
|
* @return userHash to be send to use
|
||
|
|
* @note Forecast for the following 3 days
|
||
|
|
*/
|
||
|
|
public String fetchWeatherCurrent(String city, Integer userId) {
|
||
|
|
String cityFound;
|
||
|
|
String responseToUser;
|
||
|
|
try {
|
||
|
|
String completURL = BASEURL + CURRENTPATH + "?" + getCityQuery(city) + CURRENTPARAMS + APIIDEND;
|
||
|
|
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
|
||
|
|
HttpGet request = new HttpGet(completURL);
|
||
|
|
HttpResponse response = client.execute(request);
|
||
|
|
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
|
||
|
|
String line;
|
||
|
|
String responseString = "";
|
||
|
|
while ((line = rd.readLine()) != null) {
|
||
|
|
responseString += line;
|
||
|
|
}
|
||
|
|
|
||
|
|
JSONObject jsonObject = new JSONObject(responseString);
|
||
|
|
if (jsonObject.getInt("cod") == 200) {
|
||
|
|
cityFound = jsonObject.getString("name") + " (" +
|
||
|
|
jsonObject.getJSONObject("sys").getString("country") + ")";
|
||
|
|
saveRecentWeather(userId, cityFound, jsonObject.getInt("id"));
|
||
|
|
responseToUser = "The weather for " + cityFound + " is:\n\n";
|
||
|
|
responseToUser += convertCurrentWeatherToString(jsonObject);
|
||
|
|
responseToUser += "Thank you for using our Weather Bot.\n\n" +
|
||
|
|
"Your Telegram Team";
|
||
|
|
} else {
|
||
|
|
responseToUser = "City not found";
|
||
|
|
}
|
||
|
|
} catch (IOException e) {
|
||
|
|
responseToUser = "Error fetching weather info";
|
||
|
|
}
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Fetch the weather of a city
|
||
|
|
*
|
||
|
|
* @return userHash to be send to use
|
||
|
|
* @note Forecast for the following 3 days
|
||
|
|
*/
|
||
|
|
public String fetchWeatherCurrentByLocation(Double longitude, Double latitude, Integer userId) {
|
||
|
|
String cityFound;
|
||
|
|
String responseToUser;
|
||
|
|
try {
|
||
|
|
String completURL = BASEURL + CURRENTPATH + "?q=" + URLEncoder.encode("lat=" + latitude + "&lon=" + longitude, "UTF-8") + CURRENTPARAMS + APIIDEND;;
|
||
|
|
HttpClient client = HttpClientBuilder.create().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
|
||
|
|
HttpGet request = new HttpGet(completURL);
|
||
|
|
HttpResponse response = client.execute(request);
|
||
|
|
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
|
||
|
|
String line;
|
||
|
|
String responseString = "";
|
||
|
|
while ((line = rd.readLine()) != null) {
|
||
|
|
responseString += line;
|
||
|
|
}
|
||
|
|
|
||
|
|
JSONObject jsonObject = new JSONObject(responseString);
|
||
|
|
if (jsonObject.getInt("cod") == 200) {
|
||
|
|
cityFound = jsonObject.getString("name") + " (" +
|
||
|
|
jsonObject.getJSONObject("sys").getString("country") + ")";
|
||
|
|
saveRecentWeather(userId, cityFound, jsonObject.getInt("id"));
|
||
|
|
responseToUser = "The weather for " + cityFound + " is:\n\n";
|
||
|
|
responseToUser += convertCurrentWeatherToString(jsonObject);
|
||
|
|
responseToUser += "Thank you for using our Weather Bot.\n\n" +
|
||
|
|
"Your Telegram Team";
|
||
|
|
} else {
|
||
|
|
responseToUser = "City not found";
|
||
|
|
}
|
||
|
|
} catch (IOException e) {
|
||
|
|
responseToUser = "Error fetching weather info";
|
||
|
|
}
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
private String convertCurrentWeatherToString(JSONObject jsonObject) {
|
||
|
|
String temp = jsonObject.getJSONObject("main").getDouble("temp")+"";
|
||
|
|
String cloudiness = jsonObject.getJSONObject("clouds").getInt("all") + "%";
|
||
|
|
String weatherDesc = jsonObject.getJSONArray("weather").getJSONObject(0).getString("description");
|
||
|
|
|
||
|
|
String responseToUser = "";
|
||
|
|
responseToUser +=
|
||
|
|
" |-- Weather: " + weatherDesc + "\n" +
|
||
|
|
" |-- Cloudiness: " + cloudiness + "\n" +
|
||
|
|
" |-- Temperature: " + temp + "ºC\n\n";
|
||
|
|
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Convert a list of weather forcast to a list of strings to be sent
|
||
|
|
*
|
||
|
|
* @param jsonObject JSONObject contining the list
|
||
|
|
* @return String to be sent to the user
|
||
|
|
*/
|
||
|
|
private String convertListOfForecastToString(JSONObject jsonObject) {
|
||
|
|
String responseToUser = "";
|
||
|
|
for (int i = 0; i < jsonObject.getJSONArray("list").length(); i++) {
|
||
|
|
JSONObject internalJSON = jsonObject.getJSONArray("list").getJSONObject(i);
|
||
|
|
responseToUser += convertInternalInformationToString(internalJSON);
|
||
|
|
}
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Convert internal part of then answer to string
|
||
|
|
*
|
||
|
|
* @param internalJSON JSONObject containing the part to convert
|
||
|
|
* @return String to be sent to the user
|
||
|
|
*/
|
||
|
|
private String convertInternalInformationToString(JSONObject internalJSON) {
|
||
|
|
String responseToUser = "";
|
||
|
|
LocalDate date;
|
||
|
|
String tempMax;
|
||
|
|
String tempMin;
|
||
|
|
String weatherDesc;
|
||
|
|
date = Instant.ofEpochSecond(internalJSON.getLong("dt")).atZone(ZoneId.systemDefault()).toLocalDate();
|
||
|
|
tempMax = internalJSON.getJSONObject("temp").getDouble("max") + "";
|
||
|
|
tempMin = internalJSON.getJSONObject("temp").getDouble("min") + "";
|
||
|
|
JSONObject weatherObject = internalJSON.getJSONArray("weather").getJSONObject(0);
|
||
|
|
weatherDesc = weatherObject.getString("description");
|
||
|
|
|
||
|
|
responseToUser += "*On " + dateFormaterFromDate.format(date) + "\n" +
|
||
|
|
" |--Forecast: " + weatherDesc + "\n" +
|
||
|
|
" |--High temperature: " + tempMax + "ºC\n" +
|
||
|
|
" |--Low temperature: " + tempMin + "ºC\n\n";
|
||
|
|
return responseToUser;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void saveRecentWeather(Integer userId, String cityName, int cityId) {
|
||
|
|
DatabaseManager.getInstance().addRecentWeather(userId, cityId, cityName);
|
||
|
|
}
|
||
|
|
|
||
|
|
private String getCityQuery(String city) throws UnsupportedEncodingException {
|
||
|
|
String cityQuery = "";
|
||
|
|
try {
|
||
|
|
cityQuery += "id=" + URLEncoder.encode(Integer.parseInt(city)+"", "UTF-8");
|
||
|
|
} catch(NumberFormatException | NullPointerException e) {
|
||
|
|
cityQuery += "q=" + URLEncoder.encode(city, "UTF-8");
|
||
|
|
}
|
||
|
|
return cityQuery;
|
||
|
|
}
|
||
|
|
}
|