diff --git a/plugins/weather.py b/plugins/weather.py index 965f504..8944e31 100755 --- a/plugins/weather.py +++ b/plugins/weather.py @@ -1,95 +1,141 @@ -"weather, thanks to google" from util import hook, http - -def fahrenheit_to_celcius(f): - return int(round((int(f) - 32) / 1.8, 0)) +api_url = "http://weather.yahooapis.com/forecastrss" -@hook.command(autohelp=False) -def forecast(inp, nick='', server='', - reply=None, db=None, notice=None, say=None): - "forecast [dontsave] -- Gets a weather forecast" \ - " for from Google." - loc = inp +def get_weather(location_id): + """uses the yahoo weather API to get weather information for a location""" - dontsave = loc.endswith(" dontsave") - if dontsave: - loc = loc[:-9].strip().lower() + xml = http.get_xml(api_url, p=location_id) + data = xml.xpath('//y:location', \ + namespaces={'y': 'http://xml.weather.yahoo.com/ns/rss/1.0'})[0] - db.execute("create table if not exists weather(nick primary key, loc)") + # create a dictionary for weather data + weather = {} - if not loc: - loc = db.execute("select loc from weather where nick=lower(?)", - (nick,)).fetchone() - if not loc: - notice(forecast.__doc__) - return - loc = loc[0] + weather['city'] = data.get('city') + weather['region'] = data.get('region') + weather['country'] = data.get('country') - w = http.get_xml('http://www.google.com/ig/api', weather=loc) - w = w.find('weather') + # get wind information + wind = xml.xpath('//y:wind', \ + namespaces={'y': 'http://xml.weather.yahoo.com/ns/rss/1.0'})[0] - if w.find('problem_cause') is not None: - notice("Couldn't fetch weather data for '%s', try using a zip or " \ - "postal code." % inp) - return - city = w.find('forecast_information/city').get('data') + # wind chill + weather['chill_f'] = wind.get('chill') + weather['chill_c'] = int(round((int(wind.get('chill')) - 32) / 1.8, 0)) - out = "%s: " % city + # wind speed + weather['wind_speed_kph'] = int(round(float(wind.get('speed')) * 1.609344)) + weather['wind_speed_mph'] = wind.get('speed') - for elem in w.findall('forecast_conditions'): - info = dict((e.tag, e.get('data')) for e in elem) - info['high'] = elem.find('high').get('data') - info['low'] = elem.find('low').get('data') - info['high_c'] = fahrenheit_to_celcius(elem.find('high').get('data')) - info['low_c'] = fahrenheit_to_celcius(elem.find('low').get('data')) - out += '\x02%(day_of_week)s\x02: %(condition)s (High: %(high)sF' \ - '/%(high_c)sC) (Low: %(low)sF/%(low_c)sC) ' % info + # wind_direction + weather['wind_direction'] = wind.get('direction') - return out + # textual wind direction + direction = weather['wind_direction'] + if direction >= 0 and direction < 45: + weather['wind_direction_text'] = 'N' + elif direction >= 45 and direction < 90: + weather['wind_direction_text'] = 'NE' + elif direction >= 90 and direction < 135: + weather['wind_direction_text'] = 'E' + elif direction >= 135 and direction < 180: + weather['wind_direction_text'] = 'SE' + elif direction >= 180 and direction < 225: + weather['wind_direction_text'] = 'S' + elif direction >= 225 and direction < 270: + weather['wind_direction_text'] = 'SW' + elif direction >= 270 and direction < 315: + weather['wind_direction_text'] = 'W' + elif direction >= 315 and direction < 360: + weather['wind_direction_text'] = 'NW' + else: + weather['wind_direction_text'] = 'N' + + # humidity, visibility and pressure + atmosphere = xml.xpath('//y:atmosphere', \ + namespaces={'y': 'http://xml.weather.yahoo.com/ns/rss/1.0'})[0] + weather['humidity'] = atmosphere.get('humidity') + "%" + weather['visibility_mi'] = atmosphere.get('visibility') + weather['visibility_km'] = \ + int(round(float(atmosphere.get('visibility')) * 1.609344)) + weather['pressure_in'] = atmosphere.get('pressure') + weather['pressure_mb'] = \ + str(round((float(atmosphere.get('pressure')) * 33.8637526), 2)) + + # textual value for air pressure + rising = int(atmosphere.get('rising')) + if rising == 0: + weather['pressure_tendancy'] = 'steady' + elif rising == 1: + weather['pressure_tendancy'] = 'rising' + elif rising == 2: + weather['pressure_tendancy'] = 'falling' + + # weather condition code, temperature, summary text + condition = xml.xpath('//y:condition', \ + namespaces={'y': 'http://xml.weather.yahoo.com/ns/rss/1.0'})[0] + weather['code'] = condition.get('code') + weather['temp_f'] = condition.get('temp') + weather['temp_c'] = \ + int(round(((float(condition.get('temp')) - 32) / 9) * 5)) + weather['conditions'] = condition.get('text') + + # sunset and sunrise + sun = xml.xpath('//y:astronomy', \ + namespaces={'y': 'http://xml.weather.yahoo.com/ns/rss/1.0'})[0] + weather['sunrise'] = sun.get('sunrise') + weather['sunset'] = sun.get('sunset') + + return weather @hook.command(autohelp=False) def weather(inp, nick='', server='', reply=None, db=None, notice=None): "weather [dontsave] -- Gets weather data"\ " for from Google." - loc = inp - dontsave = loc.endswith(" dontsave") - if dontsave: - loc = loc[:-9].strip().lower() + # initalise weather DB + db.execute("create table if not exists yahoo_weather(nick primary key, location_id)") - db.execute("create table if not exists weather(nick primary key, loc)") - - if not loc: - loc = db.execute("select loc from weather where nick=lower(?)", - (nick,)).fetchone() - if not loc: + # if there is no input, try getting the users last location from the DB + if not inp: + location_id = db.execute("select location_id from yahoo_weather where nick=lower(?)", + [nick]).fetchone() + if not location_id: + # no location saved in the database, send the user help text notice(weather.__doc__) return - loc = loc[0] + location_id = location_id[0] - w = http.get_xml('http://www.google.com/ig/api', weather=loc) - w = w.find('weather') + # no need to save a location, we already have it + dontsave = True + else: + # see if the input ends with "dontsave" + dontsave = inp.endswith(" dontsave") - if w.find('problem_cause') is not None: - notice("Couldn't fetch weather data for '%s', try using a zip or " \ - "postal code." % inp) - return + # remove "dontsave" from the input string after checking for it + if dontsave: + location = inp[:-9].strip().lower() + else: + location = inp - info = dict((e.tag, e.get('data')) for e in w.find('current_conditions')) - info['city'] = w.find('forecast_information/city').get('data') - info['high'] = w.find('forecast_conditions/high').get('data') - info['low'] = w.find('forecast_conditions/low').get('data') - info['high_c'] = fahrenheit_to_celcius(info['high']) - info['low_c'] = fahrenheit_to_celcius(info['low']) + # get the weather.com location id from the location + w = http.get_xml('http://xoap.weather.com/search/search', where=location) - reply('%(city)s: %(condition)s, %(temp_f)sF/%(temp_c)sC (High: %(high)sF' \ - '/%(high_c)sC) (Low: %(low)sF/%(low_c)sC), %(humidity)s, ' \ - '%(wind_condition)s.' % info) + try: + location_id = w.find('loc').get('id') + except AttributeError: + return "Unknown location." - if inp and not dontsave: - db.execute("insert or replace into weather(nick, loc) values (?,?)", - (nick.lower(), loc)) - db.commit() + # now, to get the actual weather + data = get_weather(location_id) + + reply('Current Conditions for \x02%(city)s\x02 - %(conditions)s, %(temp_f)sF/%(temp_c)sC, %(humidity)s, ' \ + 'Wind: %(wind_speed_kph)sKPH/%(wind_speed_mph)sMPH %(wind_direction_text)s.' % data) + + if location_id and not dontsave: + db.execute("insert or replace into yahoo_weather(nick, location_id) values (?,?)", + (nick.lower(), location_id)) + db.commit() \ No newline at end of file