Class: Lita::Handlers::OnewheelAqi

Inherits:
Handler
  • Object
show all
Defined in:
lib/lita/handlers/onewheel_aqi.rb

Constant Summary collapse

REDIS_KEY =
'onewheel-aqi'

Instance Method Summary collapse

Instance Method Details

#aqi_irc_emojiObject



83
84
85
86
87
88
89
90
# File 'lib/lita/handlers/onewheel_aqi.rb', line 83

def aqi_irc_emoji
  { 0..50 => '🌳',
    51..100 => '⚠️',
    101..150 => '🔶',
    151..200 => '🚫',
    201..300 => '☣️',
    301..999 => '🚫☣🚫' }
end

#aqi_range_colorsObject

Based on the temp in F.



56
57
58
59
60
61
62
63
# File 'lib/lita/handlers/onewheel_aqi.rb', line 56

def aqi_range_colors
  { 0..50 => :green,
    51..100 => :yellow,
    101..150 => :orange,
    151..200 => :red,
    201..300 => :purple,
    301..999 => :pink }
end

#aqi_range_labelsObject



65
66
67
68
69
70
71
72
# File 'lib/lita/handlers/onewheel_aqi.rb', line 65

def aqi_range_labels
  { 0..50 => 'Good',
    51..100 => 'Moderate',
    101..150 => 'Unhealthy for Sensitive Groups',
    151..200 => 'Unhealthy for All',
    201..300 => 'Very Unhealthy',
    301..999 => 'Hazardous' }
end

#aqi_slack_emojiObject



74
75
76
77
78
79
80
81
# File 'lib/lita/handlers/onewheel_aqi.rb', line 74

def aqi_slack_emoji
  { 0..50 => ':deciduous_tree:',
    51..100 => ':warning:',
    101..150 => ':large_orange_diamond:',
    151..200 => ':no_entry_sign:',
    201..300 => ':radioactive_sign:',
    301..999 => ':no_entry_sign: :radioactive_sign: :no_entry_sign:' }
end

#color_str(str, value = nil) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/lita/handlers/onewheel_aqi.rb', line 233

def color_str(str, value = nil)
  value = str.to_i if value.nil?

  aqi_range_colors.keys.each do |color_key|
    next unless color_key.cover? value # Super secred cover sauce
    if config.mode == :irc
      color = colors[aqi_range_colors[color_key]]
      str = "\x03#{color}#{str}\x03"
    end
  end

  str
end

#color_str_with_value(range_str:, range_value:) ⇒ Object



247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/lita/handlers/onewheel_aqi.rb', line 247

def color_str_with_value(range_str:, range_value:)
  str = nil
  aqi_range_colors.keys.each do |color_key|
    next unless color_key.cover? range_value.to_i # Super secred cover sauce
    color = colors[aqi_range_colors[color_key]]
    if config.mode == :irc
      str = "#{aqi_irc_emoji[color_key]} \x03#{color}#{range_str[color_key]}\x03 #{aqi_irc_emoji[color_key]} "
    elsif config.mode == :slack
      str = "#{aqi_slack_emoji[color_key]} #{range_str[color_key]} #{aqi_slack_emoji[color_key]} "
    end
  end

  str
end

#colorsObject

IRC colors.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/lita/handlers/onewheel_aqi.rb', line 36

def colors
  { white:  '00',
    black:  '01',
    blue:   '02',
    green:  '03',
    red:    '04',
    brown:  '05',
    purple: '06',
    orange: '07',
    yellow: '08',
    lime:   '09',
    teal:   '10',
    aqua:   '11',
    royal:  '12',
    pink:   '13',
    grey:   '14',
    silver: '15' }
end

#get_aqi(response) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/lita/handlers/onewheel_aqi.rb', line 148

def get_aqi(response)
  loc = get_location(response)
  aqi = get_observed_aqi(loc)

  if aqi['status'] == 'nug'
    response.reply "Status is 'nug' for aqi station near #{loc['name']}"
    return
  end

  banner_str = "(#{aqi['data']['city']['url']})"

  reply = "AQI for #{loc[:name]}, "

  Lita.logger.debug "Config mode: #{config.mode.inspect}"

  if config.mode == :irc
    reply += color_str_with_value(range_str: aqi_range_labels, range_value: aqi['data']['iaqi']['pm25']['v'].to_s)
    banner_str = "\x03#{colors[:grey]}#{banner_str}\x03"
  elsif config.mode == :slack
    reply += color_str_with_value(range_str: aqi_range_labels, range_value: aqi['data']['iaqi']['pm25']['v'].to_s)
  end

  if aqi['data']['iaqi']['pm25']
    reply += 'pm25: ' + color_str(aqi['data']['iaqi']['pm25']['v'].to_s) + '  '
    ugm3 = pm25_to_ugm3 aqi['data']['iaqi']['pm25']['v'].to_s
    reply += "µg/m³(est): #{ugm3}  "
  end
  if aqi['data']['iaqi']['pm10']
    reply += 'pm10: ' + color_str(aqi['data']['iaqi']['pm10']['v'].to_s) + '  '
  end

  updated_at = Time.parse aqi['data']['time']['s']
  diff = (Time.now - updated_at).to_i / 60

  reply += "updated #{color_str(diff.to_s)} minutes ago.  #{banner_str}"

  response.reply reply
end

#get_aqi_deets(response) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/lita/handlers/onewheel_aqi.rb', line 187

def get_aqi_deets(response)
  loc = get_location(response)
  aqi = get_observed_aqi(loc)

  if aqi['status'] == 'nug'
    response.reply "Status is 'nug' for aqi station near #{loc['name']}"
    return
  end

  reply = "AQI for #{loc[:name]}, "

  banner_str = "(#{aqi['data']['city']['url']})"

  if config.mode == :irc
    reply += color_str_with_value(range_str: aqi_range_labels, range_value: aqi['data']['iaqi']['pm25']['v'].to_s)
    banner_str = "\x03#{colors[:grey]}#{banner_str}\x03"
  end

  if aqi['data']['iaqi']['co']
    reply += 'co²: ' + aqi['data']['iaqi']['co']['v'].to_s + '  '
  end
  if aqi['data']['iaqi']['h']
    reply += 'humidity: ' + aqi['data']['iaqi']['h']['v'].to_s + '%  '
  end
  # if aqi['data']['iaqi']['p']
  #   reply += 'pressure: ' + aqi['data']['iaqi']['p']['v'].to_s + 'mb  '
  # end
  if aqi['data']['iaqi']['pm25']
    reply += 'pm25: ' + color_str(aqi['data']['iaqi']['pm25']['v'].to_s) + '  '
    ugm3 = pm25_to_ugm3 aqi['data']['iaqi']['pm25']['v']
    reply += "µg/m³(est): #{ugm3}  "
  end
  if aqi['data']['iaqi']['pm10']
    reply += 'pm10: ' + color_str(aqi['data']['iaqi']['pm10']['v'].to_s) + '  '
  end
  if aqi['data']['iaqi']['t']
    reply += 'temp: ' + aqi['data']['iaqi']['t']['v'].to_s + 'C  '
  end

  updated_at = Time.parse aqi['data']['time']['s']
  diff = (Time.now - updated_at).to_i / 60

  reply += "updated #{color_str(diff.to_s)} minutes ago.  #{banner_str}"
  response.reply reply
end

#get_location(response, persist = true) ⇒ Object

Perform a geocoder lookup based on a) the query or b) the user’s serialized state. If neither of those exist, default to config location.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/lita/handlers/onewheel_aqi.rb', line 94

def get_location(response, persist = true)
  user = response.user
  query = nil
  if response.matches[0].is_a?(Array) and !response.matches[0].empty?
    query = response.matches[0][0]
  end

  Lita.logger.debug "Performing geolookup for '#{user.name}' for '#{query}'"

  if query.nil? or query.empty?
    Lita.logger.debug "No query specified, pulling from redis #{REDIS_KEY}, #{user.name}"
    serialized_geocoded = redis.hget(REDIS_KEY, user.name)
    unless serialized_geocoded == 'null' or serialized_geocoded.nil?
      geocoded = JSON.parse(serialized_geocoded)
    end
    Lita.logger.debug "Cached location: #{geocoded.inspect}"
  end

  query = (query.nil?)? 'Portland, OR' : query
  Lita.logger.debug "q & g #{query.inspect} #{geocoded.inspect}"

  unless geocoded
    uri = "https://atlas.p3k.io/api/geocode?input=#{URI.escape query}"
    Lita.logger.debug "Redis hget failed, performing lookup for #{query} on #{uri}"
    # geocoded = optimistic_geo_wrapper query, config.geocoder_key
    geocoded = JSON.parse RestClient.get(uri)
    Lita.logger.debug "Geolocation found.  '#{geocoded.inspect}' failed, performing lookup"
    if persist
      redis.hset(REDIS_KEY, user, geocoded.to_json)
    end
  end

  Lita.logger.debug "geocoded: '#{geocoded}'"
  loc = {
    name: geocoded['best_name'],
    lat: geocoded['latitude'],
    lng: geocoded['longitude']
  }

  Lita.logger.debug "loc: '#{loc}'"

  loc
end

#get_observed_aqi(loc) ⇒ Object



138
139
140
141
142
143
144
145
146
# File 'lib/lita/handlers/onewheel_aqi.rb', line 138

def get_observed_aqi(loc)
  uri = "http://api.waqi.info/feed/geo:#{loc[:lat]};#{loc[:lng]}/?token=#{config.api_key}"
  Lita.logger.debug "Getting aqi from #{uri}"

  observed_response = RestClient.get(uri)
  observed_aqi = JSON.parse(observed_response)
  Lita.logger.debug 'Observed response: ' + observed_aqi.inspect
  observed_aqi
end

#optimistic_geo_wrapper(query) ⇒ Object

Geographical stuffs Now with less caching!



264
265
266
267
268
269
270
# File 'lib/lita/handlers/onewheel_aqi.rb', line 264

def optimistic_geo_wrapper(query)
  geocoded = nil
  result = ::Geocoder.search(query)
  puts result.inspect
  geocoded = result[0].data if result[0]
  geocoded
end

#pm25_to_ugm3(pm25) ⇒ Object

Particulate Matter 2.5 to micrograms per cubic meter



273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
# File 'lib/lita/handlers/onewheel_aqi.rb', line 273

def pm25_to_ugm3(pm25)
  ranges = {
    0..50 => [0, 50, 0.0, 12.0],
    51..100 => [51, 100, 12.1, 35.4],
    101..150 => [101, 150, 35.5, 55.4],
    151..200 => [151, 200, 55.5, 150.4],
    201..300 => [201, 300, 150.5, 250.4],
    301..999 => [301, 999, 250.5, 999]
  }
  ranges.keys.each do |range_key|
    next unless range_key.cover? pm25.to_i
    low = ranges[range_key][0]
    high = ranges[range_key][1]
    min = ranges[range_key][2]
    max = ranges[range_key][3]
    step = (max - min) / (high - low)
    ugm3 = (pm25.to_i - low) * step + min
    return ugm3.round(2)
  end
end