Early version of new weather plugin (this thing is huge :[)

This commit is contained in:
Luke Rogers 2012-09-10 22:55:34 +12:00
parent 8c33af02ae
commit fbdeacdc76

View file

@ -1,95 +1,141 @@
"weather, thanks to google"
from util import hook, http from util import hook, http
api_url = "http://weather.yahooapis.com/forecastrss"
def fahrenheit_to_celcius(f):
return int(round((int(f) - 32) / 1.8, 0))
@hook.command(autohelp=False) def get_weather(location_id):
def forecast(inp, nick='', server='', """uses the yahoo weather API to get weather information for a location"""
reply=None, db=None, notice=None, say=None):
"forecast <location> [dontsave] -- Gets a weather forecast" \
" for <location> from Google."
loc = inp
dontsave = loc.endswith(" dontsave") xml = http.get_xml(api_url, p=location_id)
if dontsave: data = xml.xpath('//y:location', \
loc = loc[:-9].strip().lower() 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: weather['city'] = data.get('city')
loc = db.execute("select loc from weather where nick=lower(?)", weather['region'] = data.get('region')
(nick,)).fetchone() weather['country'] = data.get('country')
if not loc:
notice(forecast.__doc__)
return
loc = loc[0]
w = http.get_xml('http://www.google.com/ig/api', weather=loc) # get wind information
w = w.find('weather') 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: # wind chill
notice("Couldn't fetch weather data for '%s', try using a zip or " \ weather['chill_f'] = wind.get('chill')
"postal code." % inp) weather['chill_c'] = int(round((int(wind.get('chill')) - 32) / 1.8, 0))
return
city = w.find('forecast_information/city').get('data')
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'): # wind_direction
info = dict((e.tag, e.get('data')) for e in elem) weather['wind_direction'] = wind.get('direction')
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
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) @hook.command(autohelp=False)
def weather(inp, nick='', server='', reply=None, db=None, notice=None): def weather(inp, nick='', server='', reply=None, db=None, notice=None):
"weather <location> [dontsave] -- Gets weather data"\ "weather <location> [dontsave] -- Gets weather data"\
" for <location> from Google." " for <location> from Google."
loc = inp
dontsave = loc.endswith(" dontsave") # initalise weather DB
if dontsave: db.execute("create table if not exists yahoo_weather(nick primary key, location_id)")
loc = loc[:-9].strip().lower()
db.execute("create table if not exists weather(nick primary key, loc)") # if there is no input, try getting the users last location from the DB
if not inp:
if not loc: location_id = db.execute("select location_id from yahoo_weather where nick=lower(?)",
loc = db.execute("select loc from weather where nick=lower(?)", [nick]).fetchone()
(nick,)).fetchone() if not location_id:
if not loc: # no location saved in the database, send the user help text
notice(weather.__doc__) notice(weather.__doc__)
return return
loc = loc[0] location_id = location_id[0]
w = http.get_xml('http://www.google.com/ig/api', weather=loc) # no need to save a location, we already have it
w = w.find('weather') dontsave = True
else:
# see if the input ends with "dontsave"
dontsave = inp.endswith(" dontsave")
if w.find('problem_cause') is not None: # remove "dontsave" from the input string after checking for it
notice("Couldn't fetch weather data for '%s', try using a zip or " \ if dontsave:
"postal code." % inp) location = inp[:-9].strip().lower()
return else:
location = inp
info = dict((e.tag, e.get('data')) for e in w.find('current_conditions')) # get the weather.com location id from the location
info['city'] = w.find('forecast_information/city').get('data') w = http.get_xml('http://xoap.weather.com/search/search', where=location)
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'])
reply('%(city)s: %(condition)s, %(temp_f)sF/%(temp_c)sC (High: %(high)sF' \ try:
'/%(high_c)sC) (Low: %(low)sF/%(low_c)sC), %(humidity)s, ' \ location_id = w.find('loc').get('id')
'%(wind_condition)s.' % info) except AttributeError:
return "Unknown location."
if inp and not dontsave: # now, to get the actual weather
db.execute("insert or replace into weather(nick, loc) values (?,?)", data = get_weather(location_id)
(nick.lower(), loc))
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() db.commit()