events_nearby 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +15 -9
- data/bin/console +1 -1
- data/bin/events_nearby +4 -3
- data/events_nearby.gemspec +9 -1
- data/lib/environment.rb +14 -0
- data/lib/events_nearby/city.rb +44 -0
- data/lib/events_nearby/cli.rb +72 -70
- data/lib/events_nearby/event.rb +26 -0
- data/lib/events_nearby/scraper.rb +56 -46
- data/lib/events_nearby/version.rb +1 -1
- metadata +8 -9
- data/config/environment.rb +0 -8
- data/lib/events_nearby.rb +0 -4
- data/lib/events_nearby/events.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 88852aa7f3a5d1fde260b076cd68223d642f9165d6a03352dae0cd26a653f459
|
4
|
+
data.tar.gz: b5e140a36cea1ed0f14ccc02535996a49f196d5df6ea3f77d919398245cab708
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ddead6ae46f39a03981776c13ac30edcfe535f085e4c30ed76c1fe7e32318a05ad36e78914b125d5c8d05e3dc9eb029d783aeb098e6479fe0ae3bb0fb9a78d3
|
7
|
+
data.tar.gz: 966564917b92816e98b9127bf535b5fb25a1454cea2e16c1efd7b0cffa70b99ad7f67b21f1a624daec25f9723034fdea85f70c48c64b704591e285eec4e4ba5d
|
data/README.md
CHANGED
@@ -2,7 +2,15 @@
|
|
2
2
|
|
3
3
|
Welcome to 'Events Nearby'! In this directory, you'll find a CLI Ruby Gem. 'Events Nearby' lets you enter any location to retrieve a list of events that are near that location. Displayed will be the name of the events, when they are taking place, where exactly they are, and how much they cost. You can then choose one of the listed events to see details about that event and even open it in your browser.
|
4
4
|
|
5
|
-
## Installation
|
5
|
+
## Installation/Running the application
|
6
|
+
|
7
|
+
### Option 1: Cloning the repository and running it directly
|
8
|
+
* Clone this repository: `git clone https://github.com/amelieoller/events-nearby-cli-gem.git`
|
9
|
+
* `cd` into the cloned directory
|
10
|
+
* Run `bundle install` in your terminal
|
11
|
+
* Then run the application with `bin/events_nearby`
|
12
|
+
|
13
|
+
### Option 2: Add the gem to your gemfile
|
6
14
|
|
7
15
|
Add this line to your application's Gemfile:
|
8
16
|
|
@@ -10,13 +18,11 @@ Add this line to your application's Gemfile:
|
|
10
18
|
gem 'events_nearby'
|
11
19
|
```
|
12
20
|
|
13
|
-
And then
|
14
|
-
|
15
|
-
$ bundle
|
16
|
-
|
17
|
-
Or install it yourself as:
|
21
|
+
And then run:
|
22
|
+
$ bundle
|
18
23
|
|
19
|
-
|
24
|
+
### Option 3: Install it yourself
|
25
|
+
$ gem install events_nearby
|
20
26
|
|
21
27
|
## Usage
|
22
28
|
|
@@ -27,9 +33,9 @@ Or install it yourself as:
|
|
27
33
|
|
28
34
|
## Contributing
|
29
35
|
|
30
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
36
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/amelieoller/events-nearby-cli-gem. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
31
37
|
|
32
38
|
|
33
39
|
## License
|
34
40
|
|
35
|
-
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
41
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/bin/console
CHANGED
data/bin/events_nearby
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
# Load
|
4
|
-
require_relative '../
|
3
|
+
# Load our environment
|
4
|
+
require_relative '../lib/environment'
|
5
5
|
|
6
|
-
|
6
|
+
# Create new CLI instance and call choose_city to start app
|
7
|
+
EventsNearby::CLI.new.choose_city
|
data/events_nearby.gemspec
CHANGED
@@ -12,12 +12,20 @@ Gem::Specification.new do |spec|
|
|
12
12
|
spec.summary = %q{Events Nearby will show you events nearby based on the location you enter.}
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
16
|
+
# delete this section to allow pushing this gem to any host.
|
17
|
+
# if spec.respond_to?(:metadata)
|
18
|
+
# spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
|
19
|
+
# else
|
20
|
+
# raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
21
|
+
# end
|
22
|
+
|
15
23
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
16
24
|
spec.bindir = "exe"
|
17
25
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
26
|
spec.require_paths = ["lib"]
|
19
27
|
|
20
|
-
spec.add_development_dependency "bundler", "~>
|
28
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
21
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
22
30
|
spec.add_dependency "nokogiri", "~> 1.8"
|
23
31
|
end
|
data/lib/environment.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# City model
|
2
|
+
class EventsNearby::City
|
3
|
+
attr_accessor :name, :state, :events
|
4
|
+
@@all = []
|
5
|
+
|
6
|
+
def initialize(name, state)
|
7
|
+
@name = name
|
8
|
+
@state = state
|
9
|
+
@events = []
|
10
|
+
@@all << self
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds new event to city array
|
14
|
+
def add_event(event)
|
15
|
+
self.events << event unless self.events.include?(event)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.all
|
19
|
+
@@all
|
20
|
+
end
|
21
|
+
|
22
|
+
# Find city if city and state combination exist already
|
23
|
+
def self.find_by(name, state)
|
24
|
+
self.all.detect{|city| city.name == name && city.state == state}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Parse user city input and return name of city and state
|
28
|
+
def self.parse_city_input(city_input)
|
29
|
+
data = city_input.split(/[\s,]+/)
|
30
|
+
|
31
|
+
if city_input.include?(",")
|
32
|
+
state = data.last.gsub(/[^0-9A-Za-z]/, '').upcase
|
33
|
+
city_array = data.first data.size - 1
|
34
|
+
else
|
35
|
+
city_array = data
|
36
|
+
end
|
37
|
+
|
38
|
+
name = city_array.collect do |item|
|
39
|
+
item.gsub(/[^0-9A-Za-z]/, '').capitalize
|
40
|
+
end.join(" ")
|
41
|
+
|
42
|
+
{name: name, state: state}
|
43
|
+
end
|
44
|
+
end
|
data/lib/events_nearby/cli.rb
CHANGED
@@ -1,81 +1,83 @@
|
|
1
1
|
# CLI Controller
|
2
|
-
|
3
2
|
class EventsNearby::CLI
|
3
|
+
# Ask user for city input, find or create new city and set @city instance variable
|
4
|
+
def choose_city
|
5
|
+
puts "What city would you like to see events nearby? (e.g. 'San Francisco, CA')"
|
6
|
+
|
7
|
+
input = gets.strip.downcase
|
8
|
+
parsed_input = EventsNearby::City.parse_city_input(input)
|
9
|
+
name = parsed_input[:name]
|
10
|
+
state = parsed_input[:state]
|
11
|
+
|
12
|
+
if EventsNearby::City.find_by(name, state)
|
13
|
+
@city = EventsNearby::City.find_by(name, state)
|
14
|
+
list_events
|
15
|
+
else
|
16
|
+
@city = EventsNearby::Scraper.new.scrape_events(name, state)
|
17
|
+
@city == false ? choose_city : list_events
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def list_events
|
22
|
+
separator
|
23
|
+
puts "These are the upcoming events for #{@city.name.bold}:".red
|
24
|
+
separator
|
4
25
|
|
5
|
-
|
6
|
-
|
7
|
-
|
26
|
+
@city.events.each_with_index do |event, i|
|
27
|
+
puts "#{i+1}. #{event.format_event}"
|
28
|
+
end
|
8
29
|
|
9
|
-
|
10
|
-
|
11
|
-
input = gets.strip.downcase
|
12
|
-
EventsNearby::Events.destroy_all
|
13
|
-
EventsNearby::Events.today(input)
|
14
|
-
input == "exit" ? goodbye : list_events(input)
|
15
|
-
end
|
30
|
+
menu
|
31
|
+
end
|
16
32
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
33
|
+
def menu
|
34
|
+
separator
|
35
|
+
puts "What would you like to do next?"
|
36
|
+
puts "- Pick an event by entering a number".bold
|
37
|
+
puts "- Type " + "'city'".bold + " to choose a new city"
|
38
|
+
puts "- Type " + "'list'".bold + " to list all events again"
|
39
|
+
puts "- Type " + "'exit'".bold + " to exit"
|
40
|
+
separator
|
25
41
|
|
26
|
-
|
27
|
-
puts "Which event would you like to know more about? Enter a number, 'start' to start over, or 'exit'."
|
28
|
-
input = gets.strip
|
29
|
-
if input.to_i.between?(1, EventsNearby::Events.all.size)
|
30
|
-
event = EventsNearby::Events.all[input.to_i - 1]
|
31
|
-
show_details(event)
|
32
|
-
else
|
33
|
-
decision(input)
|
34
|
-
end
|
35
|
-
end
|
42
|
+
input = gets.strip
|
36
43
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
44
|
+
if input == "exit"
|
45
|
+
puts "See you later!"
|
46
|
+
elsif input == "list"
|
47
|
+
list_events
|
48
|
+
elsif input == "city"
|
49
|
+
choose_city
|
50
|
+
elsif input.to_i.between?(1, @city.events.size)
|
51
|
+
event = @city.events[input.to_i - 1]
|
52
|
+
EventsNearby::Scraper.new.scrape_event(event) unless event.content
|
53
|
+
show_details(event)
|
54
|
+
else
|
55
|
+
puts "Not sure what you mean..."
|
56
|
+
menu
|
57
|
+
end
|
58
|
+
end
|
52
59
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
60
|
+
def show_details(event)
|
61
|
+
puts ""
|
62
|
+
puts "--- #{event.format_event} ---".green
|
63
|
+
puts event.content
|
64
|
+
puts ""
|
65
|
+
separator
|
66
|
+
puts "Would you like to open this event in your browser? #{'yes'.bold} or #{'no'.bold}?"
|
67
|
+
separator
|
62
68
|
|
63
|
-
|
64
|
-
case input
|
65
|
-
when "exit"
|
66
|
-
goodbye
|
67
|
-
when "menu"
|
68
|
-
menu
|
69
|
-
when "start"
|
70
|
-
choose_city
|
71
|
-
else
|
72
|
-
puts "Not sure what you mean. Enter 'menu' to pick another event, 'start' to start over, or 'exit'."
|
73
|
-
decision(gets.strip)
|
74
|
-
end
|
75
|
-
end
|
69
|
+
input = gets.strip.downcase
|
76
70
|
|
77
|
-
|
78
|
-
|
79
|
-
|
71
|
+
if ["y", "yes", "open"].include?(input)
|
72
|
+
event.open_in_browser
|
73
|
+
puts ""
|
74
|
+
menu
|
75
|
+
else
|
76
|
+
menu
|
77
|
+
end
|
78
|
+
end
|
80
79
|
|
81
|
-
|
80
|
+
def separator
|
81
|
+
puts "--------------**********--------------".red
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Event model
|
2
|
+
class EventsNearby::Event
|
3
|
+
attr_accessor :name, :date, :price, :url, :city, :content
|
4
|
+
@@all = []
|
5
|
+
|
6
|
+
def initialize(name, date, price, url, city)
|
7
|
+
@name = name
|
8
|
+
@date = date
|
9
|
+
@price = price
|
10
|
+
@url = url
|
11
|
+
@city = city
|
12
|
+
@@all << self
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.all
|
16
|
+
@@all
|
17
|
+
end
|
18
|
+
|
19
|
+
def format_event
|
20
|
+
"#{self.name} | #{self.date} | #{self.price}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def open_in_browser
|
24
|
+
Launchy.open(url)
|
25
|
+
end
|
26
|
+
end
|
@@ -1,47 +1,57 @@
|
|
1
|
-
require_relative '../../config/environment'
|
2
|
-
|
3
1
|
class EventsNearby::Scraper
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
2
|
+
def scrape_events(name, state)
|
3
|
+
url = "https://www.eventbrite.com/d/#{state}--#{name.split(/[\s,]+/).join("-")}/all-events/"
|
4
|
+
|
5
|
+
# Check if url is valid or returns error. If valid, scrape city, if not return false
|
6
|
+
doc = nokogiri_error_handling(url)
|
7
|
+
return false if doc == false
|
8
|
+
|
9
|
+
city = EventsNearby::City.new(name, state)
|
10
|
+
|
11
|
+
doc.search(".search-event-card-wrapper").each do |event_data|
|
12
|
+
name = event_data.search(".card-text--truncated__three").text.strip
|
13
|
+
url = event_data.search(".eds-media-card-content__action-link").attr('href').value
|
14
|
+
date = event_data.search(".eds-text-bs--fixed")[0].text
|
15
|
+
price = event_data.search(".eds-text-bs--fixed")[2].text
|
16
|
+
|
17
|
+
event = EventsNearby::Event.new(name, date, price, url, city)
|
18
|
+
city.add_event(event)
|
19
|
+
end
|
20
|
+
|
21
|
+
city
|
22
|
+
end
|
23
|
+
|
24
|
+
def scrape_event(event)
|
25
|
+
doc = nokogiri_error_handling(event.url)
|
26
|
+
event.content = doc.search(".js-xd-read-more-contents p").text.strip[0..300].gsub(/\s\w+\s*$/,'...')
|
27
|
+
end
|
28
|
+
|
29
|
+
def nokogiri_error_handling(url)
|
30
|
+
openuri_params = {
|
31
|
+
# set timeout durations for HTTP connection
|
32
|
+
# default values for open_timeout and read_timeout is 60 seconds
|
33
|
+
:open_timeout => 1,
|
34
|
+
:read_timeout => 1,
|
35
|
+
}
|
36
|
+
|
37
|
+
attempt_count = 0
|
38
|
+
max_attempts = 3
|
39
|
+
|
40
|
+
begin
|
41
|
+
attempt_count += 1
|
42
|
+
content = open(url, openuri_params).read
|
43
|
+
rescue OpenURI::HTTPError => e
|
44
|
+
# it's 404, etc. - puts out error & do nothing
|
45
|
+
puts "We encountered a 404 error, please try again."
|
46
|
+
false
|
47
|
+
rescue SocketError, Net::ReadTimeout => e
|
48
|
+
# server can't be reached or doesn't send any respones
|
49
|
+
puts "error: #{e}"
|
50
|
+
sleep 3
|
51
|
+
retry if attempt_count < max_attempts
|
52
|
+
else
|
53
|
+
# connection successful, content is fetched, parse content with Nokogiri
|
54
|
+
Nokogiri::HTML(content)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: events_nearby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- amelieoller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,11 +68,11 @@ files:
|
|
68
68
|
- bin/console
|
69
69
|
- bin/events_nearby
|
70
70
|
- bin/setup
|
71
|
-
- config/environment.rb
|
72
71
|
- events_nearby.gemspec
|
73
|
-
- lib/
|
72
|
+
- lib/environment.rb
|
73
|
+
- lib/events_nearby/city.rb
|
74
74
|
- lib/events_nearby/cli.rb
|
75
|
-
- lib/events_nearby/
|
75
|
+
- lib/events_nearby/event.rb
|
76
76
|
- lib/events_nearby/scraper.rb
|
77
77
|
- lib/events_nearby/version.rb
|
78
78
|
- spec.md
|
@@ -95,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
requirements: []
|
98
|
-
|
99
|
-
rubygems_version: 2.5.1
|
98
|
+
rubygems_version: 3.0.2
|
100
99
|
signing_key:
|
101
100
|
specification_version: 4
|
102
101
|
summary: Events Nearby will show you events nearby based on the location you enter.
|
data/config/environment.rb
DELETED
data/lib/events_nearby.rb
DELETED
data/lib/events_nearby/events.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
class EventsNearby::Events
|
2
|
-
|
3
|
-
attr_accessor :name, :date, :price, :url, :content
|
4
|
-
|
5
|
-
@@all = []
|
6
|
-
|
7
|
-
def save
|
8
|
-
@@all << self
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.all
|
12
|
-
@@all
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.destroy_all
|
16
|
-
self.all.clear
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.today(input)
|
20
|
-
EventsNearby::Scraper.new.scrape_events(input)
|
21
|
-
end
|
22
|
-
|
23
|
-
def content
|
24
|
-
@content ||= EventsNearby::Scraper.new(url).scrape_event
|
25
|
-
end
|
26
|
-
|
27
|
-
def formatted_event
|
28
|
-
"#{self.name} | #{self.date} | #{self.price}"
|
29
|
-
end
|
30
|
-
|
31
|
-
def open_in_browser
|
32
|
-
system("xdg-open '#{url}'")
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|