/*
* Copyright (c) 2013 Christopher Thunes
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.brewtab.ircbot.applets;
import java.io.IOException;
import java.net.MalformedURLException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
import com.brewtab.irc.User;
import com.brewtab.irc.client.Channel;
import com.brewtab.ircbot.util.SQLProperties;
import com.brewtab.ircbot.util.URLBuilder;
public class WundergroundApplet implements BotApplet {
private static final Logger log = LoggerFactory.getLogger(WundergroundApplet.class);
private static final String AUTOCOMPLETE_URL = "http://autocomplete.wunderground.com/aq";
private static final String API_URL_TEMPLATE = "http://api.wunderground.com/api/%s/%s%s.xml";
private SQLProperties properties;
private DocumentBuilder documentBuilder;
private XPath xpath;
private String apikey;
private Options options;
private PosixParser parser;
public WundergroundApplet(SQLProperties properties, String apikey) {
this.properties = properties;
this.apikey = apikey;
try {
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
xpath = XPathFactory.newInstance().newXPath();
options = new Options();
options.addOption("c", "metric", false, "use metric units");
options.addOption("f", "imperial", false, "use imperial units (default)");
options.addOption("n", "no-save", false, "do not save the query as default");
parser = new PosixParser();
}
private URLBuilder makeUrl(String base) {
try {
return new URLBuilder(base);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
private String buildKey(Channel channel, User from) {
return "wunderground:" + channel.getName() + ":" + from.getNick() + ":";
}
public String findLocation(Channel channel, User from, String query, boolean saveSettings) throws Exception {
if (StringUtils.isBlank(query)) {
String location = properties.<String> get(buildKey(channel, from) + "location");
return location;
}
URLBuilder url = makeUrl(AUTOCOMPLETE_URL);
url.setParameter("format", "xml");
url.setParameter("query", query);
Document doc = documentBuilder.parse(url.toString());
String location = xpath.evaluate("/RESULTS/l[1]", doc);
if (StringUtils.isNotBlank(location) && saveSettings) {
properties.set(buildKey(channel, from) + "location", location);
}
return location;
}
private Document request(String feature, String location) throws SAXException, IOException {
String url = String.format(API_URL_TEMPLATE, apikey, feature, location);
return documentBuilder.parse(url);
}
private String formatTemp(String s) {
int value = (int) Float.parseFloat(s);
return Integer.toString(value);
}
@Override
public void run(Channel channel, User from, String command, String[] args, String unparsed) {
try {
CommandLine commandLine = parser.parse(options, args, true);
boolean saveSettings = !commandLine.hasOption("no-save");
boolean useMetric = commandLine.hasOption("metric");
boolean useImperial = commandLine.hasOption("imperial");
String query = StringUtils.join(commandLine.getArgs(), " ");
String locationQuery = findLocation(channel, from, query, saveSettings);
if (StringUtils.isBlank(locationQuery)) {
channel.write("No location found");
return;
}
// Get current conditions
Document result = request("conditions", locationQuery);
String location = xpath.evaluate("/response/current_observation/display_location/full", result);
String temp_f = formatTemp(xpath.evaluate("/response/current_observation/temp_f", result));
String temp_c = formatTemp(xpath.evaluate("/response/current_observation/temp_c", result));
String condition = xpath.evaluate("/response/current_observation/weather", result);
// Get todays forecast
result = request("forecast", locationQuery);
String forecastBase = "/response/forecast/simpleforecast/forecastdays/forecastday[1]/";
String high_f = formatTemp(xpath.evaluate(forecastBase + "high/fahrenheit", result));
String high_c = formatTemp(xpath.evaluate(forecastBase + "high/celsius", result));
String low_f = formatTemp(xpath.evaluate(forecastBase + "low/fahrenheit", result));
String low_c = formatTemp(xpath.evaluate(forecastBase + "low/celsius", result));
if (!useMetric && !useImperial) {
useMetric = properties.<Boolean> get(buildKey(channel, from) + "metric", false);
} else if (saveSettings) {
properties.set(buildKey(channel, from) + "metric", useMetric);
}
if (useMetric) {
channel.write(String.format("%s: %s, %sC, high of %sC, low of %sC",
location, condition, temp_c, high_c, low_c));
} else {
channel.write(String.format("%s: %s, %sF, high of %sF, low of %sF",
location, condition, temp_f, high_f, low_f));
}
} catch (Exception e) {
log.error("Caught exception running Wunderground applet", e);
}
}
}