Source code for modules.weather

# -*- coding: utf-8 -*-

import json
import sys
import requests
from event import Event

if sys.version_info > (3, 0, 0):
    try:
        from .basemodule import BaseModule
    except (ImportError, SystemError):
        from modules.basemodule import BaseModule
else:
    try:
        from basemodule import BaseModule
    except (ImportError, SystemError):
        from modules.basemodule import BaseModule

try:
    from owm_api import Owm_Api as oa
except (ImportError, SystemError):
    print("Warning: weather module requires credentials in $PYBOT_ROOT/owm_api.py")

[docs] class Phony_Owm_Api: api_key = "None"
oa = Phony_Owm_Api()
[docs]class Weather(BaseModule):
[docs] def post_init(self): weather2 = Event('__.weather2__') weather2.define( msg_definition=r'^\.weather |^\.w ', case_insensitive=True) weather2.subscribe(self) self.bot.register_event(weather2, self) # two apis because we get the lat/long from openmeteo self.meteo_api_url = "https://geocoding-api.open-meteo.com/v1/search?count=10&language=en&format=json&name=" self.api_url = "https://api.openweathermap.org/data/2.5/weather" self.api_key = oa.api_key self.headers = { 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36', }
[docs] def get_lat_long_from_bing(self, location): """ Returns: tuple of x,y coordinates - (0,0) on error """ u = self.meteo_api_url + location # print(u) j = json.loads(requests.get(u, self.headers).text) # print(j['results'][0]) try: x = j['results'][0]['latitude'] y = j['results'][0]['longitude'] except IndexError: return (0, 0) return (x, y)
[docs] def get_api_request(self, x, y): """ Simple form the query string and return it. """ return self.api_url + "?lat=" + \ str(x) + "&lon=" + str(y) + \ "&units=imperial" + "&appid=" + self.api_key
[docs] def get_conditions(self, query, channel): """given a fully formed query to the OpenWeatherMap API, format an output string""" r = requests.get(query) try: r.raise_for_status() except requests.exceptions.HTTPError: self.say( channel, "Encountered an error contacting the OpenWeatherMap API") return weather = r.json() # print(weather) try: # grab the relevant data we want for formatting location = weather['name'] conditions = weather['weather'][0]['main'] if conditions == "Clear": icon = '\N{sun}' elif conditions == "Rain" or conditions == "Drizzle": icon = '\N{cloud with rain}' elif conditions == "Thunderstorm": icon = '\N{cloud with lightning}' elif conditions == "Clouds": icon = '\N{cloud}' elif conditions == "Snow": icon = '\N{cloud with snow}' elif conditions == "Mist": icon = '\N{fog}' else: icon = '\N{fire}' temp_f = round(weather['main']['temp'], 1) temp_c = round((temp_f - 32) * (5.0 / 9.0), 1) # sky = weather['weather'][0]['main'] # print(sky) except KeyError: self.say( channel, "Unable to get weather data from results. Sorry.") return # return the formatted string of weather data # return location + ': ' + conditions + " 🌧️ " + ', ' + \ return location + ': ' + conditions + ' ' + icon + ', ' + \ str(temp_f) + '°F (' + str(temp_c) + '°C)'
[docs] def handle(self, event): # split the line beginning with .weather into 2 parts, the command and # the search string weather_line = event.msg.split(None, 1) if len(weather_line) > 1: # if we're sure there's actually a search string, then continue x, y = self.get_lat_long_from_bing(weather_line[1]) weather = self.get_conditions( self.get_api_request( x, y), event.channel) if not weather: return self.say(event.channel, weather) else: # chastise the user for being silly and not actually searching for # a location self.say( event.channel, "It would help if you supplied an actual location to search for.")