fulvia/modules/weather.py
2018-03-16 03:13:43 -04:00

145 lines
3.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
The weather man.
"""
import requests
import xmltodict
from module import commands, example
URI = "https://query.yahooapis.com/v1/public/yql?{QUERY}"
def woeid_search(query):
"""
Find the first Where On Earth ID for the given query. Result is the etree
node for the result, so that location data can still be retrieved. Returns
None if there is no result, or the woeid field is empty.
"""
query = f'q=select * from geo.places where text="{query}"'
res = requests.get(URI.format(**{"QUERY": query}), verify=True)
body = res.content
parsed = xmltodict.parse(body).get('query')
results = parsed.get('results')
if results is None or results.get('place') is None:
return None
if type(results.get('place')) is list:
return results.get('place')[0]
return results.get('place')
def get_cover(parsed):
try:
condition = parsed['channel']['item']['yweather:condition']
except KeyError:
return 'unknown'
text = condition['@text']
# code = int(condition['code'])
# TODO parse code to get those little icon thingies.
return text
def get_temp(parsed):
try:
condition = parsed['channel']['item']['yweather:condition']
temp = int(condition['@temp'])
except (KeyError, ValueError):
return 'unknown'
f = round((temp * 1.8) + 32, 2)
return (u'%d\u00B0C (%d\u00B0F)' % (temp, f))
def get_humidity(parsed):
try:
humidity = parsed['channel']['yweather:atmosphere']['@humidity']
except (KeyError, ValueError):
return 'unknown'
return "Humidity: %s%%" % humidity
def get_wind(parsed):
try:
wind_data = parsed['channel']['yweather:wind']
kph = float(wind_data['@speed'])
m_s = float(round(kph / 3.6, 1))
speed = int(round(kph / 1.852, 0))
degrees = int(wind_data['@direction'])
except (KeyError, ValueError):
return 'unknown'
if speed < 1:
description = 'Calm'
elif speed < 4:
description = 'Light air'
elif speed < 7:
description = 'Light breeze'
elif speed < 11:
description = 'Gentle breeze'
elif speed < 16:
description = 'Moderate breeze'
elif speed < 22:
description = 'Fresh breeze'
elif speed < 28:
description = 'Strong breeze'
elif speed < 34:
description = 'Near gale'
elif speed < 41:
description = 'Gale'
elif speed < 48:
description = 'Strong gale'
elif speed < 56:
description = 'Storm'
elif speed < 64:
description = 'Violent storm'
else:
description = 'Hurricane'
if (degrees <= 22.5) or (degrees > 337.5):
degrees = u'\u2193'
elif (degrees > 22.5) and (degrees <= 67.5):
degrees = u'\u2199'
elif (degrees > 67.5) and (degrees <= 112.5):
degrees = u'\u2190'
elif (degrees > 112.5) and (degrees <= 157.5):
degrees = u'\u2196'
elif (degrees > 157.5) and (degrees <= 202.5):
degrees = u'\u2191'
elif (degrees > 202.5) and (degrees <= 247.5):
degrees = u'\u2197'
elif (degrees > 247.5) and (degrees <= 292.5):
degrees = u'\u2192'
elif (degrees > 292.5) and (degrees <= 337.5):
degrees = u'\u2198'
return description + ' ' + str(m_s) + 'm/s (' + degrees + ')'
@commands("weather")
@example('.weather London')
def weather(bot, trigger):
""".weather location - Show the weather at the given location."""
if not trigger.group(2):
return bot.reply("Weather where?")
location = trigger.group(2)
location = location.strip()
first_result = woeid_search(location)
woeid = None
if first_result is not None:
woeid = first_result.get('woeid')
if not woeid:
return bot.reply("I don't know where that is.")
query =f"q=select * from weather.forecast where woeid=\"{woeid}\" and u='c'"
res = requests.get(URI.format(**{"QUERY": query}), verify=True)
body = res.content
parsed = xmltodict.parse(body).get('query')
results = parsed.get('results')
if results is None:
return bot.reply("No forecast available. Try a more specific location.")
location = results.get('channel').get('title')
cover = get_cover(results)
temp = get_temp(results)
humidity = get_humidity(results)
wind = get_wind(results)
bot.say(u'%s: %s, %s, %s, %s' % (location, cover, temp, humidity, wind))