root/trunk/contrib/GoogleWeather.java

Revision 1120, 10.5 kB (checked in by benji, 19 months ago)

"Fix" for GoogleWeather? breakage. Google--

Line 
1import java.io.IOException;
2import java.net.URLEncoder;
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6import java.util.Map;
7import java.util.Arrays;
8
9import javax.xml.bind.JAXBContext;
10import javax.xml.bind.JAXBException;
11import javax.xml.bind.Unmarshaller;
12import javax.xml.bind.annotation.XmlAccessType;
13import javax.xml.bind.annotation.XmlAccessorType;
14import javax.xml.bind.annotation.XmlAttribute;
15import javax.xml.bind.annotation.XmlElementRef;
16import javax.xml.bind.annotation.XmlElementRefs;
17import javax.xml.bind.annotation.XmlRootElement;
18import javax.xml.namespace.QName;
19import javax.xml.transform.Source;
20import javax.xml.ws.Dispatch;
21import javax.xml.ws.Service;
22import javax.xml.ws.handler.MessageContext;
23import javax.xml.ws.http.HTTPBinding;
24
25import uk.co.uwcs.choob.modules.Modules;
26import uk.co.uwcs.choob.support.ChoobNoSuchCallException;
27import uk.co.uwcs.choob.support.IRCInterface;
28import uk.co.uwcs.choob.support.events.Message;
29
30/**
31 * Plugin for Querying weather information from google.
32 * @author benji
33 */
34public class GoogleWeather
35{
36        private static final String baseURL = "http://www.google.com/ig/api?weather=";
37        private static final Class[] DATA_TYPES = {GoogleMapsResponse.class,Weather.class,CurrentConditions.class,ForecastConditions.class,DataItem.class};
38
39        private GoogleWeather()
40        {
41
42        }
43
44        public String[] info()
45        {
46                return new String[] {
47                        "Plugin to get weather forecasts from http://www.google.com/ig",
48                        "The Choob Team",
49                        "choob@uwcs.co.uk",
50                        "0.2"
51                };
52        }
53
54        private static final HashMap<String,String> symbols = new HashMap<String,String>()
55        {
56                private static final long serialVersionUID = 997592107556024573L;
57
58        {
59                put("Cloudy","☁");
60                put("Rain","☂");
61                put("Light Rain","☂");
62        }};
63
64        public <T> T getXmlFromHTTP(final String url, final Class... dataTypes) throws IOException, JAXBException
65        {
66                final QName qname = new QName("", "");
67                final Service service = Service.create(qname);
68                service.addPort(qname, HTTPBinding.HTTP_BINDING, baseURL);
69                final Dispatch<Source> dispatcher =  service.createDispatch(qname, Source.class, Service.Mode.PAYLOAD);
70                final Map<String, Object> requestContext = dispatcher.getRequestContext();
71                requestContext.put(MessageContext.HTTP_REQUEST_METHOD, "GET");
72                requestContext.put(MessageContext.HTTP_REQUEST_HEADERS,new HashMap<String,List<String>>(){{put("User-Agent",Arrays.asList("Opera/8.51 (X11; Linux x86_64; U; en)"));}});
73                requestContext.put(Dispatch.ENDPOINT_ADDRESS_PROPERTY, url);
74                final Source got = dispatcher.invoke(null);
75                final JAXBContext context = JAXBContext.newInstance(dataTypes);
76                final Unmarshaller u = context.createUnmarshaller();
77                return (T)u.unmarshal(got);
78        }
79
80        private String getWeather(final String weatherLocation) throws IOException, JAXBException, LocationNotFoundException
81        {
82                final GoogleMapsResponse response = getXmlFromHTTP(baseURL + URLEncoder.encode(weatherLocation, "UTF-8"), DATA_TYPES);
83                if (response == null || response.getWeather() == null || response.getWeather().getCurrentConditions() == null)
84                        throw new LocationNotFoundException();
85                final String conditions = response.getWeather().getCurrentConditions().getCondition().getData();
86                final String temp = response.getWeather().getCurrentConditions().getTemp_c().getData();
87                final ForecastInformation inf = response.getWeather().getForecastInformation();
88                final StringBuilder forecast = new StringBuilder();
89                for (final ForecastConditions fCons : response.getWeather().getForeCastConditions())
90                        forecast
91                                .append(fCons.getDay_of_week().getData())
92                                .append(" ")
93                                .append(fCons.getCondition().getData())
94                                .append("; ");
95
96                return "Weather in " +
97                        (inf != null ? inf.getCity() : weatherLocation ) +
98                        " is " +
99                        (symbols.containsKey(conditions) ? symbols.get(conditions) + " " : "") +
100                        conditions +
101                        ". Current temperature is " +
102                        temp +
103                        "°C. " +
104                        (forecast.length() > 0 ? "Forecast is - " + forecast.toString() : "");
105        }
106
107        private Modules mods;
108        private IRCInterface irc;
109
110        public GoogleWeather(final Modules mods, final IRCInterface irc)
111        {
112                this.mods = mods;
113                this.irc = irc;
114        }
115
116        public String[] optionsUser = { "Location" };
117        public String[] optionsUserDefaults = { "coventry" };
118
119        public String[] helpOptionGoogleWeatherLocation =
120        {
121                "Set your home location for the weather command with no parameters."
122        };
123
124        public boolean optionCheckUserWeather(final String value, final String nick)
125        {
126                return true; //hmm
127        }
128
129        private String checkOption(final String userNick)
130        {
131                try
132                {
133                        return (String)mods.plugin.callAPI("Options", "GetUserOption", userNick,"Location", optionsUserDefaults[0]);
134                } catch (final ChoobNoSuchCallException e)
135                {
136                        return optionsUserDefaults[0];
137                }
138        }
139
140        public String[] helpCommandWeather =
141        {
142                "Return weather data for a location",
143                "<LOCATION>",
144                "<LOCATION> can be any of a text location eg: 'london' or a US zip code, or any other location google weather accepts"
145        };
146        public void commandWeather( final Message mes )
147        {
148                final List<String> params = mods.util.getParams(mes,2);
149                String location = "";
150                if (params.size()<2)
151                {
152                        location = checkOption(mes.getNick());
153                }
154                if (location == null || location.equals(""))
155                        location = mods.util.getParams(mes, 1).get(1);
156
157                if (location.equals(""))
158                {
159                        irc.sendContextReply(mes, "Please give me a location to lookup.");
160                        return;
161                }
162
163                try
164                {
165                        irc.sendContextReply(mes,getWeather(location));
166                } catch (final IOException e)
167                {
168                        System.err.println(e.getMessage());
169                        e.printStackTrace();
170                        irc.sendContextReply(mes,"Could not contact the site to obtain weather information");
171                } catch (final JAXBException e)
172                {
173                        System.err.println(e.getMessage());
174                        e.printStackTrace();
175                        irc.sendContextReply(mes,"Could not understand the weather information");
176                } catch (final LocationNotFoundException e)
177                {
178                        irc.sendContextReply(mes,"Could not retrieve any weather information for that location");
179                } catch (final Throwable e)
180                {
181                        Throwable ex = e;
182                        while (ex != null)
183                        {
184                                System.err.println(ex.getMessage());
185                                ex.printStackTrace();
186                                System.out.println("Cause is " + ex.getCause());
187                                ex = ex.getCause();
188                        }
189                }
190        }
191
192        public static void main(final String[] args) throws IOException, JAXBException, LocationNotFoundException
193        {
194                if (args.length != 1)
195                {
196                        System.err.println("Usage: <Location>");
197                        System.exit(-1);
198                }
199                final GoogleWeather m = new GoogleWeather();
200                System.out.println(m.getWeather(args[0]));
201        }
202}
203
204class LocationNotFoundException extends Exception {
205
206        /**
207         *
208         */
209        private static final long serialVersionUID = 3732524579011476793L;}
210
211/**
212 * Represents the response google maps will send us
213 * @author benji
214 */
215@XmlRootElement(name = "xml_api_reply")
216class GoogleMapsResponse
217{
218
219        private Weather weather;
220
221        public void setWeather(final Weather weather)
222        {
223                this.weather = weather;
224        }
225
226        public Weather getWeather()
227        {
228                return weather;
229        }
230}
231
232
233class Weather
234{
235
236        public CurrentConditions getCurrentConditions()
237        {
238                for (final Object o : getForeCastInformation())
239                {
240                        if (o instanceof CurrentConditions)
241                        {
242                                return (CurrentConditions) o;
243                        }
244                }
245                return null;
246        }
247
248        public List<ForecastConditions> getForeCastConditions()
249        {
250                final ArrayList<ForecastConditions> forecastConditions = new ArrayList<ForecastConditions>();
251                for (final Object o : getForeCastInformation())
252                {
253                        if (o instanceof ForecastConditions)
254                        {
255                                forecastConditions.add((ForecastConditions) o);
256                        }
257                }
258                return forecastConditions;
259        }
260
261        public ForecastInformation getForecastInformation()
262        {
263                for (final Object o : getForeCastInformation())
264                {
265                        if (o instanceof ForecastInformation)
266                        {
267                                return (ForecastInformation)o;
268                        }
269                }
270                return null;
271        }
272
273        @XmlElementRefs(
274        {
275                @XmlElementRef(name = "forecast_information", type = ForecastInformation.class),
276                @XmlElementRef(name = "current_conditions", type = CurrentConditions.class),
277                @XmlElementRef(name = "forecast_conditions", type = ForecastConditions.class)
278        })
279        protected List<Object> foreCastInformation;
280
281        public List<Object> getForeCastInformation()
282        {
283                if (foreCastInformation == null)
284                {
285                        foreCastInformation = new ArrayList<Object>();
286                }
287                return this.foreCastInformation;
288        }
289}
290
291@XmlRootElement(name="forecast_conditions")
292class ForecastConditions
293{
294
295        private DataItem day_of_week;
296        private DataItem low;
297        private DataItem high;
298        private DataItem icon;
299        private DataItem condition;
300
301        public DataItem getDay_of_week()
302        {
303                return day_of_week;
304        }
305
306        public void setDay_of_week(final DataItem day_of_week)
307        {
308                this.day_of_week = day_of_week;
309        }
310
311        public DataItem getLow()
312        {
313                return low;
314        }
315
316        public void setLow(final DataItem low)
317        {
318                this.low = low;
319        }
320
321        public DataItem getHigh()
322        {
323                return high;
324        }
325
326        public void setHigh(final DataItem high)
327        {
328                this.high = high;
329        }
330
331        public DataItem getIcon()
332        {
333                return icon;
334        }
335
336        public void setIcon(final DataItem icon)
337        {
338                this.icon = icon;
339        }
340
341        public DataItem getCondition()
342        {
343                return condition;
344        }
345
346        public void setCondition(final DataItem condition)
347        {
348                this.condition = condition;
349        }
350}
351
352
353@XmlRootElement(name="current_conditions")
354class CurrentConditions
355{
356
357        private DataItem condition;
358        private DataItem temp_f;
359        private DataItem temp_c;
360        private DataItem humidity;
361        private DataItem icon;
362        private DataItem wind_direction;
363
364        public DataItem getCondition()
365        {
366                return condition;
367        }
368
369        public void setCondition(final DataItem condition)
370        {
371                this.condition = condition;
372        }
373
374        public DataItem getTemp_f()
375        {
376                return temp_f;
377        }
378
379        public void setTemp_f(final DataItem temp_f)
380        {
381                this.temp_f = temp_f;
382        }
383
384        public DataItem getTemp_c()
385        {
386                return temp_c;
387        }
388
389        public void setTemp_c(final DataItem temp_c)
390        {
391                this.temp_c = temp_c;
392        }
393
394        public DataItem getHumidity()
395        {
396                return humidity;
397        }
398
399        public void setHumidity(final DataItem humidity)
400        {
401                this.humidity = humidity;
402        }
403
404        public DataItem getIcon()
405        {
406                return icon;
407        }
408
409        public void setIcon(final DataItem icon)
410        {
411                this.icon = icon;
412        }
413
414        public DataItem getWind_direction()
415        {
416                return wind_direction;
417        }
418
419        public void setWind_direction(final DataItem wind_direction)
420        {
421                this.wind_direction = wind_direction;
422        }
423}
424
425@XmlAccessorType(XmlAccessType.FIELD)
426class DataItem
427{
428
429        @XmlAttribute(required = true)
430        protected String data;
431
432        public String getData()
433        {
434                return data;
435        }
436
437        public void setData(final String value)
438        {
439                this.data = value;
440        }
441
442        @Override
443        public String toString()
444        {
445                return data;
446        }
447}
448
449@XmlRootElement(name="forecast_information")
450class ForecastInformation
451{
452        private DataItem city;
453
454        public DataItem getCity()
455        {
456                return city;
457        }
458
459        public void setCity(final DataItem city)
460        {
461                this.city = city;
462        }
463}
Note: See TracBrowser for help on using the browser.