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