From 1bd57a8c3b8ba2337024adbad47884ff9e9c50a5 Mon Sep 17 00:00:00 2001 From: "Brian S. Stephan" Date: Fri, 15 May 2015 21:23:01 -0500 Subject: [PATCH] Weather: ported to new bot. deleted --- ircbot/modules/Weather.py | 296 -------------------------------------- 1 file changed, 296 deletions(-) delete mode 100644 ircbot/modules/Weather.py diff --git a/ircbot/modules/Weather.py b/ircbot/modules/Weather.py deleted file mode 100644 index 1022af6..0000000 --- a/ircbot/modules/Weather.py +++ /dev/null @@ -1,296 +0,0 @@ -# coding: utf-8 -""" -Weather - query weather underground for info -Copyright (C) 2010 Brian S. Stephan - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -""" - -import json -import MySQLdb as mdb -import re -import urllib2 - -from Module import Module - -class Weather(Module): - """Provide weather lookup services to the bot.""" - - def __init__(self, irc, config): - """Set up regexes and wunderground API.""" - - Module.__init__(self, irc, config) - - self.weatherre = re.compile("^!weather\s+(.*)$") - - # get the API key from config - api_key = self._get_api_key_from_db() - if api_key is None: - raise Exception("weather underground API key not found!") - - self.wu_base = 'http://api.wunderground.com/api/{0:s}/'.format(api_key) - - def db_init(self): - """Initialize the tiny table that stores the API key.""" - - version = self.db_module_registered(self.__class__.__name__) - if version == None: - db = self.get_db() - try: - version = 1 - cur = db.cursor(mdb.cursors.DictCursor) - cur.execute(''' - CREATE TABLE weather_settings ( - api_key VARCHAR(256) NOT NULL - ) - ''') - - db.commit() - self.db_register_module_version(self.__class__.__name__, version) - except mdb.Error as e: - db.rollback() - self.log.error("database error trying to create tables") - self.log.exception(e) - raise - finally: cur.close() - - def do(self, connection, event, nick, userhost, what, admin_unlocked): - """Handle IRC input for a weather queries.""" - - match = self.weatherre.search(what) - if match: - # see if there was a specific command given in the query, first - query = match.group(1) - queryitems = query.split(" ") - if len(queryitems) <= 0: - return - - # search for commands - if queryitems[0] == "conditions": - # current weather query - results = self.get_conditions_for_query(queryitems[1:]) - return self.irc.reply(event, results) - elif queryitems[0] == "forecast": - # forecast query - results = self.get_forecast_for_query(queryitems[1:]) - return self.irc.reply(event, results) - else: - # assume they wanted current weather - results = self.get_conditions_for_query(queryitems) - return self.irc.reply(event, results) - - def get_conditions_for_query(self, queryitems): - """Make a wunderground conditions call, return as string.""" - - # recombine the query into a string - query = ' '.join(queryitems) - query = query.replace(' ', '_') - - try: - url = self.wu_base + ('{0:s}/q/{1:s}.json'.format('conditions', - query)) - json_resp = urllib2.urlopen(url) - condition_data = json.load(json_resp) - except IOError as e: - self.log.error("error while making conditions query") - self.log.exception(e) - raise - - # condition data is loaded. the rest of this is obviously specific to - # http://www.wunderground.com/weather/api/d/docs?d=data/conditions - self.log.debug(json.dumps(condition_data, sort_keys=True, indent=4)) - - try: - # just see if we have current_observation data - current = condition_data['current_observation'] - except KeyError as e: - # ok, try to see if the ambiguous results stuff will help - self.log.debug("potentially ambiguous results, checking") - try: - results = condition_data['response']['results'] - reply = "Multiple results, try one of the following zmw codes:" - for res in results[:-1]: - q = res['l'].strip('/q/') - reply += " {0:s} ({1:s}, {2:s}),".format(q, res['name'], - res['country_name']) - q = results[-1]['l'].strip('/q/') - reply += " or {0:s} ({1:s}, {2:s}).".format(q, results[-1]['name'], - results[-1]['country_name']) - return reply - except KeyError as e: - # now we really know something is wrong - self.log.error("error or bad query in conditions lookup") - self.log.exception(e) - return "No results." - else: - try: - location = current['display_location']['full'] - reply = "Conditions for {0:s}: ".format(location) - - weather_str = current['weather'] - if weather_str != '': - reply += "{0:s}, ".format(weather_str) - - temp_f = current['temp_f'] - temp_c = current['temp_c'] - temp_str = current['temperature_string'] - if temp_f != '' and temp_c != '': - reply += "{0:.1f}°F ({1:.1f}°C)".format(temp_f, temp_c) - elif temp_str != '': - reply += "{0:s}".format(temp_str) - - # append feels like if we have it - feelslike_f = current['feelslike_f'] - feelslike_c = current['feelslike_c'] - feelslike_str = current['feelslike_string'] - if feelslike_f != '' and feelslike_c != '': - reply += ", feels like {0:s}°F ({1:s}°C)".format(feelslike_f, feelslike_c) - elif feelslike_str != '': - reply += ", feels like {0:s}".format(feelslike_str) - - # whether this is current or current + feelslike, terminate sentence - reply += ". " - - humidity_str = current['relative_humidity'] - if humidity_str != '': - reply += "Humidity: {0:s}. ".format(humidity_str) - - wind_str = current['wind_string'] - if wind_str != '': - reply += "Wind: {0:s}. ".format(wind_str) - - pressure_in = current['pressure_in'] - pressure_trend = current['pressure_trend'] - if pressure_in != '': - reply += "Pressure: {0:s}\"".format(pressure_in) - if pressure_trend != '': - reply += " and {0:s}".format("dropping" if pressure_trend == '-' else "rising") - reply += ". " - - heat_index_str = current['heat_index_string'] - if heat_index_str != '' and heat_index_str != 'NA': - reply += "Heat index: {0:s}. ".format(heat_index_str) - - windchill_str = current['windchill_string'] - if windchill_str != '' and windchill_str != 'NA': - reply += "Wind chill: {0:s}. ".format(windchill_str) - - visibility_mi = current['visibility_mi'] - if visibility_mi != '': - reply += "Visibility: {0:s} miles. ".format(visibility_mi) - - precip_in = current['precip_today_in'] - if precip_in != '': - reply += "Precipitation today: {0:s}\". ".format(precip_in) - - observation_time = current['observation_time'] - if observation_time != '': - reply += "{0:s}. ".format(observation_time) - - return self._prettify_weather_strings(reply.rstrip()) - except KeyError as e: - self.log.error("error or unexpected results in conditions reply") - self.log.exception(e) - return "Error parsing results." - - def get_forecast_for_query(self, queryitems): - """Make a wunderground forecast call, return as string.""" - - # recombine the query into a string - query = ' '.join(queryitems) - query = query.replace(' ', '_') - - try: - url = self.wu_base + ('{0:s}/q/{1:s}.json'.format('forecast', - query)) - json_resp = urllib2.urlopen(url) - forecast_data = json.load(json_resp) - except IOError as e: - self.log.error("error while making forecast query") - self.log.exception(e) - raise - - # forecast data is loaded. the rest of this is obviously specific to - # http://www.wunderground.com/weather/api/d/docs?d=data/forecast - self.log.debug(json.dumps(forecast_data, sort_keys=True, indent=4)) - - try: - # just see if we have forecast data - forecasts = forecast_data['forecast']['txt_forecast'] - except KeyError as e: - # ok, try to see if the ambiguous results stuff will help - self.log.debug("potentially ambiguous results, checking") - try: - results = forecast_data['response']['results'] - reply = "Multiple results, try one of the following zmw codes:" - for res in results[:-1]: - q = res['l'].strip('/q/') - reply += " {0:s} ({1:s}, {2:s}),".format(q, res['name'], - res['country_name']) - q = results[-1]['l'].strip('/q/') - reply += " or {0:s} ({1:s}, {2:s}).".format(q, results[-1]['name'], - results[-1]['country_name']) - return reply - except KeyError as e: - # now we really know something is wrong - self.log.error("error or bad query in forecast lookup") - self.log.exception(e) - return "No results." - else: - try: - reply = "Forecast: " - for forecast in forecasts['forecastday'][0:5]: - reply += "{0:s}: {1:s} ".format(forecast['title'], - forecast['fcttext']) - - return self._prettify_weather_strings(reply.rstrip()) - except KeyError as e: - self.log.error("error or unexpected results in forecast reply") - self.log.exception(e) - return "Error parsing results." - - def _get_api_key_from_db(self): - """Get the API key string from the database, or None if unset.""" - - api_key = None - db = self.get_db() - try: - cur = db.cursor(mdb.cursors.DictCursor) - query = '''SELECT api_key FROM weather_settings''' - cur.execute(query) - value = cur.fetchone() - if (value != None): - api_key = value['api_key'] - except mdb.Error as e: - self.log.error("database error during api key retrieval") - self.log.exception(e) - finally: cur.close() - - return api_key - - def _prettify_weather_strings(self, weather_str): - """ - Clean up output strings. - - For example, turn 32F into 32°F in input string. - - Input: - weather_str --- the string to clean up - - """ - - return re.sub(r'(\d+)\s*([FC])', r'\1°\2', weather_str) - -# vi:tabstop=4:expandtab:autoindent -# kate: indent-mode python;indent-width 4;replace-tabs on;