lita-meetup-finder 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a19e4f4c790665cd9c45ee2233390c10f09c17f627bd8d912bc736342bccaccc
4
- data.tar.gz: 7c22995bf6bfd9b5891210858f7296d1bfbf66bec6e0466933748edf99430925
3
+ metadata.gz: 8a06ecdb93d4ff7cdd441333156abfc7c525b4521c07e005f26a87b88e77da4e
4
+ data.tar.gz: fe59db060aae6890560c1f462e7c0f791ade7039f30a3cd52d7aedbcb4d3aeac
5
5
  SHA512:
6
- metadata.gz: d1b3039d36a33673cb4e16f0307af3a6510774625fca7ef634d34f8ea0caf2e44aa95097e0a2f59c7e1cf0c45384ff85f1a4e8af302294d7720ec483205f63eb
7
- data.tar.gz: 8034ac0995f3fe16248a3f3c0b2c041f0dc6236f9e5fafe072637cceb44cd30e61b2ce38cc3b2b9ce98efa87d204f175bdf07c81fb6cad9cd70d568d89b05105
6
+ metadata.gz: 5345eb9b2bca45a974e076c9c25d6568791e2e32d503bf51a75b0e94de557a648c425ebed1f40304d342acb6ea81ce3521936acdf3ac36e258d8bde0a6064cd3
7
+ data.tar.gz: 902f34591d30b83832cc87bf5558fc2df98c8784f9d3c224d50c24dfcf5cfb94ea65c9b9745b0a0e36b4ed4b7584405178686cdda8749a631db4f5cbb73db75b
@@ -0,0 +1,6 @@
1
+ $ env MEETUP_API_KEY='14ae7022223d49b6e5e673d3e29' MEETUP_ZIP='38117' lita
2
+ Type "exit" or "quit" to end the session.
3
+ Lita > lita find meetup python
4
+ Memphis Python User Group >> Group: Memphis Technology User Groups
5
+ >> Mon Nov 19 18:30:00 2018
6
+ >> https://www.meetup.com/memphis-technology-user-groups/events/255343667/
@@ -0,0 +1,83 @@
1
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master →) git commit -m "Initial handler code"
2
+ [master (root-commit) 228d789] Initial handler code
3
+ 11 files changed, 105 insertions(+)
4
+ create mode 100644 .gitignore
5
+ create mode 100644 Gemfile
6
+ create mode 100644 README.md
7
+ create mode 100644 Rakefile
8
+ create mode 100644 lib/lita-meetup-finder.rb
9
+ create mode 100644 lib/lita/handlers/meetup_finder.rb
10
+ create mode 100644 lita-meetup-finder.gemspec
11
+ create mode 100644 locales/en.yml
12
+ create mode 100644 spec/lita/handlers/meetup_finder_spec.rb
13
+ create mode 100644 spec/spec_helper.rb
14
+ create mode 100644 templates/.gitkeep
15
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master) rake release
16
+ lita-meetup-finder 0.1.0 built to pkg/lita-meetup-finder-0.1.0.gem.
17
+ Tagged v0.1.0.
18
+ Untagging v0.1.0 due to error.
19
+ rake aborted!
20
+ Couldn't git push. `git push ' failed with the following output:
21
+
22
+ fatal: No configured push destination.
23
+ Either specify the URL from the command-line or configure a remote repository using
24
+
25
+ git remote add <name> <url>
26
+
27
+ and then push using the remote name
28
+
29
+ git push <name>
30
+
31
+
32
+
33
+ Tasks: TOP => release => release:source_control_push
34
+ (See full trace by running task with --trace)
35
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master)
36
+ git remote add origin git@github.com:dpritchett/lita-meetup-finder.git
37
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master) git push -u origin master
38
+ Counting objects: 21, done.
39
+ Delta compression using up to 4 threads.
40
+ Compressing objects: 100% (12/12), done.
41
+ Writing objects: 100% (21/21), 2.46 KiB | 252.00 KiB/s, done.
42
+ Total 21 (delta 0), reused 0 (delta 0)
43
+ remote:
44
+ remote: Create a pull request for 'master' on GitHub by visiting:
45
+ remote: https://github.com/dpritchett/lita-meetup-finder/pull/new/master
46
+ remote:
47
+ To github.com:dpritchett/lita-meetup-finder.git
48
+ * [new branch] master -> master
49
+ Branch 'master' set up to track remote branch 'master' from 'origin'.
50
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=) rake release
51
+ lita-meetup-finder 0.1.0 built to pkg/lita-meetup-finder-0.1.0.gem.
52
+ Tagged v0.1.0.
53
+ Pushed git commits and tags.
54
+ rake aborted!
55
+ Your rubygems.org credentials aren't set. Run `gem push` to set them.
56
+
57
+ Tasks: TOP => release => release:rubygem_push
58
+ (See full trace by running task with --trace)
59
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=) gem push
60
+ Enter your RubyGems.org credentials.
61
+ Don't have an account yet? Create one at https://rubygems.org/sign_up
62
+ Email: dpritchett@gmail.com
63
+ Password:
64
+
65
+ HTTP Basic: Access denied.
66
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=) gem push
67
+ Enter your RubyGems.org credentials.
68
+ Don't have an account yet? Create one at https://rubygems.org/sign_up
69
+ Email: dpritchett@gmail.com
70
+ Password:
71
+
72
+ Signed in.
73
+ ERROR: While executing gem ... (Gem::CommandLineError)
74
+ Please specify a gem name on the command line (e.g. gem build GEMNAME)
75
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=) gem login
76
+ ERROR: While executing gem ... (Gem::CommandLineError)
77
+ Unknown command login
78
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=) rake release
79
+ lita-meetup-finder 0.1.0 built to pkg/lita-meetup-finder-0.1.0.gem.
80
+ Tag v0.1.0 has already been created.
81
+ Pushed lita-meetup-finder 0.1.0 to rubygems.org
82
+ /m/w/U/d/D/d/B/c/lita-meetup-finder (master=)
83
+
@@ -5,6 +5,7 @@ Lita.load_locales Dir[File.expand_path(
5
5
  )]
6
6
 
7
7
  require "lita/handlers/meetup_finder"
8
+ require "lita/meetup_result"
8
9
 
9
10
  Lita::Handlers::MeetupFinder.template_root File.expand_path(
10
11
  File.join("..", "..", "templates"),
@@ -1,9 +1,86 @@
1
+ # START:require
2
+ # Load 3rd party meetup API client gem
3
+ require 'meetup_client'
4
+ # END:require
5
+
1
6
  module Lita
2
7
  module Handlers
3
8
  class MeetupFinder < Handler
4
- # insert handler code here
9
+ # START:custom_error
10
+ MeetupApiError = Class.new(StandardError)
11
+ # END:custom_error
12
+
13
+ # START:config
14
+ # Set these in your bot's lita_config.rb or via environment
15
+ # variable
16
+ config :meetup_api_key, default: ENV['MEETUP_API_KEY']
17
+ # note the
18
+ config :meetup_zip, default: ENV['MEETUP_ZIP']
19
+ # END:config
20
+
21
+ # START:route
22
+ route(/^find meetup\s+(.+)$/i, :find_matching_meetup, command: true)
23
+ # END:route
24
+
25
+ # START:handle_user_input
26
+ def find_matching_meetup(message)
27
+ # extract search term from user input
28
+ search_term = message.matches.first
29
+ # pass search term to meetup query method
30
+ meetups = meetups_matching search_term
31
+
32
+ # handle two basic outcomes: no results, 1+ results
33
+ if meetups.none?
34
+ message.reply "Sorry, no matching meetups found."
35
+ else
36
+ message.reply meetups.first&.tagline
37
+ end
38
+ end
39
+ # END:handle_user_input
40
+
41
+ # START:build_api_client
42
+ def client
43
+ MeetupClient.configure do |meetup_config|
44
+ # sets meetup config using value from lita config
45
+ meetup_config.api_key = config.meetup_api_key
46
+ end
47
+
48
+ # store client rather than rebuilding on each call
49
+ @_client ||= MeetupApi.new
50
+ end
51
+ # END:build_api_client
52
+
53
+ # START:perform_lookup
54
+ # query Meetup API for local meetups and return a
55
+ # list of matching MeetupResult objects
56
+ def meetups_matching(search_text)
57
+ query = build_search(search_text)
58
+
59
+ begin
60
+ response = client.open_events(query)
61
+ results = response.fetch('results')
62
+ rescue StandardError
63
+ raise MeetupApiError.new(response)
64
+ end
65
+
66
+ # coerce an array of JSON-ish results into richer
67
+ # MeetupResult objects
68
+ results.map { |r| MeetupResult.new(r) }
69
+ end
70
+ # END:perform_lookup
71
+
72
+ # START:build_search
73
+ def build_search(search_text)
74
+ {
75
+ zip: config.meetup_zip,
76
+ format: 'json',
77
+ page: '5',
78
+ text: search_text
79
+ }
80
+ end
81
+ # END:build_search
5
82
 
6
83
  Lita.register_handler(self)
7
84
  end
8
85
  end
9
- end
86
+ end
@@ -0,0 +1,37 @@
1
+ module Lita
2
+ class MeetupResult
3
+ # START:init
4
+ def initialize(raw_result)
5
+ @raw_result = raw_result
6
+
7
+ @name = raw_result.fetch('name')
8
+ @url = raw_result.fetch('event_url')
9
+ @group_name = raw_result.fetch('group').fetch('name')
10
+ end
11
+ # END:init
12
+
13
+ # START:attrs
14
+ # expose instance variables as attribute getters
15
+ attr_reader :raw_result, :name, :url, :group_name
16
+ # END:attrs
17
+
18
+ # START:start_time
19
+ # Human readable start time for the event
20
+ # Raw time: 1541941200000
21
+ # Human time: Sun Nov 11 07:00:00 2018
22
+ def start_time
23
+ # API results are in milliseconds since the unix epoch
24
+ epoch_msec = raw_result.fetch('time')
25
+ epoch_sec = epoch_msec / 1000
26
+
27
+ Time.at(epoch_sec).ctime
28
+ end
29
+ # END:start_time
30
+
31
+ # START:tagline
32
+ def tagline
33
+ "#{name} >> Group: #{group_name} >> #{start_time} >> #{url}"
34
+ end
35
+ # END:tagline
36
+ end
37
+ end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-meetup-finder"
3
- spec.version = "0.1.0"
3
+ spec.version = "1.0.0"
4
4
  spec.authors = ["Daniel J. Pritchett"]
5
5
  spec.email = ["dpritchett@gmail.com"]
6
6
  spec.description = "Ask your Lita chatbot to find relevant meetups in your area"
@@ -15,11 +15,16 @@ Gem::Specification.new do |spec|
15
15
  spec.require_paths = ["lib"]
16
16
 
17
17
  spec.add_runtime_dependency "lita", ">= 4.7"
18
+ # START:client
18
19
  spec.add_runtime_dependency 'meetup_client', '~> 1.0'
20
+ # END:client
19
21
 
20
22
  spec.add_development_dependency "bundler", "~> 1.3"
21
23
  spec.add_development_dependency "pry-byebug"
22
24
  spec.add_development_dependency "rake"
23
25
  spec.add_development_dependency "rack-test"
24
26
  spec.add_development_dependency "rspec", ">= 3.0.0"
27
+ # START:webmock
28
+ spec.add_development_dependency 'webmock', '~> 3.3'
29
+ # END:webmock
25
30
  end
@@ -0,0 +1 @@
1
+ {"results":[{"utc_offset":-21600000,"venue":{"zip":"38104","country":"us","localized_country_name":"USA","city":"Memphis","address_1":"2164 Young Ave","name":"Grivet Outdoors","lon":-89.990074,"id":25963887,"state":"tn","lat":35.119804,"repinned":true},"headcount":0,"distance":5.100682735443115,"visibility":"public","waitlist_count":0,"created":1539897150000,"fee":{"amount":50,"currency":"USD","label":"Price","accepts":"wepay","required":"1"},"maybe_rsvp_count":0,"description":"<p>This is a super convenient opportunity to explore an area you may not have been out to yet! Pinnacle Mountain is located about 2.5 hours from Memphis right outside of Little Rock, Arkansas. Grivet rents a van and provides all transportation. All you have to do is hop on the van and we take care of the rest!</p> <p>We’ll be doing the Base Trail and hitting the peak by going up the West Summit Trail and coming back down the East Summit Trail. Although it is only about 0.75 miles each way, you are climbing about 750 feet very quickly, up and over several boulder fields. You should expect to use your hands and knees for stability and to pull yourself up on some rocks. We’ll also aim to cover the Rocky Valley Trail and the East Quarry Trail – bringing our total mileage for the day to around 6 miles. Although this sounds short, remember how steep some of it is, so I’m rating this hike as moderate-strenuous difficulty. I want to stress how physical those boulder fields are to get up and over! It is a lot of fun and something different to challenge even experienced hikers. We’ll be meeting at the store at 7:00 AM for coffee and tasty breakfast treats, hiking from 10:00 - 4:00 and returning home around 6:30 PM. Please RSVP for this day trip if you’d like to join us.</p> <p>There are only a few spots on the van left. Please contact [masked] for more information or to lock up your spot.</p>","event_url":"https://www.meetup.com/MemphisOutdoors/events/255648544/","yes_rsvp_count":3,"duration":43200000,"name":"Grivet Outdoors: Hiking Trip to Pinnacle Mountain ","id":"255648544","time":1541941200000,"updated":1540832649000,"group":{"join_mode":"open","created":1210106868000,"name":"Memphis Outdoor Adventures","group_lon":-89.94999694824219,"id":1138444,"urlname":"MemphisOutdoors","group_lat":35.11000061035156,"who":"Adventurers"},"status":"upcoming"},{"utc_offset":-21600000,"venue":{"zip":"38104","country":"us","localized_country_name":"USA","city":"Memphis","address_1":"2164 Young Ave","name":"Grivet Outdoors","lon":-89.990074,"id":25963887,"state":"tn","lat":35.119804,"repinned":true},"headcount":0,"distance":5.100682735443115,"visibility":"public","waitlist_count":0,"created":1539897057000,"maybe_rsvp_count":0,"description":"<p>This is a super convenient opportunity to explore an area you may not have been out to yet! Pinnacle Mountain is located about 2.3 hours from Memphis right outside of Little Rock, Arkansas. Grivet rents a van and provides all transportation. All you have to do is hop on the van and we take care of the rest!</p> <p>We’ll be doing the Base Trail and hitting the peak by going up the West Summit Trail and coming back down the East Summit Trail. Although it is only about 0.75 miles each way, you are climbing about 750 feet very quickly, up and over several boulder fields. You should expect to use your hands and knees for stability and to pull yourself up on some rocks. We’ll also aim to cover the Rocky Valley Trail and the East Quarry Trail – bringing our total mileage for the day to around 6 miles. Although this sounds short, remember how steep some of it is, so I’m rating this hike as moderate-strenuous difficulty. I want to stress how physical those boulder fields are to get up and over! It is a lot of fun and something different to challenge even experienced hikers. We’ll be meeting at the store at 7:00 AM for coffee and tasty breakfast treats, hiking from 10:00 - 4:00 and returning home around 6:30 PM. Please RSVP for this day trip if you’d like to join us.</p> <p>The cost for this hike is $49.95 and there are only a few spots on the van left. Please contact [masked] for more information or to lock up your spot.</p>","event_url":"https://www.meetup.com/MemphisOutdoors/events/255648524/","yes_rsvp_count":3,"duration":43200000,"name":"Grivet Outdoors: Hiking Trip to Pinnacle Mountain ","id":"255648524","time":1541941200000,"updated":1540264031000,"group":{"join_mode":"open","created":1210106868000,"name":"Memphis Outdoor Adventures","group_lon":-89.94999694824219,"id":1138444,"urlname":"MemphisOutdoors","group_lat":35.11000061035156,"who":"Adventurers"},"status":"upcoming"}]}
@@ -1,4 +1,63 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
+ require 'pry'
2
3
 
3
4
  describe Lita::Handlers::MeetupFinder, lita_handler: true do
5
+ subject { described_class.new(robot) }
6
+
7
+ let(:test_api_key) { nil } ##'14ae7022223d49b6e5e673d3e29' }
8
+ let(:test_zip) { 38117 }
9
+
10
+ # Ask webmock to intercept any HTTP traffic to meetup API
11
+ # and respond with stored data instead of live data
12
+ before { stub_meetup_calls! }
13
+
14
+ # force config values to things you can test against
15
+ before(:each) do
16
+ # you'll need your own test API key here
17
+ subject.config.meetup_api_key = test_api_key
18
+ subject.config.meetup_zip = test_zip
19
+ end
20
+
21
+ describe 'routes' do
22
+ # confirm three variations on what's brad eating each trigger a response
23
+ it { is_expected.to route("Lita find meetup climbing") }
24
+ it { is_expected.to_not route("Lita what’s for dinner?") }
25
+ end
26
+
27
+ describe ':build_search' do
28
+ let(:search_text) { 'climbers'}
29
+ let(:result) { subject.build_search search_text }
30
+
31
+ it "should return an array of Meetup search parameters" do
32
+ expected = {
33
+ zip: test_zip,
34
+ format: 'json',
35
+ page: '5',
36
+ text: search_text
37
+ }
38
+
39
+ expect(result).to eq expected
40
+ end
41
+ end
42
+
43
+ # START:response
44
+ # validate your basic HTML content fetching methods
45
+ describe ':meetup_search' do
46
+ let(:climbers) { subject.meetups_matching 'climbers' }
47
+
48
+ it "should find two results" do
49
+ expect(climbers.count).to eq(2)
50
+ end
51
+ end
52
+ # END:response
53
+
54
+ # START:meetup_find
55
+ # high-level "lita hears X and returns Y" end-to-end testing
56
+ describe ':meetup_find' do
57
+ it 'responds with a list of relevant meetups' do
58
+ send_message "Lita find meetup climbing"
59
+ expect(replies.last).to match(/\w+ >> http/i)
60
+ end
61
+ end
62
+ # END:meetup_find
4
63
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ require 'json'
3
+ require 'pry'
4
+
5
+ describe Lita::MeetupResult do
6
+ let(:raw_results) { JSON.load(json_fixture).fetch('results') }
7
+
8
+ it "has a fixture with 2 results" do
9
+ expect(raw_results.count).to eq 2
10
+ end
11
+
12
+ context "Result parsing" do
13
+ let(:parsed_results) { raw_results.map { |el| described_class.new el } }
14
+
15
+ it "can parse the fixture's JSON input as MeetupResult objects" do
16
+ expect(parsed_results.map(&:class).uniq).to eq [described_class]
17
+ end
18
+
19
+ context "accessor methods" do
20
+ let(:result) { parsed_results.first }
21
+
22
+ it 'parses group name' do
23
+ expect(result.group_name).to eq "Memphis Outdoor Adventures"
24
+ end
25
+
26
+ it 'parses event name' do
27
+ expect(result.name).to include 'Pinnacle Mountain'
28
+ end
29
+
30
+ it 'parses start time' do
31
+ expect(result.start_time).to include 'Sun Nov 11'
32
+ end
33
+
34
+ it 'parses url' do
35
+ expect(result.url.start_with? 'https://www.meetup.com/').to be_truthy
36
+ end
37
+
38
+ context 'human-friendly formatting' do
39
+ let(:tagline) { result.tagline }
40
+ fields = [:group_name, :name, :start_time, :url]
41
+
42
+ fields.each do |field|
43
+ it "tagline includes #{field}" do
44
+ expected = result.send(field)
45
+ expect(tagline.include? expected).to be_truthy
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -4,3 +4,23 @@ require "lita/rspec"
4
4
  # A compatibility mode is provided for older plugins upgrading from Lita 3. Since this plugin
5
5
  # was generated with Lita 4, the compatibility mode should be left disabled.
6
6
  Lita.version_3_compatibility_mode = false
7
+
8
+ require 'webmock/rspec'
9
+
10
+ # call me in a before block anywhere you're calling pastebin!
11
+ # This will save you from fairly low-overhead API limits.
12
+ def stub_meetup_calls!
13
+ stub_request(:get, /api.meetup.com/).
14
+ with(
15
+ headers: {
16
+ 'Accept'=>'*/*',
17
+ 'Accept-Charset'=>'UTF-8',
18
+ 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
19
+ 'User-Agent'=>'Ruby'
20
+ }).
21
+ to_return(status: 200, body: json_fixture, headers: {})
22
+ end
23
+
24
+ def json_fixture
25
+ @_raw_json ||= open('./spec/fixtures/meetup_results.json')
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-meetup-finder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Pritchett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-04 00:00:00.000000000 Z
11
+ date: 2018-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: 3.0.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.3'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.3'
111
125
  description: Ask your Lita chatbot to find relevant meetups in your area
112
126
  email:
113
127
  - dpritchett@gmail.com
@@ -119,11 +133,16 @@ files:
119
133
  - Gemfile
120
134
  - README.md
121
135
  - Rakefile
136
+ - examples/001-runtime-env-var.sh
137
+ - examples/999-push-gem.session
122
138
  - lib/lita-meetup-finder.rb
123
139
  - lib/lita/handlers/meetup_finder.rb
140
+ - lib/lita/meetup_result.rb
124
141
  - lita-meetup-finder.gemspec
125
142
  - locales/en.yml
143
+ - spec/fixtures/meetup_results.json
126
144
  - spec/lita/handlers/meetup_finder_spec.rb
145
+ - spec/lita/meetup_result_spec.rb
127
146
  - spec/spec_helper.rb
128
147
  - templates/.gitkeep
129
148
  homepage: https://github.com/dpritchett/lita-meetup-finder
@@ -152,5 +171,7 @@ signing_key:
152
171
  specification_version: 4
153
172
  summary: Help Lita query the Meetup.com API for local meetups
154
173
  test_files:
174
+ - spec/fixtures/meetup_results.json
155
175
  - spec/lita/handlers/meetup_finder_spec.rb
176
+ - spec/lita/meetup_result_spec.rb
156
177
  - spec/spec_helper.rb