123 lines
4.0 KiB
Python
123 lines
4.0 KiB
Python
"weather, thanks to wunderground"
|
|
|
|
from util import hook, http
|
|
|
|
|
|
@hook.api_key('wunderground')
|
|
@hook.command(autohelp=False)
|
|
def weather(inp, chan='', nick='', reply=None, db=None, api_key=None):
|
|
".weather <location> [dontsave] | @<nick> -- gets weather data from Wunderground "\
|
|
"http://wunderground.com/weather/api"
|
|
|
|
if not api_key:
|
|
return None
|
|
|
|
# this database is used by other plugins interested in user's locations,
|
|
# like .near in tag.py
|
|
db.execute(
|
|
"create table if not exists location(chan, nick, loc, lat, lon, primary key(chan, nick))")
|
|
|
|
if inp[0:1] == '@':
|
|
nick = inp[1:].strip()
|
|
loc = None
|
|
dontsave = True
|
|
else:
|
|
dontsave = inp.endswith(" dontsave")
|
|
# strip off the " dontsave" text if it exists and set it back to `inp` so we don't report it
|
|
# back to the user incorrectly
|
|
if dontsave:
|
|
inp = inp[:-9].strip().lower()
|
|
loc = inp
|
|
|
|
if not loc: # blank line
|
|
loc = db.execute(
|
|
"select loc from location where chan=? and nick=lower(?)",
|
|
(chan, nick)).fetchone()
|
|
if not loc:
|
|
try:
|
|
# grab from old-style weather database
|
|
loc = db.execute("select loc from weather where nick=lower(?)",
|
|
(nick,)).fetchone()
|
|
except db.OperationalError:
|
|
pass # no such table
|
|
if not loc:
|
|
return weather.__doc__
|
|
loc = loc[0]
|
|
|
|
loc, _, state = loc.partition(', ')
|
|
|
|
# Check to see if a lat, long pair is being passed. This could be done more
|
|
# completely with regex, and converting from DMS to decimal degrees. This
|
|
# is nice and simple, however.
|
|
try:
|
|
float(loc)
|
|
float(state)
|
|
|
|
loc = loc + ',' + state
|
|
state = ''
|
|
except ValueError:
|
|
if state:
|
|
state = http.quote_plus(state)
|
|
state += '/'
|
|
|
|
loc = http.quote_plus(loc)
|
|
|
|
url = 'http://api.wunderground.com/api/'
|
|
query = '{key}/geolookup/conditions/forecast/q/{state}{loc}.json' \
|
|
.format(key=api_key, state=state, loc=loc)
|
|
url += query
|
|
|
|
try:
|
|
parsed_json = http.get_json(url)
|
|
except IOError:
|
|
return 'Could not get data from Wunderground'
|
|
|
|
info = {}
|
|
if 'current_observation' not in parsed_json:
|
|
resp = 'Could not find weather for {inp}. '.format(inp=inp)
|
|
|
|
# In the case of no observation, but results, print some possible
|
|
# location matches
|
|
if 'results' in parsed_json['response']:
|
|
resp += 'Possible matches include: '
|
|
results = parsed_json['response']['results']
|
|
|
|
for place in results[:6]:
|
|
resp += '{city}, '.format(**place)
|
|
|
|
if place['state']:
|
|
resp += '{state}, '.format(**place)
|
|
|
|
if place['country_name']:
|
|
resp += '{country_name}; '.format(**place)
|
|
|
|
resp = resp[:-2]
|
|
|
|
reply(resp)
|
|
return
|
|
|
|
obs = parsed_json['current_observation']
|
|
sf = parsed_json['forecast']['simpleforecast']['forecastday'][0]
|
|
info['city'] = obs['display_location']['full']
|
|
info['t_f'] = obs['temp_f']
|
|
info['t_c'] = obs['temp_c']
|
|
info['weather'] = obs['weather']
|
|
info['h_f'] = sf['high']['fahrenheit']
|
|
info['h_c'] = sf['high']['celsius']
|
|
info['l_f'] = sf['low']['fahrenheit']
|
|
info['l_c'] = sf['low']['celsius']
|
|
info['humid'] = obs['relative_humidity']
|
|
info['wind'] = 'Wind: {mph}mph/{kph}kph' \
|
|
.format(mph=obs['wind_mph'], kph=obs['wind_kph'])
|
|
reply('{city}: {weather}, {t_f}F/{t_c}C'
|
|
'(H:{h_f}F/{h_c}C L:{l_f}F/{l_c}C)'
|
|
', Humidity: {humid}, {wind}'.format(**info))
|
|
|
|
lat = float(obs['display_location']['latitude'])
|
|
lon = float(obs['display_location']['longitude'])
|
|
|
|
if inp and not dontsave:
|
|
db.execute("insert or replace into location(chan, nick, loc, lat, lon) "
|
|
"values (?, ?, ?, ?,?)", (chan, nick.lower(), inp, lat, lon))
|
|
db.commit()
|