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
|
## Requirements
|
||||||
Python 3.6+
|
Python 3.6+
|
||||||
System packages: `enchant`
|
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
|
## TODO
|
||||||
Fix the movie table
|
Fix the movie table
|
||||||
|
|
|
@ -31,3 +31,6 @@ exchangerate_api_key = 'password'
|
||||||
|
|
||||||
""" Crypto """
|
""" Crypto """
|
||||||
coinlib_api_key = 'password'
|
coinlib_api_key = 'password'
|
||||||
|
|
||||||
|
""" Weather """
|
||||||
|
weather_api_key = 'password'
|
||||||
|
|
|
@ -3,142 +3,61 @@
|
||||||
The weather man.
|
The weather man.
|
||||||
"""
|
"""
|
||||||
import requests
|
import requests
|
||||||
import xmltodict
|
|
||||||
|
|
||||||
|
import config
|
||||||
from module import commands, example
|
from module import commands, example
|
||||||
|
|
||||||
URI = "https://query.yahooapis.com/v1/public/yql?{QUERY}"
|
URI = "https://api.openweathermap.org/data/2.5/weather"
|
||||||
|
|
||||||
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")
|
@commands("weather")
|
||||||
@example('.weather London')
|
@example('.weather Hell')
|
||||||
def weather(bot, trigger):
|
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):
|
if not trigger.group(2):
|
||||||
return bot.reply("Weather where?")
|
return bot.reply("Weather where?")
|
||||||
location = trigger.group(2)
|
location = trigger.group(3)
|
||||||
location = location.strip()
|
if location == '-m' or location == '--metric':
|
||||||
first_result = woeid_search(location)
|
location = trigger.group(4)
|
||||||
woeid = None
|
units = 'metric'
|
||||||
if first_result is not None:
|
else:
|
||||||
woeid = first_result.get('woeid')
|
units = 'imperial'
|
||||||
|
|
||||||
if not woeid:
|
params = {
|
||||||
return bot.reply("I don't know where that is.")
|
'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'"
|
city = data.get('name')
|
||||||
res = requests.get(URI.format(**{"QUERY": query}), verify=True)
|
country = data['sys']['country']
|
||||||
body = res.content
|
sky = data['weather'][0]['main']
|
||||||
parsed = xmltodict.parse(body).get('query')
|
temp = data['main']['temp']
|
||||||
results = parsed.get('results')
|
humidity = data['main']['humidity']
|
||||||
if results is None:
|
wind = data['wind']['speed']
|
||||||
return bot.reply("No forecast available. Try a more specific location.")
|
degrees = data['wind']['deg']
|
||||||
location = results.get('channel').get('title')
|
|
||||||
cover = get_cover(results)
|
msg = "[\x0304Weather\x03] "
|
||||||
temp = get_temp(results)
|
msg += f"\x0310City\x03: \x0312{city}\x03, \x0312{country}\x03 | "
|
||||||
humidity = get_humidity(results)
|
msg += f"\x0310Sky: \x0312{sky}\x03 | "
|
||||||
wind = get_wind(results)
|
msg += f"\x0310Temp\x03: \x0308{temp}\u00B0"
|
||||||
bot.msg(u'%s: %s, %s, %s, %s' % (location, cover, temp, humidity, wind))
|
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