forecast.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. from event import Event
  2. import json
  3. try:
  4. import requests
  5. except ImportError:
  6. print "Warning: forecast module requires requests"
  7. requests = object
  8. class Forecast:
  9. def __init__(self, events=None, printer_handle=None, bot=None, say=None):
  10. self.events = events
  11. self.printer = printer_handle
  12. self.interests = ['__.forecast__']
  13. self.bot = bot
  14. forecast = Event("__.forecast__")
  15. forecast.define(msg_definition="^\.forecast")
  16. forecast.subscribe(self)
  17. self.bot.register_event(forecast, self)
  18. self.help = ".forecast <location>"
  19. def get_location(self, location_search):
  20. """Returns a list of 3 strings. A formatted location, its latitude, and its longitude"""
  21. if location_search == '':
  22. return None
  23. address = location_search.replace(' ', '+')
  24. key = 'AIzaSyBr4KECytQxPN8PDZhWczIvyK7voqjdN3c'
  25. #key = "AIzaSyA95TSuDZMUySAeijsNuIiqX7cJFbXKUSw"
  26. parameters = {'address': address, 'sensor': 'false', 'key': key}
  27. try:
  28. raw = requests.get('https://maps.googleapis.com/maps/api/geocode/json', params=parameters)
  29. raw.raise_for_status()
  30. geocode = raw.json()
  31. except ValueError:
  32. return ['Error: Cannot form json object']
  33. except requests.exceptions.HTTPError:
  34. return ['Trouble retrieving data from Google API']
  35. try:
  36. latitude = geocode['results'][0]['geometry']['location']['lat']
  37. longitude = geocode['results'][0]['geometry']['location']['lng']
  38. location_name = geocode['results'][0]['formatted_address']
  39. except (IndexError, KeyError), e:
  40. return ['Location not found']
  41. return [location_name, str(latitude), str(longitude)]
  42. def get_forecast(self, latitude="", longitude=""):
  43. """Returns a JSON formatted object with all weather data on the requested
  44. latitude and longitude. latitude and longitude are strings
  45. """
  46. key = "5a9290d413a126311a547f2de4f510c6"
  47. try:
  48. return requests.get('https://api.forecast.io/forecast/'+key+'/'+latitude+','+longitude).json()
  49. except ValueError:
  50. return {}
  51. def current(self, current_data={}):
  52. """Takes a JSON formatted object of data on current weather conditions from forecast.io
  53. Formats into a summarized string for IRC bot use
  54. """
  55. #if no data provided, return a string saying so
  56. conditions = ''
  57. if current_data == {}:
  58. return "No data on current weather conditions."
  59. #Add the data on current temperature. We round the data, cast as int, add into the string
  60. conditions += str(int(round(current_data['temperature']))) + u'\u00B0.'
  61. #Add data on cloud cover. Should alway be available. Descriptions taken from forecast.io api docs
  62. if current_data['cloudCover'] >= 0 and current_data['cloudCover'] < 0.4:
  63. conditions += " Clear skies."
  64. elif current_data['cloudCover'] >= 0.4 and current_data['cloudCover'] < 0.75:
  65. conditions += " Partly cloudy."
  66. elif current_data['cloudCover'] >= 0.75 and current_data['cloudCover'] < 1:
  67. conditions += " Mostly cloudy."
  68. else:
  69. conditions += " Overcast."
  70. #If there is any precipitation data, get the intensity and type of precipitation added into the description
  71. try:
  72. if current_data['precipIntensity'] > 0:
  73. if current_data['precipIntensity'] > 0 and current_data['precipIntensity'] <= 0.017:
  74. conditions += " Very light "
  75. elif current_data['precipIntensity'] > 0.017 and current_data['precipIntensity'] <= 0.1:
  76. conditions += " Light "
  77. elif current_data['precipIntensity'] >= 0.1 and current_data['precipIntensity'] < 0.4:
  78. conditions += " Moderate "
  79. elif current_data['precipIntensity'] >= 0.4:
  80. conditions += " Heavy "
  81. conditions += current_data['precipType'] + '.'
  82. except KeyError:
  83. pass
  84. return conditions
  85. def handle(self, event):
  86. _z = str.split(event.msg, None, 1)
  87. #print "Debugging: Reached stage 1 of handle()"
  88. if _z[1] != '':
  89. cur = ''
  90. loc = self.get_location(_z[1])
  91. if len(loc) == 3: #if there are 3 items, valid data retrieved. if not, it didn't work
  92. cur = ': ' + self.current(self.get_forecast(loc[1], loc[2])['currently'])
  93. try:
  94. self.printer("PRIVMSG " + event.channel + ' :' + loc[0] + cur + '\n')
  95. except TypeError:
  96. print "DEBUG: TypeError: ",
  97. print event.channel,
  98. print event.user