lita-forecast 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +33 -0
- data/.rspec +2 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +10 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +100 -0
- data/Rakefile +13 -0
- data/lib/lita/handlers/forecast/current.rb +65 -0
- data/lib/lita/handlers/forecast/future.rb +65 -0
- data/lib/lita/handlers/forecast/location.rb +31 -0
- data/lib/lita/handlers/forecast/mixins.rb +26 -0
- data/lib/lita/handlers/forecast/persistence.rb +18 -0
- data/lib/lita/handlers/forecast/response.rb +24 -0
- data/lib/lita/handlers/forecast/weather.rb +25 -0
- data/lib/lita/handlers/forecast.rb +57 -0
- data/lib/lita/handlers/forecast_locations.rb +97 -0
- data/lib/lita/handlers/location_search.rb +44 -0
- data/lib/lita-forecast/version.rb +7 -0
- data/lib/lita-forecast.rb +6 -0
- data/lita-forecast.gemspec +34 -0
- data/spec/lita/handlers/forecast/current_spec.rb +264 -0
- data/spec/lita/handlers/forecast/future_spec.rb +260 -0
- data/spec/lita/handlers/forecast/location_spec.rb +116 -0
- data/spec/lita/handlers/forecast/mixins_spec.rb +126 -0
- data/spec/lita/handlers/forecast/persistence_spec.rb +27 -0
- data/spec/lita/handlers/forecast/response_spec.rb +115 -0
- data/spec/lita/handlers/forecast/weather_spec.rb +147 -0
- data/spec/lita/handlers/forecast_locations_spec.rb +296 -0
- data/spec/lita/handlers/forecast_spec.rb +75 -0
- data/spec/lita/handlers/location_search_spec.rb +101 -0
- data/spec/lita_forecast/version_spec.rb +11 -0
- data/spec/spec_helper.rb +12 -0
- metadata +242 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 818e612a4379d01e51b89a449d6c594c93484844
|
4
|
+
data.tar.gz: 4d082b73283ba8bc5618064543d8cfd9a6cb74df
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ffe26f94a9f842179ee7abf1524029fa5e711d6511282c68b113320cf82ad8d57d792633cf470b6394cfb70327f53a3c5dee164b2a16d72b825e56d422ef3480
|
7
|
+
data.tar.gz: be690554ce1e9acdbd1574590cf8693a60aebdbc336624b0ed8a06b3a12bcfe58104e0874daeb470ea94677ffac4943e459f503fbc2b79b6a0588072e5f8b171
|
data/.gitignore
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
coverage
|
6
|
+
InstalledFiles
|
7
|
+
lib/bundler/man
|
8
|
+
pkg
|
9
|
+
rdoc
|
10
|
+
spec/reports
|
11
|
+
test/tmp
|
12
|
+
test/version_tmp
|
13
|
+
tmp
|
14
|
+
Gemfile.lock
|
15
|
+
|
16
|
+
## Documentation cache and generated files:
|
17
|
+
/.yardoc/
|
18
|
+
/_yardoc/
|
19
|
+
/doc/
|
20
|
+
/rdoc/
|
21
|
+
|
22
|
+
## Environment normalisation:
|
23
|
+
/.bundle/
|
24
|
+
/lib/bundler/man/
|
25
|
+
|
26
|
+
# for a library or gem, you might want to ignore these files since the code is
|
27
|
+
# intended to run in multiple environments; otherwise, check them in:
|
28
|
+
# Gemfile.lock
|
29
|
+
# .ruby-version
|
30
|
+
# .ruby-gemset
|
31
|
+
|
32
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
33
|
+
.rvmrc
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Tim Heckman
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
lita-forecast
|
2
|
+
=============
|
3
|
+
[](https://travis-ci.org/theckman/lita-forecast)
|
4
|
+
[](https://tldrlegal.com/license/mit-license)
|
5
|
+
[](https://rubygems.org/gems/lita-forecast)
|
6
|
+
[](https://coveralls.io/r/theckman/lita-forecast)
|
7
|
+
[](https://codeclimate.com/github/theckman/lita-forecast)
|
8
|
+
[](https://gemnasium.com/theckman/lita-forecast)
|
9
|
+
|
10
|
+
Forecast.io plugin for Lita
|
11
|
+
|
12
|
+
LICENSE
|
13
|
+
-------
|
14
|
+
[lita-forecast](https://github.com/theckman/lita-forecast) is released under
|
15
|
+
the [MIT](http://opensource.org/licenses/MIT) license. The full license is
|
16
|
+
provided in the `LICENSE` file.
|
17
|
+
|
18
|
+
CONTRIBUTING
|
19
|
+
------------
|
20
|
+
Something wrong or you want to submit an improvement? Fork the repo, make your
|
21
|
+
changes on a feature branch, write some tests, and submit a pull request. I
|
22
|
+
only ask that the commits have useful information and use proper/complete
|
23
|
+
sentences.
|
24
|
+
|
25
|
+
INSTALLATION
|
26
|
+
------------
|
27
|
+
Simply add `lita-forecast` to the `Gemfile` for your Lita instance.
|
28
|
+
|
29
|
+
```Ruby
|
30
|
+
gem 'lita-forecast'
|
31
|
+
```
|
32
|
+
|
33
|
+
CONFIGURATION
|
34
|
+
-------------
|
35
|
+
There is only one required configuration option for this plugin, and that's
|
36
|
+
your Forecast.io API key
|
37
|
+
[Forecast.io Developer Site](https://developer.forecast.io/register)
|
38
|
+
|
39
|
+
```Ruby
|
40
|
+
config.handlers.forecast.api_key = '<API_KEY>'
|
41
|
+
```
|
42
|
+
|
43
|
+
COMMANDS
|
44
|
+
-----
|
45
|
+
* `wx <alias/location>` - get the weather forecast for a location in US units.
|
46
|
+
* `wc <alias/location>` - get the weather forecast for a location in CA units.
|
47
|
+
* `ws <location>` - returns the lat. and long. for your search string so that
|
48
|
+
you can add a weather alias
|
49
|
+
* `wl` - list known weather aliases
|
50
|
+
* `wadd <alias> <lat> <long> [<description>]` - add an alias to your bot
|
51
|
+
* `wrm alias` - remove an alias added to your bot
|
52
|
+
|
53
|
+
USAGE
|
54
|
+
-----
|
55
|
+
```
|
56
|
+
>> Lita wx San Francisco, CA
|
57
|
+
San Francisco, CA:
|
58
|
+
|
59
|
+
Now: 55.5F (feels like 55.5F) Mostly Cloudy; Winds WSW 8.6mph; Humidity 66%; Dew Pt 44.2F; Pressure 1019.2mb; Cloud cover 82%.
|
60
|
+
Next hour: Mostly cloudy for the hour. Next 24h: Rain throughout the day.
|
61
|
+
|
62
|
+
Summary: Light rain today through Thursday, with temperatures bottoming out at 52°F on Tuesday.
|
63
|
+
Today: Mostly cloudy throughout the day. High 57F, Low 51F. 90% chance of rain. Winds W 7mph.
|
64
|
+
Tomorrow: Rain throughout the day. High 55F, Low 51F. 100% chance of rain. Winds SSW 9mph.
|
65
|
+
|
66
|
+
>> Lita wc San Francisco, CA
|
67
|
+
San Francisco, CA:
|
68
|
+
|
69
|
+
Now: 13.1C (feels like 13.1C) Mostly Cloudy; Winds WSW 12.6kmph; Humidity 65%; Dew Pt 6.7C; Pressure 1019.2mb; Cloud cover 82%.
|
70
|
+
Next hour: Mostly cloudy for the hour. Next 24h: Rain throughout the day.
|
71
|
+
|
72
|
+
Summary: Light rain today through Thursday, with temperatures bottoming out at 11°C on Tuesday.
|
73
|
+
Today: Mostly cloudy throughout the day. High 14C, Low 10C. 90% chance of rain. Winds W 11kmph.
|
74
|
+
Tomorrow: Rain throughout the day. High 13C, Low 10C. 100% chance of rain. Winds SSW 15kmph.
|
75
|
+
|
76
|
+
>> Lita wl
|
77
|
+
There are no weather aliases
|
78
|
+
|
79
|
+
>> Lita ws 501 2nd St, 94107
|
80
|
+
San Francisco, CA: 37.7830503, -122.3933962 :: !wadd <alias> 37.7830503 -122.3933962 <description/city name>
|
81
|
+
|
82
|
+
>> Lita wadd sf 37.7749295 -122.4194155 PagerDuty San Francisco
|
83
|
+
sf added to the cache at [37.7749295, -122.4194155]
|
84
|
+
|
85
|
+
>> Lita wx sf
|
86
|
+
PagerDuty San Francisco:
|
87
|
+
|
88
|
+
Now: 55.6F (feels like 55.6F) Mostly Cloudy; Winds WSW 7.8mph; Humidity 65%; Dew Pt 44.0F; Pressure 1019.2mb; Cloud cover 82%.
|
89
|
+
Next hour: Mostly cloudy for the hour. Next 24h: Rain throughout the day.
|
90
|
+
|
91
|
+
Summary: Light rain today through Thursday, with temperatures bottoming out at 52°F on Tuesday.
|
92
|
+
Today: Mostly cloudy throughout the day. High 57F, Low 51F. 90% chance of rain. Winds W 7mph.
|
93
|
+
Tomorrow: Rain throughout the day. High 55F, Low 51F. 100% chance of rain. Winds SSW 9mph.
|
94
|
+
|
95
|
+
>> Lita wl
|
96
|
+
Known weather aliases: sf
|
97
|
+
|
98
|
+
>> Lita wrm sf
|
99
|
+
Alias removed!
|
100
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- coding: UTF-8 -*_
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'rubocop/rake_task'
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec)
|
6
|
+
|
7
|
+
Rubocop::RakeTask.new(:rubocop) do |t|
|
8
|
+
t.patterns =
|
9
|
+
%w( Rakefile Gemfile lita-forecast.gemspec lib/**/*.rb spec/*_spec.rb )
|
10
|
+
t.fail_on_error = true
|
11
|
+
end
|
12
|
+
|
13
|
+
task default: [:rubocop, :spec]
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'lita/handlers/forecast/mixins'
|
3
|
+
|
4
|
+
module LitaForecast
|
5
|
+
# LitaForecast::Current
|
6
|
+
#
|
7
|
+
class Current
|
8
|
+
include LitaForecast::Mixins
|
9
|
+
|
10
|
+
def initialize(forecast)
|
11
|
+
@f = forecast
|
12
|
+
end
|
13
|
+
|
14
|
+
def conditions
|
15
|
+
c = currently
|
16
|
+
"#{temp} (feels like #{feels}) #{c['summary']}; Winds #{wind}; " \
|
17
|
+
"Humidity #{humidity}; Dew Pt #{dew_pt}; Pressure #{pressure}; Cloud " \
|
18
|
+
"cover #{clouds}.\n" \
|
19
|
+
"Next hour: #{next_hour} Next 24h: #{today}"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def currently
|
25
|
+
@f['currently']
|
26
|
+
end
|
27
|
+
|
28
|
+
def temp
|
29
|
+
"#{currently['temperature'].round(1)}#{units(@f)[:t]}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def feels
|
33
|
+
"#{currently['apparentTemperature'].round(1)}#{units(@f)[:t]}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def wind
|
37
|
+
direction = Compass::Rose.direction(currently['windBearing'], 16)[:abbr]
|
38
|
+
"#{direction} #{currently['windSpeed'].round(1)}#{units(@f)[:w]}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def humidity
|
42
|
+
"#{(currently['humidity'] * 100).round(0)}%"
|
43
|
+
end
|
44
|
+
|
45
|
+
def dew_pt
|
46
|
+
"#{currently['dewPoint'].round(1)}#{units(@f)[:t]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def pressure
|
50
|
+
"#{currently['pressure'].round(1)}mb"
|
51
|
+
end
|
52
|
+
|
53
|
+
def clouds
|
54
|
+
"#{(currently['cloudCover'] * 100).round(0)}%"
|
55
|
+
end
|
56
|
+
|
57
|
+
def next_hour
|
58
|
+
@f['minutely']['summary']
|
59
|
+
end
|
60
|
+
|
61
|
+
def today
|
62
|
+
@f['hourly']['summary']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'English'
|
3
|
+
require 'compass_rose'
|
4
|
+
require 'lita/handlers/forecast/mixins'
|
5
|
+
|
6
|
+
module LitaForecast
|
7
|
+
# LitaForecast::Future
|
8
|
+
#
|
9
|
+
class Future
|
10
|
+
include LitaForecast::Mixins
|
11
|
+
|
12
|
+
def method_missing(method, *args, &block)
|
13
|
+
super unless /^generate_(.*)$/.match(method)
|
14
|
+
m = $LAST_MATCH_INFO
|
15
|
+
super unless %w(today tomorrow).include?(m[1])
|
16
|
+
i = { today: 0, tomorrow: 1 }[m[1].to_sym]
|
17
|
+
generate_day(i, m[1])
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(forecast)
|
21
|
+
@f = forecast
|
22
|
+
end
|
23
|
+
|
24
|
+
def conditions
|
25
|
+
future = generate_summary
|
26
|
+
future << generate_today
|
27
|
+
future << generate_tomorrow
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def daily
|
33
|
+
@f['daily']['data']
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_summary
|
37
|
+
"Summary: #{@f['daily']['summary']}\n"
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_day(index, day)
|
41
|
+
@i = daily[index]
|
42
|
+
@d = day
|
43
|
+
"#{summary} #{high_low} #{precip} #{wind}\n"
|
44
|
+
end
|
45
|
+
|
46
|
+
def summary
|
47
|
+
"#{@d.capitalize}: #{@i['summary']}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def high_low
|
51
|
+
"High #{@i['temperatureMax'].round(0)}#{units(@f)[:t]}, " \
|
52
|
+
"Low #{@i['temperatureMin'].round(0)}#{units(@f)[:t]}."
|
53
|
+
end
|
54
|
+
|
55
|
+
def precip
|
56
|
+
type = @i['precipType'] || 'precipitation'
|
57
|
+
"#{(@i['precipProbability'] * 100).round(0)}% chance of #{type}."
|
58
|
+
end
|
59
|
+
|
60
|
+
def wind
|
61
|
+
direction = Compass::Rose.direction(@i['windBearing'], 16)[:abbr]
|
62
|
+
"Winds #{direction} #{@i['windSpeed'].round(0)}#{units(@f)[:w]}."
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'geocoder'
|
3
|
+
require 'lita/handlers/forecast/mixins'
|
4
|
+
|
5
|
+
module LitaForecast
|
6
|
+
# LitaForecast class for determining someone's location
|
7
|
+
#
|
8
|
+
class Location
|
9
|
+
include LitaForecast::Mixins
|
10
|
+
|
11
|
+
attr_accessor :lita_redis
|
12
|
+
|
13
|
+
def initialize(redis)
|
14
|
+
@lita_redis = redis
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_location(search)
|
18
|
+
loc = lita_redis.hgetall("alias:#{search}").symbolize_keys!
|
19
|
+
|
20
|
+
if loc.empty?
|
21
|
+
g = Geocoder.search(search)[0].data
|
22
|
+
gl = geo_location(g)
|
23
|
+
loc = { lat: g['geometry']['location']['lat'],
|
24
|
+
lng: g['geometry']['location']['lng'],
|
25
|
+
desc: "#{gl[:city]}, #{gl[:state]}" }
|
26
|
+
end
|
27
|
+
|
28
|
+
loc
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
module LitaForecast
|
4
|
+
# The random mixins I'll need, eventually
|
5
|
+
#
|
6
|
+
module Mixins
|
7
|
+
def geo_location(result)
|
8
|
+
h = {}
|
9
|
+
result['address_components'].each do |a|
|
10
|
+
a['types'].each do |t|
|
11
|
+
h[:city] = a['long_name'] if t == 'locality'
|
12
|
+
h[:state] = a['short_name'] if t == 'administrative_area_level_1'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
h
|
16
|
+
end
|
17
|
+
|
18
|
+
def units(forecast)
|
19
|
+
if forecast['flags']['units'] == 'us'
|
20
|
+
{ t: 'F', w: 'mph', v: 'mi' }
|
21
|
+
else
|
22
|
+
{ t: 'C', w: 'kmph', v: 'km' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'lita'
|
3
|
+
require 'redis-namespace'
|
4
|
+
|
5
|
+
# LitaForecast module
|
6
|
+
#
|
7
|
+
module LitaForecast
|
8
|
+
FORECAST_NAMESPACE = 'handlers:forecast'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def redis
|
12
|
+
@forecastredis ||= begin
|
13
|
+
Redis::Namespace.new(FORECAST_NAMESPACE, redis: Lita.redis)
|
14
|
+
end
|
15
|
+
@forecastredis
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'compass_rose'
|
3
|
+
require 'lita/handlers/forecast/current'
|
4
|
+
require 'lita/handlers/forecast/future'
|
5
|
+
|
6
|
+
module LitaForecast
|
7
|
+
# LutaForecast::Response
|
8
|
+
#
|
9
|
+
class Response
|
10
|
+
def initialize(forecast, location)
|
11
|
+
@forecast = forecast
|
12
|
+
@location = location
|
13
|
+
@current = LitaForecast::Current.new(@forecast)
|
14
|
+
@future = LitaForecast::Future.new(@forecast)
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate
|
18
|
+
response = "#{@location}:\n\n"
|
19
|
+
response << "Now: #{@current.conditions}\n\n"
|
20
|
+
response << @future.conditions
|
21
|
+
response
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'forecast_io'
|
3
|
+
require 'lita/handlers/forecast/location'
|
4
|
+
require 'lita/handlers/forecast/response'
|
5
|
+
|
6
|
+
# The thing
|
7
|
+
#
|
8
|
+
module LitaForecast
|
9
|
+
# Module
|
10
|
+
#
|
11
|
+
module Weather
|
12
|
+
def weather_forecast(api_key, l = {})
|
13
|
+
ForecastIO.api_key = api_key
|
14
|
+
l = { params: { exclude: 'alerts' } }.merge(l)
|
15
|
+
ForecastIO.forecast(l[:lat].to_f, l[:lng].to_f, params: l[:params])
|
16
|
+
end
|
17
|
+
|
18
|
+
def weather(response, api_key, units = 'us')
|
19
|
+
location = LitaForecast::Location.new(LitaForecast.redis)
|
20
|
+
.find_location(response.args.join(' '))
|
21
|
+
f = weather_forecast(api_key, location.merge(params: { units: units }))
|
22
|
+
LitaForecast::Response.new(f, location[:desc]).generate
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'lita/handlers/forecast/mixins'
|
3
|
+
require 'lita/handlers/forecast/weather'
|
4
|
+
|
5
|
+
module Lita
|
6
|
+
module Handlers
|
7
|
+
# Lita Forecast.io plugin!
|
8
|
+
# this provides handlers for US and Canadian units
|
9
|
+
#
|
10
|
+
class Forecast < Handler
|
11
|
+
include LitaForecast::Mixins
|
12
|
+
include LitaForecast::Weather
|
13
|
+
|
14
|
+
def self.default_config(config)
|
15
|
+
config.api_key = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
route(
|
19
|
+
/^wx\s(.*)$/,
|
20
|
+
:weather_us,
|
21
|
+
command: true,
|
22
|
+
help: {
|
23
|
+
'wx san francisco' => 'Get the weather for San Francisco'
|
24
|
+
}
|
25
|
+
)
|
26
|
+
|
27
|
+
route(
|
28
|
+
/^wc\s(.*)$/,
|
29
|
+
:weather_ca,
|
30
|
+
command: true,
|
31
|
+
help: {
|
32
|
+
'wc toronto' => 'You want the weather for Toronto, eh?'
|
33
|
+
}
|
34
|
+
)
|
35
|
+
|
36
|
+
def weather_us(response)
|
37
|
+
response.reply(build_weather('us', response))
|
38
|
+
end
|
39
|
+
|
40
|
+
def weather_ca(response)
|
41
|
+
response.reply(build_weather('ca', response))
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_weather(units, response)
|
45
|
+
weather(response, api_key, units)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def api_key
|
51
|
+
Lita.config.handlers.forecast.api_key
|
52
|
+
end
|
53
|
+
|
54
|
+
Lita.register_handler(Forecast)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'lita/handlers/forecast/persistence'
|
3
|
+
|
4
|
+
module Lita
|
5
|
+
module Handlers
|
6
|
+
# Lita::Handlers::ForecastLocations
|
7
|
+
#
|
8
|
+
class ForecastLocations < Handler
|
9
|
+
route(
|
10
|
+
/^wadd\s(.+?)\s([0-9.,\-]+?)\s([0-9.,\-]+)\s*(.*)$/,
|
11
|
+
:location_add,
|
12
|
+
command: true,
|
13
|
+
help: {
|
14
|
+
'wadd sf 37.78439928029 -122.39204721970 PagerDuty San Francisco' =>
|
15
|
+
'Add the lat and long of the office with the alias "sf"'
|
16
|
+
}
|
17
|
+
)
|
18
|
+
|
19
|
+
route(
|
20
|
+
/^wrm\s(.+?)$/,
|
21
|
+
:location_rm,
|
22
|
+
command: true,
|
23
|
+
help: {
|
24
|
+
'wrm sf' =>
|
25
|
+
'Remove the specified alias, in this case "sf"'
|
26
|
+
}
|
27
|
+
)
|
28
|
+
|
29
|
+
route(
|
30
|
+
/^wl$/,
|
31
|
+
:locations,
|
32
|
+
command: true,
|
33
|
+
help: {
|
34
|
+
'wl' => 'List known weather aliases'
|
35
|
+
}
|
36
|
+
)
|
37
|
+
|
38
|
+
def self.default_config(config)
|
39
|
+
config.api_key = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def location_add(response)
|
43
|
+
r = response.matches[0]
|
44
|
+
return response.reply('Already there!') if alias_exists?(r[0])
|
45
|
+
|
46
|
+
d = saved_location_hash(r)
|
47
|
+
add_to_cache(d)
|
48
|
+
|
49
|
+
response.reply("#{r[0]} added to the cache at [#{r[1]}, #{r[2]}]")
|
50
|
+
end
|
51
|
+
|
52
|
+
def location_rm(response)
|
53
|
+
key = "alias:#{response.matches[0][0]}"
|
54
|
+
return response.reply('Alias not found') unless alias_exists?(key)
|
55
|
+
rm_from_cache(key)
|
56
|
+
if LitaForecast.redis.keys(key).empty?
|
57
|
+
return response.reply('Alias removed!')
|
58
|
+
else
|
59
|
+
return response.reply('Somehow that failed... I need an adult!')
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def locations(response)
|
64
|
+
k = LitaForecast.redis.keys('alias:*').map { |v| v.gsub('alias:', '') }
|
65
|
+
return response.reply('There are no weather aliases') if k.empty?
|
66
|
+
response.reply("Known weather aliases: #{k.join(', ')}")
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def alias_exists?(key)
|
72
|
+
return true unless LitaForecast.redis.hgetall(key).empty?
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
def add_to_cache(location)
|
77
|
+
key = "alias:#{location[:name]}"
|
78
|
+
LitaForecast.redis.pipelined do
|
79
|
+
[:lat, :lng, :desc].each do |k|
|
80
|
+
LitaForecast.redis.hset(key, k.to_s, location[k])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def rm_from_cache(key)
|
86
|
+
LitaForecast.redis.del(key)
|
87
|
+
end
|
88
|
+
|
89
|
+
def saved_location_hash(r)
|
90
|
+
d = (r[3].nil? || r[3].empty?) ? r[0] : r[3].slice(0..29)
|
91
|
+
{ name: r[0], lat: r[1], lng: r[2], desc: d }
|
92
|
+
end
|
93
|
+
|
94
|
+
Lita.register_handler(ForecastLocations)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
require 'geocoder'
|
3
|
+
require 'lita/handlers/forecast/mixins'
|
4
|
+
|
5
|
+
module Lita
|
6
|
+
module Handlers
|
7
|
+
# Lita::Handlers::LocationSearch
|
8
|
+
#
|
9
|
+
class LocationSearch < Handler
|
10
|
+
include LitaForecast::Mixins
|
11
|
+
|
12
|
+
route(
|
13
|
+
/^ws\s(.*)$/,
|
14
|
+
:search,
|
15
|
+
command: true,
|
16
|
+
help: { 'ws san francisco' =>
|
17
|
+
'find the lat and long for the location' }
|
18
|
+
)
|
19
|
+
|
20
|
+
def search(response)
|
21
|
+
s = response.args.join(' ')
|
22
|
+
r = search_geocoder(s)
|
23
|
+
return response.reply('You made that up...') if r.empty?
|
24
|
+
response.reply(generate_response(r))
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def search_geocoder(search)
|
30
|
+
Geocoder.search(search)[0].data
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_response(result)
|
34
|
+
l = geo_location(result)
|
35
|
+
lat = result['geometry']['location']['lat']
|
36
|
+
lng = result['geometry']['location']['lng']
|
37
|
+
"#{l[:city]}, #{l[:state]}: #{lat}, #{lng} :: "\
|
38
|
+
"!wadd <alias> #{lat} #{lng} <description/city name>"
|
39
|
+
end
|
40
|
+
|
41
|
+
Lita.register_handler(LocationSearch)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|