Rewrite weather.py to use the Wunderground API
This commit is contained in:
parent
bc6d604897
commit
98f9e814b7
|
@ -1,75 +1,17 @@
|
|||
from util import hook, web
|
||||
from util import hook, http, web
|
||||
|
||||
base_url = "http://api.wunderground.com/api/{}/geolookup/{}/q/{}.json"
|
||||
|
||||
|
||||
def get_weather(location):
|
||||
"""uses the yahoo weather API to get weather information for a location"""
|
||||
|
||||
query = "SELECT * FROM weather.bylocation WHERE location=@location LIMIT 1"
|
||||
result = web.query(query, {"location": location})
|
||||
|
||||
data = result.rows[0]["rss"]["channel"]
|
||||
|
||||
# wind conversions
|
||||
data['wind']['chill_c'] = int(round((int(data['wind']['chill']) - 32) / 1.8, 0))
|
||||
data['wind']['speed_kph'] = int(round(float(data['wind']['speed']) * 1.609344))
|
||||
|
||||
# textual wind direction
|
||||
direction = data['wind']['direction']
|
||||
if direction >= 0 and direction < 45:
|
||||
data['wind']['text'] = 'N'
|
||||
elif direction >= 45 and direction < 90:
|
||||
data['wind']['text'] = 'NE'
|
||||
elif direction >= 90 and direction < 135:
|
||||
data['wind']['text'] = 'E'
|
||||
elif direction >= 135 and direction < 180:
|
||||
data['wind']['text'] = 'SE'
|
||||
elif direction >= 180 and direction < 225:
|
||||
data['wind']['text'] = 'S'
|
||||
elif direction >= 225 and direction < 270:
|
||||
data['wind']['text'] = 'SW'
|
||||
elif direction >= 270 and direction < 315:
|
||||
data['wind']['text'] = 'W'
|
||||
elif direction >= 315 and direction < 360:
|
||||
data['wind']['text'] = 'NW'
|
||||
else:
|
||||
data['wind']['text'] = 'N'
|
||||
|
||||
# visibility and pressure conversions
|
||||
try:
|
||||
data['atmosphere']['visibility_km'] = \
|
||||
int(round(float(data['atmosphere']['visibility']) * 1.609344))
|
||||
data['atmosphere']['visibility_km'] = \
|
||||
str(round((float(data['atmosphere']['visibility']) * 33.8637526), 2))
|
||||
except:
|
||||
data['atmosphere']['visibility_km'] = "ERR"
|
||||
|
||||
# textual value for air pressure
|
||||
rising = data['atmosphere']['rising']
|
||||
if rising == 0:
|
||||
data['atmosphere']['tendancy'] = 'steady'
|
||||
elif rising == 1:
|
||||
data['atmosphere']['tendancy'] = 'rising'
|
||||
elif rising == 2:
|
||||
data['atmosphere']['tendancy'] = 'falling'
|
||||
|
||||
# current conditions
|
||||
data['item']['condition']['temp_c'] = \
|
||||
int(round(((float(data['item']['condition']['temp']) - 32) / 9) * 5))
|
||||
|
||||
# forecasts
|
||||
for i in data['item']['forecast']:
|
||||
i['high_c'] = \
|
||||
int(round(((float(i['high']) - 32) / 9) * 5))
|
||||
i['low_c'] = \
|
||||
int(round(((float(i['low']) - 32) / 9) * 5))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@hook.command(autohelp=False)
|
||||
def weather(inp, nick="", reply=None, db=None, notice=None):
|
||||
@hook.command(autohelp=None)
|
||||
def weather(inp, reply=None, db=None, nick=None, bot=None):
|
||||
"weather <location> [dontsave] -- Gets weather data"\
|
||||
" for <location> from Yahoo."
|
||||
" for <location> from Wunderground."
|
||||
|
||||
api_key = bot.config.get("api_keys", {}).get("wunderground")
|
||||
|
||||
if not api_key:
|
||||
return "Error: No wunderground API details."
|
||||
|
||||
# initalise weather DB
|
||||
db.execute("create table if not exists weather(nick primary key, loc)")
|
||||
|
@ -82,7 +24,7 @@ def weather(inp, nick="", reply=None, db=None, notice=None):
|
|||
# no location saved in the database, send the user help text
|
||||
notice(weather.__doc__)
|
||||
return
|
||||
location = location[0]
|
||||
loc = location[0]
|
||||
|
||||
# no need to save a location, we already have it
|
||||
dontsave = True
|
||||
|
@ -92,45 +34,74 @@ def weather(inp, nick="", reply=None, db=None, notice=None):
|
|||
|
||||
# remove "dontsave" from the input string after checking for it
|
||||
if dontsave:
|
||||
location = inp[:-9].strip().lower()
|
||||
loc = inp[:-9].strip().lower()
|
||||
else:
|
||||
location = inp
|
||||
loc = inp
|
||||
|
||||
location = http.quote_plus(loc)
|
||||
|
||||
conditions_url = base_url.format(api_key, "conditions", location)
|
||||
conditions = http.get_json(conditions_url)
|
||||
|
||||
# now, to get the actual weather
|
||||
try:
|
||||
data = get_weather(location)
|
||||
conditions['location']['city']
|
||||
|
||||
# found result, lets get the rest of the data
|
||||
forecast_url = base_url.format(api_key, "forecast", location)
|
||||
forecast = http.get_json(forecast_url)
|
||||
except KeyError:
|
||||
return "Could not get weather for that location."
|
||||
try:
|
||||
# try and get the closest match
|
||||
location_id = conditions['response']['results'][0]['zmw']
|
||||
except KeyError:
|
||||
return "Could not get weather for that location."
|
||||
|
||||
# get the conditions again, using the closest match
|
||||
conditions_url = base_url.format(api_key, "conditions", "zmw:" + location_id)
|
||||
conditions = http.get_json(conditions_url)
|
||||
forecast_url = base_url.format(api_key, "forecast", "zmw:" + location_id)
|
||||
forecast = http.get_json(forecast_url)
|
||||
|
||||
if conditions['location']['state']:
|
||||
place_name = "\x02{}\x02, \x02{}\x02 (\x02{}\x02)".format(conditions['location']['city'],
|
||||
conditions['location']['state'], conditions['location']['country'])
|
||||
else:
|
||||
place_name = "\x02{}\x02 (\x02{}\x02)".format(conditions['location']['city'],
|
||||
conditions['location']['country'])
|
||||
|
||||
forecast_today = forecast["forecast"]["simpleforecast"]["forecastday"][0]
|
||||
forecast_tomorrow = forecast["forecast"]["simpleforecast"]["forecastday"][1]
|
||||
|
||||
# put all the stuff we want to use in a dictionary for easy formatting of the output
|
||||
weather_data = {
|
||||
"place": data['location']['city'],
|
||||
"conditions": data['item']['condition']['text'],
|
||||
"temp_f": data['item']['condition']['temp'],
|
||||
"temp_c": data['item']['condition']['temp_c'],
|
||||
"humidity": data['atmosphere']['humidity'],
|
||||
"wind_kph": data['wind']['speed_kph'],
|
||||
"wind_mph": data['wind']['speed'],
|
||||
"wind_text": data['wind']['text'],
|
||||
"forecast": data['item']['forecast'][0]['text'],
|
||||
"high_f": data['item']['forecast'][0]['high'],
|
||||
"high_c": data['item']['forecast'][0]['high_c'],
|
||||
"low_f": data['item']['forecast'][0]['low'],
|
||||
"low_c": data['item']['forecast'][0]['low_c'],
|
||||
"_forecast": data['item']['forecast'][1]['text'],
|
||||
"_high_f": data['item']['forecast'][1]['high'],
|
||||
"_high_c": data['item']['forecast'][1]['high_c'],
|
||||
"_low_f": data['item']['forecast'][1]['low'],
|
||||
"_low_c": data['item']['forecast'][1]['low_c']
|
||||
"place": place_name,
|
||||
"conditions": conditions['current_observation']['weather'],
|
||||
"temp_f": conditions['current_observation']['temp_f'],
|
||||
"temp_c": conditions['current_observation']['temp_c'],
|
||||
"humidity": conditions['current_observation']['relative_humidity'],
|
||||
"wind_kph": conditions['current_observation']['wind_kph'],
|
||||
"wind_mph": conditions['current_observation']['wind_mph'],
|
||||
"wind_direction": conditions['current_observation']['wind_dir'],
|
||||
"today_conditions": forecast_today['conditions'],
|
||||
"today_high_f": forecast_today['high']['fahrenheit'],
|
||||
"today_high_c": forecast_today['high']['celsius'],
|
||||
"today_low_f": forecast_today['low']['fahrenheit'],
|
||||
"today_low_c": forecast_today['low']['celsius'],
|
||||
"tomorrow_conditions": forecast_tomorrow['conditions'],
|
||||
"tomorrow_high_f": forecast_tomorrow['high']['fahrenheit'],
|
||||
"tomorrow_high_c": forecast_tomorrow['high']['celsius'],
|
||||
"tomorrow_low_f": forecast_tomorrow['low']['fahrenheit'],
|
||||
"tomorrow_low_c": forecast_tomorrow['low']['celsius'],
|
||||
"url": web.isgd(conditions["current_observation"]['forecast_url'] + "?apiref=e535207ff4757b18")
|
||||
}
|
||||
|
||||
reply("\x02{place}\x02 - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, Humidity: {humidity}%, " \
|
||||
"Wind: {wind_kph}KPH/{wind_mph}MPH {wind_text}, \x02Today:\x02 {forecast}, " \
|
||||
"High: {high_f}F/{high_c}C, Low: {low_f}F/{low_c}C. " \
|
||||
"\x02Tomorrow:\x02 {_forecast}, High: {_high_f}F" \
|
||||
"/{_high_c}C, Low: {_low_f}F/{_low_c}C.".format(**weather_data))
|
||||
reply("{place} - \x02Current:\x02 {conditions}, {temp_f}F/{temp_c}C, {humidity}, "
|
||||
"Wind: {wind_kph}KPH/{wind_mph}MPH {wind_direction}, \x02Today:\x02 {today_conditions}, "
|
||||
"High: {today_high_f}F/{today_high_c}C, Low: {today_low_f}F/{today_low_c}C. "
|
||||
"\x02Tomorrow:\x02 {tomorrow_conditions}, High: {tomorrow_high_f}F/{tomorrow_high_c}C, "
|
||||
"Low: {tomorrow_low_f}F/{tomorrow_low_c}C - {url}".format(**weather_data))
|
||||
|
||||
if location and not dontsave:
|
||||
db.execute("insert or replace into weather(nick, loc) values (?,?)",
|
||||
(nick.lower(), location))
|
||||
(nick.lower(), location))
|
||||
db.commit()
|
||||
|
|
Reference in a new issue