diff --git a/environment/template b/environment/template index 7d47bcc..c70b7fd 100644 --- a/environment/template +++ b/environment/template @@ -3,6 +3,7 @@ ######################## export DISCORD_BOT_TOKEN=<> +export OPENWEATHER_API_TOKEN=<> export MYSQL_HOST=<> export MYSQL_PORT=<> export MYSQL_DATABASE=<> diff --git a/requirements/common.txt b/requirements/common.txt index 78a6c39..138a057 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -1,3 +1,5 @@ discord.py mysqlclient SQLAlchemy +json +pyre2 \ No newline at end of file diff --git a/settings/config.py b/settings/config.py index a6b3dc7..7435b77 100644 --- a/settings/config.py +++ b/settings/config.py @@ -80,4 +80,10 @@ PERMISSIONS = { 'v' : ['Operador', 'BotMan'] } +OW_API_CONFIG = { + 'api_id' : os.environ.get('OPENWEATHER_API_TOKEN'), + 'gc_url' : 'http://api.openweathermap.org/geo/1.0/direct?q=,,&limit=1&appid=', + 'wh_url' : 'https://api.openweathermap.org/data/2.5/weather?lat=&lon=&units=metric&appid=' +} + logger.dictConfig(LOGGING_CONFIG) diff --git a/utils/commands.py b/utils/commands.py index 823d109..e0f2c89 100644 --- a/utils/commands.py +++ b/utils/commands.py @@ -3,10 +3,12 @@ Bot commands. """ import logging from random import choice +import re2 from discord.ext import commands from utils.database import get_by_id, get_quotes, remove_quote, set_quote, count_quotes +from utils.weather import geocode, getweatherdata, displayweather from settings.config import PERMISSIONS @@ -178,4 +180,42 @@ async def info(bot: object) -> str: fullbanner = fullbanner + lines msg = f'''```\n''' + fullbanner + f'''\n```''' - return await bot.send(msg) \ No newline at end of file + return await bot.send(msg) + +@client.command(aliases=['w']) +async def weather(bot: object, *location: str) -> str: + """ + Displays the weather information for a given place + """ + if location: + location = str(location) + stripped = re2.sub(" ", "", location) # Strips all whitespace + separated = stripped.split(',') # Splits between commas + separated.pop(-1) + separated[0] = separated[0][1:len(separated[0])] # These two commands clean up input for the parser + + if len(separated) > 3: + return await bot.send("This command takes 3 parameters at most!") + if len(separated) == 1: + city = separated[0] + state = "" + country = "" + elif len(separated) == 2: + city = separated[0] + state = separated[1] + country = "" + else: + city = separated[0] + state = separated[1] + country = separated[2] + else: + city = "" + state = "" + country = "" + + lat, lon = geocode(city, state, country) + weatherdata = getweatherdata(lat, lon) + msg = displayweather(weatherdata) + + return await bot.send(msg) + \ No newline at end of file diff --git a/utils/weather.py b/utils/weather.py new file mode 100644 index 0000000..b672cb7 --- /dev/null +++ b/utils/weather.py @@ -0,0 +1,98 @@ +import logging + +from settings.config import OW_API_CONFIG + +import urllib.request +import json +import re2 + +def geocode(city = 'curitiba', state = 'parana', country = 'BR') -> str: + """ + Converts city, state and country parameters into their coordinates + """ + if city == "" and state == "" and country == "": + city = 'curitiba' + state = 'parana' + country = 'BR' + ow_gc_url = OW_API_CONFIG['gc_url'] + ow_gc_url = re2.sub('', city, ow_gc_url) + ow_gc_url = re2.sub('', state, ow_gc_url) + ow_gc_url = re2.sub('', OW_API_CONFIG['api_id'], ow_gc_url) + + placedata = urllib.request.urlopen(ow_gc_url) + placedata = placedata.read().decode() + placedata = json.loads(str(placedata)) + + return str(placedata[0]['lat']), str(placedata[0]['lon']) + +def getweatherdata(lat, lon): + """ + Gets weather data based on coordinates + """ + ow_wh_url = OW_API_CONFIG['wh_url'] + ow_wh_url = re2.sub('', lat, ow_wh_url) + ow_wh_url = re2.sub('', lon, ow_wh_url) + ow_wh_url = re2.sub('', OW_API_CONFIG['api_id'], ow_wh_url) + + weatherdata = urllib.request.urlopen(ow_wh_url) + weatherdata = weatherdata.read().decode() + weatherdata = json.loads(str(weatherdata)) + + return weatherdata + +def displayweather(wdata): + """ + "Prettifies" the output for discord + """ + try: + wdata['weather'][0]['description'] + description = wdata['weather'][0]['description'] + except: + description = "No data on description" + try: + wdata['main']['temp'] + temp = wdata['main']['temp'] + tempmsg = f"Temperature is {temp}ºC" + except: + tempmsg = "No data on temperature" + try: + wdata['main']['feels_like'] + feels_like = wdata['main']['feels_like'] + feels_likemsg = f"Feels like {feels_like}ºC" + except: + feels_likemsg = "No data on perceived temperature" + try: + wdata['main']['humidity'] + humidity = wdata['main']['humidity'] + humiditymsg = f"Humidity is {humidity}%" + except: + humiditymsg = "No data on humidity" + try: + wdata['wind']['speed'] + wind_speed = wdata['wind']['speed'] + wind_speedmsg = f"Wind speed is {wind_speed}m/s" + except: + wind_speedmsg = "No data on wind speed" + try: + wdata['wind']['gust'] + wind_gusts = wdata['wind']['gust'] + wind_gustsmsg = f"with gusts of {wind_gusts}m/s" + except: + wind_gustsmsg = "with no data on gusts" + try: + wdata['clouds']['all'] + cloud_coverage = wdata['clouds']['all'] + cloud_coveragemsg = f"Cloud coverage is {cloud_coverage}%" + except: + cloud_coveragemsg = "No data on cloud coverage" + name = wdata['name'] + + msg = f""" + ``` + Weather for {name}: + {description}, {tempmsg}. {feels_likemsg}. {humiditymsg}. + {wind_speedmsg}, {wind_gustsmsg}. {cloud_coveragemsg}. + ```""" + + return msg \ No newline at end of file