rewrite weather.py to use openweathermap
This commit is contained in:
parent
743a3a2d34
commit
8962e93d3c
|
@ -4,7 +4,7 @@ It's like Sopel, except rewritten from scratch using Twisted as a base and over
|
|||
## Requirements
|
||||
Python 3.6+
|
||||
System packages: `enchant`
|
||||
Python packages: `twisted python-dateutil requests bs4 wolframalpha pyenchant emoji Pillow xml2dict ipython numpy numpngw`
|
||||
Python packages: `twisted python-dateutil requests bs4 wolframalpha pyenchant emoji pillow ipython numpy numpngw`
|
||||
|
||||
## TODO
|
||||
Fix the movie table
|
||||
|
|
|
@ -31,3 +31,6 @@ exchangerate_api_key = 'password'
|
|||
|
||||
""" Crypto """
|
||||
coinlib_api_key = 'password'
|
||||
|
||||
""" Weather """
|
||||
weather_api_key = 'password'
|
||||
|
|
|
@ -3,142 +3,61 @@
|
|||
The weather man.
|
||||
"""
|
||||
import requests
|
||||
import xmltodict
|
||||
|
||||
import config
|
||||
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 + ')'
|
||||
|
||||
URI = "https://api.openweathermap.org/data/2.5/weather"
|
||||
|
||||
@commands("weather")
|
||||
@example('.weather London')
|
||||
@example('.weather Hell')
|
||||
def weather(bot, trigger):
|
||||
""".weather location - Show the weather at the given location."""
|
||||
"""
|
||||
Show the weather at the given location.
|
||||
|
||||
-m, --metric - uses metric units instead of imperial.
|
||||
"""
|
||||
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')
|
||||
location = trigger.group(3)
|
||||
if location == '-m' or location == '--metric':
|
||||
location = trigger.group(4)
|
||||
units = 'metric'
|
||||
else:
|
||||
units = 'imperial'
|
||||
|
||||
if not woeid:
|
||||
return bot.reply("I don't know where that is.")
|
||||
params = {
|
||||
'q': location,
|
||||
'appid': config.weather_api_key,
|
||||
'units': units
|
||||
}
|
||||
res = requests.get(URI, params=params, verify=True)
|
||||
data = res.json()
|
||||
if data['cod'] == 404:
|
||||
return bot.reply("City not found. Try a different query.")
|
||||
|
||||
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.msg(u'%s: %s, %s, %s, %s' % (location, cover, temp, humidity, wind))
|
||||
city = data.get('name')
|
||||
country = data['sys']['country']
|
||||
sky = data['weather'][0]['main']
|
||||
temp = data['main']['temp']
|
||||
humidity = data['main']['humidity']
|
||||
wind = data['wind']['speed']
|
||||
degrees = data['wind']['deg']
|
||||
|
||||
msg = "[\x0304Weather\x03] "
|
||||
msg += f"\x0310City\x03: \x0312{city}\x03, \x0312{country}\x03 | "
|
||||
msg += f"\x0310Sky: \x0312{sky}\x03 | "
|
||||
msg += f"\x0310Temp\x03: \x0308{temp}\u00B0"
|
||||
if units == 'imperial':
|
||||
msg += "F\x03 | "
|
||||
else:
|
||||
msg += "C\x03 | "
|
||||
msg += f"\x0310Humidity\x03: \x0308{humidity}%\x03 | "
|
||||
msg += f"\x0310Wind\x03: \x0308{wind}"
|
||||
if units == 'imperial':
|
||||
msg += "mph"
|
||||
else:
|
||||
msg += "m/s"
|
||||
if degrees:
|
||||
msg += f"\x03 (\x0308{degrees}\u00B0\x03)"
|
||||
bot.msg(msg)
|
||||
|
|
Loading…
Reference in New Issue
Block a user