phishin-client 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6ba6717562dcaf7dd994c1af15a4c1af646465c
4
- data.tar.gz: 767ed8669cc0948e001a693515aba36937922ef1
3
+ metadata.gz: c31df8b669a3fc0b684d189fda45bc2525da697c
4
+ data.tar.gz: 2e73e1e28a5f23c4fccbc1b623a2f1adbe539b89
5
5
  SHA512:
6
- metadata.gz: 7a43194c60950bd245ed48232c19a4e476a9f0ae662c42ff6b131748a4e4bf11bf4d9c61f9441c9e259f02430b39a15f4187e8fda63e9dd9a6fb1a247f95196f
7
- data.tar.gz: 3e0a13c14bcf6db790b9ba00a3682a086902d4fec36abf699f30f280a1342adb915844cb28d492318708b5aa5644e9d4dc9ba07ecfde0a60f27fbdc6286e1607
6
+ metadata.gz: 9a46ee9486dd17392f9ed597351be9dcc2537a11cf7b36d90d8de3513863632a110d683ff7a9cadad37c4415f446d4e885aa2f44afb022220685987fd07a1ec3
7
+ data.tar.gz: a837f573985ab56a7c6b2b09aa2787d0c87310f6d955cd19b6361d2e8ee0c44bbaf1c55270fce24f189e968350301b9ea6b9d7918695ba1e3bee451710f67b7e
data/README.md CHANGED
@@ -16,10 +16,14 @@ Talks to the http://phish.in API. Has built-in caching.
16
16
  ```ruby
17
17
  require 'phishin-client'
18
18
  doglogger = Logger.new
19
- c = Phishin::Client.new log: true, logger: doglogger
19
+ c = Phishin::Client.new log: true, logger: doglogger, cache_options: { memcached_servers: ['localhost:11211'] }
20
+ # to not use caching, don't specify the :cache => false option
20
21
 
21
- response = c.get_tracks(page: 1, per_page: 40) # Phishin::Api::Response instance
22
+ response = c.tracks(params: { page: 1, per_page: 40 }) # Phishin::Api::Response instance
22
23
  json_hash = response.data
24
+
25
+ # no caching for this request
26
+ response = c.tracks(params: { page: 1, per_page: 40 }, force: true) # Phishin::Api::Response instance
23
27
  ```
24
28
 
25
29
  ## License
@@ -17,16 +17,13 @@ module Phishin
17
17
  @total_pages = response_data['total_pages']
18
18
  @page = response_data['page']
19
19
  @data = response_data['data']
20
+ @data = @data.is_a?(Hash) ? Hashie::Mash.new(@data) : @data.map{ |d| d.is_a?(Hash) ? Hashie::Mash.new(d) : d }
20
21
  else
21
22
  @message = response_data['message']
22
23
  raise Phishin::Client::UnsuccessfulResponseError.new(url, @message)
23
24
  end
24
25
  end
25
26
 
26
- def [](key)
27
- return @data[key]
28
- end
29
-
30
27
  def success?
31
28
  return @success == true
32
29
  end
@@ -3,97 +3,136 @@ module Phishin
3
3
  module V1
4
4
  BASE_URL = 'http://phish.in/api/v1'
5
5
  HEADERS = { 'accept' => 'application/json' }
6
- DEFAULT_PARAMS = %i[page per_page sort_attr sort_dir]
7
6
 
8
- # @param id_or_slug [String,Integer] track id or slug
9
- def get_track(id_or_slug)
10
- check_id_arg('track', id_or_slug)
11
- perform_get_request('tracks/%s.json' % id_or_slug.to_s)
12
- end
13
-
14
- # @option opts [Integer] :page The desired page
15
- # @option opts [Integer] :per_page Results per page
16
- def get_tracks(opts={})
17
- perform_get_request('tracks.json', select_params(opts, DEFAULT_PARAMS))
18
- end
19
-
20
-
21
-
22
- # @param (see #get_track)
23
- def get_show(id_or_slug)
7
+ # Get track by id.
8
+ #
9
+ # @param id [Integer] id belonging to the the resource
10
+ # @option opts [Boolean] :force (false) no caching for this request
11
+ def track(id, opts={})
12
+ check_id_arg('track', id)
13
+ perform_get_request(format('tracks/%d.json', id), nil, opts)
14
+ end
15
+
16
+ # Get many tracks.
17
+ #
18
+ # For more on available params, see http://phish.in/api-docs.
19
+ #
20
+ # @option opts (see #track)
21
+ # @option opts [Hash] :params parameters for HTTP GET query string
22
+ # - :page (Integer) The desired page
23
+ # - :per_page (Integer) Results per page
24
+ # - :sort_attr (String) Sorting attribute
25
+ # - :sort_dir (String) Sorting direction (ASC|DESC)
26
+ def tracks(opts={})
27
+ perform_get_request('tracks.json', opts)
28
+ end
29
+
30
+
31
+ # Get show by id or slug (ie, date).
32
+ #
33
+ # @param id_or_slug [Integer] id or slug belonging to the the resource
34
+ # @option opts (see #track)
35
+ def show(id_or_slug, opts={})
24
36
  check_id_arg('show', id_or_slug)
25
- perform_get_request('shows/%s.json' % id_or_slug.to_s)
37
+ perform_get_request(format('shows/%s.json', id_or_slug.to_s), opts)
26
38
  end
27
39
 
28
- # @option (see #get_tracks)
29
- def get_shows(opts={})
30
- perform_get_request('shows.json', select_params(opts, DEFAULT_PARAMS))
40
+ # Get many shows.
41
+ #
42
+ # @option opts (see #tracks)
43
+ def shows(opts={})
44
+ perform_get_request('shows.json', opts)
31
45
  end
32
46
 
47
+ # Get show by date (YYYY-MM-DD).
48
+ #
33
49
  # @param show_date [String] a show date in the format YYYY-MM-DD
34
- def get_show_on_date(show_date)
50
+ # @option opts (see #track)
51
+ # @raise [Phishin::Cilent::Error] if the date format is wrong
52
+ def show_on_date(show_date, opts={})
35
53
  raise Phishin::Client::Error, "invalid argument: show_date must match YYYY-MM-DD" unless show_date && show_date =~ /\d{4}-\d{2}-\d{2}/
36
- perform_get_request('show-on-date/%s.json' % show_date)
54
+ perform_get_request(format('show-on-date/%s.json', show_date), opts)
37
55
  end
38
56
 
39
57
 
40
58
 
41
- # @param (see #get_track)
42
- def get_song(id_or_slug)
59
+ # Get song by id or slug.
60
+ #
61
+ # @param id_or_slug (see #show)
62
+ # @option opts (see #track)
63
+ def song(id_or_slug, opts={})
43
64
  check_id_arg('song', id_or_slug)
44
- perform_get_request('songs/%s.json' % id_or_slug.to_s)
65
+ perform_get_request(format('songs/%s.json', id_or_slug.to_s), opts)
45
66
  end
46
67
 
47
- # @option (see #get_tracks)
48
- def get_songs(opts={})
49
- perform_get_request('songs.json', select_params(opts, DEFAULT_PARAMS))
68
+ # Get many songs
69
+ #
70
+ # @option opts (see #tracks)
71
+ def songs(opts={})
72
+ perform_get_request('songs.json', opts)
50
73
  end
51
74
 
52
75
 
53
76
 
54
- # @param (see #get_track)
55
- def get_tour(id_or_slug)
77
+ # Get tour by id or slug.
78
+ #
79
+ # @param id_or_slug (see #show)
80
+ # @option opts (see #track)
81
+ def tour(id_or_slug, opts={})
56
82
  check_id_arg('tour', id_or_slug)
57
- perform_get_request('tours/%s.json' % id_or_slug.to_s)
83
+ perform_get_request(format('tours/%s.json', id_or_slug.to_s), opts)
58
84
  end
59
85
 
60
- # @option (see #get_tracks)
61
- def get_tours(opts={})
62
- perform_get_request('tours.json', select_params(opts, DEFAULT_PARAMS))
86
+ # Get many tours.
87
+ #
88
+ # @option opts (see #tracks)
89
+ def tours(opts={})
90
+ perform_get_request('tours.json', opts)
63
91
  end
64
92
 
65
93
 
66
94
 
67
- # @param (see #get_track)
68
- def get_venue(id_or_slug)
95
+ # Get venue by id or slug.
96
+ #
97
+ # @param id_or_slug (see #show)
98
+ # @option opts (see #track)
99
+ def venue(id_or_slug, opts={})
69
100
  check_id_arg('venue', id_or_slug)
70
- perform_get_request('venues/%s.json' % id_or_slug.to_s)
101
+ perform_get_request(format('venues/%s.json', id_or_slug.to_s), opts)
71
102
  end
72
103
 
73
- # @option (see #get_tracks)
74
- def get_venues(opts={})
75
- perform_get_request('venues.json', select_params(opts, DEFAULT_PARAMS))
104
+ # Get many venues.
105
+ #
106
+ # @option opts (see #tracks)
107
+ def venues(opts={})
108
+ perform_get_request('venues.json', opts)
76
109
  end
77
110
 
78
111
 
79
112
 
80
- def get_eras
81
- perform_get_request('eras.json')
113
+ # Get eras.
114
+ #
115
+ # @option opts (see #track)
116
+ def eras(opts={})
117
+ perform_get_request('eras.json', opts)
82
118
  end
83
119
 
84
- def get_years
85
- perform_get_request('years.json')
120
+ # Get years.
121
+ #
122
+ # @option opts (see #track)
123
+ def years(opts={})
124
+ perform_get_request('years.json', opts)
86
125
  end
87
126
 
88
127
 
89
128
 
90
129
  # @api private
91
- def select_params(opts, keys)
92
- params = {}
130
+ def select_params(params, keys)
131
+ _params = {}
93
132
  keys.each do |key|
94
- params[key] = opts[key] if opts.key?(key)
133
+ _params[key] = params[key] if params.key?(key)
95
134
  end
96
- return params
135
+ return _params
97
136
  end
98
137
 
99
138
  # @api private
@@ -102,11 +141,21 @@ module Phishin
102
141
  end
103
142
 
104
143
  # @api private
105
- def perform_get_request(path, params={})
144
+ def perform_get_request(path, opts)
145
+ opts ||= {}
106
146
  url = [BASE_URL, path].join("/")
107
- logger.info "phish.in api GET url=#{url} params=#{params}" if logger
108
- response = RestClient.get(url, HEADERS.merge(params: params))
109
- resp = Phishin::Api::Response.new(url, Oj.load(response.to_s))
147
+ force = opts.delete(:force)
148
+ params = opts.delete(:params) || {}
149
+ key = [path,
150
+ [params.to_a.sort.map { |e| e.join('=')}].join('&')]
151
+ .join('?').chomp('?')
152
+
153
+ json_str = ::Phishin::Client::Cache.fetch(key, force: force) do
154
+ logger.info "phish.in api GET url=#{url} params=#{params}" if logger
155
+ RestClient.get(url, HEADERS.merge(params: params)).to_s
156
+ end
157
+
158
+ resp = Phishin::Api::Response.new(url, JSON.load(json_str))
110
159
  assert_response_data_field(resp)
111
160
  return resp
112
161
  end
@@ -0,0 +1,128 @@
1
+ module Phishin
2
+ module Client
3
+ class Cache
4
+
5
+ CACHE_NAMESPACE = 'phishin-client'
6
+
7
+ class << self
8
+
9
+ @enabled = nil
10
+ @underlying_cache = nil
11
+
12
+ # @api private
13
+ def setup(opts={})
14
+ @enabled = true
15
+
16
+ #require 'dalli'
17
+ #@underlying_cache = MemcachedCache.new(opts)
18
+ require 'redis'
19
+ @underlying_cache = RedisCache.new(opts)
20
+ end
21
+
22
+ # @api private
23
+ def should_cache?
24
+ return @enabled && !!@underlying_cache
25
+ end
26
+
27
+ def enable
28
+ @enabled = true
29
+ end
30
+
31
+ def disable
32
+ @enabled = false
33
+ end
34
+
35
+ def read(key)
36
+ return nil unless should_cache?
37
+
38
+ val = @underlying_cache.get(key)
39
+ log_cache_action('read', key, val) if val
40
+ return val
41
+ end
42
+
43
+ def write(key, value, ttl=nil)
44
+ return nil unless should_cache?
45
+
46
+ log_cache_action('write', key, value)
47
+ @underlying_cache.set(key, value, ttl)
48
+ end
49
+
50
+ def delete(key)
51
+ return nil unless should_cache?
52
+
53
+ val = @underlying_cache.delete(key)
54
+ log_cache_action('delete', key) if val
55
+ return val
56
+ end
57
+
58
+ # @api private
59
+ def log_cache_action(action, key, val=nil)
60
+ ::Phishin::Client::Client.logger.info "phish.in cache #{action} key=#{key[0..8]}" if ::Phishin::Client::Client.logger
61
+ end
62
+
63
+ # @option opts [Integer] :ttl time to live
64
+ # @option opts [Boolean] :force don't use cache
65
+ def fetch(key, opts={})
66
+ ttl = opts.delete(:ttl)
67
+ force = opts.delete(:force)
68
+ value = read(key) unless force
69
+
70
+ if force || !value
71
+ value = yield
72
+ write(key, value, ttl) unless force
73
+ end
74
+ return value
75
+ end
76
+ end
77
+ end
78
+
79
+ class RedisCache
80
+ def initialize(opts={})
81
+ opts ||= {}
82
+ @expires_in = opts.delete(:expires_in)
83
+ url = opts.delete(:url)
84
+ @client = Redis.new(url: url)
85
+ cli = @client.client
86
+ ::Phishin::Client::Client.logger.info "initialized phish.in cache Redis client redis://:REDACTED@#{cli.host}:#{cli.port}/#{cli.db}" if ::Phishin::Client::Client.logger
87
+ end
88
+
89
+ def get(key)
90
+ @client.get(namespace_key(key))
91
+ end
92
+
93
+ def set(key, value, ttl=nil)
94
+ ttl ||= @expires_in
95
+ @client.set(namespace_key(key), value, { ex: ttl })
96
+ end
97
+
98
+ def delete(key)
99
+ @client.del(namespace_key(key))
100
+ end
101
+
102
+ private
103
+
104
+ def namespace_key(key)
105
+ format('%s:%s', Cache::CACHE_NAMESPACE, key)
106
+ end
107
+ end
108
+
109
+ class MemcachedCache
110
+ def initialize(opts={})
111
+ expires_in = opts[:expires_in] || nil
112
+ servers = opts[:servers]
113
+ @client = Dalli::Client.new(servers, namespace: Cache::CACHE_NAMESPACE, expires_in: expires_in)
114
+ end
115
+
116
+ def get(key)
117
+ end
118
+
119
+ def set(key, value, ttl=nil)
120
+ @client.set(key, value, ttl)
121
+ end
122
+
123
+ def delete(key)
124
+ end
125
+ end
126
+ end
127
+ end
128
+
@@ -4,20 +4,53 @@ module Phishin
4
4
 
5
5
  include Phishin::Api::V1
6
6
 
7
- attr_accessor :logger
8
-
9
7
  DEFAULT_LOGGER = lambda do
10
8
  require 'logger'
11
9
  logger = Logger.new(STDOUT)
12
10
  logger.progname = 'phishin-client'
11
+ formatter = Logger::Formatter.new
12
+ logger.formatter = proc { |severity, datetime, progname, msg|
13
+ formatter.call(severity, datetime, progname, msg)
14
+ }
13
15
  logger
14
16
  end
15
17
 
16
- # @option opts [Boolean] :log Enable/disable logging
17
- # @option opts [Object] :logger Logger-compatible object instance to use
18
+ # @param opts [Hash] options hash.
19
+ # @option opts [Boolean] :log Enable/disable logging.
20
+ # @option opts [Object] :logger Logger-compatible object instance to use.
21
+ # @option opts [Boolean] :cache (true) Enable/disable caching.
22
+ # @option opts [Hash] :cache_options options to pass along to the cache.
23
+ # Leave blank to disable caching.
18
24
  def initialize(opts={})
19
- opts[:log] = true if !opts.key?(:log)
20
- @logger = opts[:log] ? (opts[:logger] || DEFAULT_LOGGER.call()) : nil
25
+ opts ||= {}
26
+ opts[:log] = true if !opts.key?(:log)
27
+ cache = opts[:cache] || true
28
+ self.class.logger = opts[:log] ? (opts[:logger] || DEFAULT_LOGGER.call()) : nil
29
+
30
+ if cache
31
+ ::Phishin::Client::Cache.setup(opts[:cache_options])
32
+ end
33
+ end
34
+
35
+ def logger
36
+ return ::Phishin::Client::Client.logger
37
+ end
38
+
39
+ def logger=(logger)
40
+ ::Phishin::Client::Client.logger = logger
41
+ end
42
+
43
+ class << self
44
+
45
+ @logger = nil
46
+
47
+ def logger
48
+ @logger
49
+ end
50
+
51
+ def logger=(logger)
52
+ @logger = logger
53
+ end
21
54
  end
22
55
  end
23
56
  end
@@ -1,6 +1,6 @@
1
1
  module Phishin
2
2
  module Client
3
- VERSION = '0.0.2'
3
+ VERSION = '0.0.3'
4
4
  end
5
5
  end
6
6
 
@@ -1,11 +1,13 @@
1
1
  require 'rest-client'
2
2
  require 'oj'
3
+ require 'hashie'
3
4
 
4
5
  require 'phishin/api'
5
6
  require 'phishin/api/v1'
6
7
  require 'phishin/api/response'
7
8
 
8
9
  require 'phishin/client/version'
10
+ require 'phishin/client/cache'
9
11
  require 'phishin/client/client'
10
12
  require 'phishin/client/errors'
11
13
 
@@ -21,7 +21,10 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_runtime_dependency "rest-client", "~> 1.6.7"
24
- spec.add_runtime_dependency "oj", "~> 2.8.1"
24
+ spec.add_runtime_dependency "json", "~> 1.8.1"
25
+ spec.add_runtime_dependency "hashie", "~> 2.1.1"
26
+ spec.add_runtime_dependency "dalli", "~> 2.7.0"
27
+ spec.add_runtime_dependency "redis", "~> 3.0.5"
25
28
  spec.add_development_dependency "bundler", "~> 1.6"
26
29
  spec.add_development_dependency "rake"
27
30
  spec.add_development_dependency "yard", "~> 0.8"
metadata CHANGED
@@ -1,83 +1,125 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phishin-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Bird
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-29 00:00:00.000000000 Z
11
+ date: 2014-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.6.7
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.6.7
27
27
  - !ruby/object:Gem::Dependency
28
- name: oj
28
+ name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.8.1
33
+ version: 1.8.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.8.1
40
+ version: 1.8.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashie
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.1.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.1.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: dalli
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.7.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.7.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: redis
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 3.0.5
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 3.0.5
41
83
  - !ruby/object:Gem::Dependency
42
84
  name: bundler
43
85
  requirement: !ruby/object:Gem::Requirement
44
86
  requirements:
45
- - - ~>
87
+ - - "~>"
46
88
  - !ruby/object:Gem::Version
47
89
  version: '1.6'
48
90
  type: :development
49
91
  prerelease: false
50
92
  version_requirements: !ruby/object:Gem::Requirement
51
93
  requirements:
52
- - - ~>
94
+ - - "~>"
53
95
  - !ruby/object:Gem::Version
54
96
  version: '1.6'
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: rake
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
- - - '>='
101
+ - - ">="
60
102
  - !ruby/object:Gem::Version
61
103
  version: '0'
62
104
  type: :development
63
105
  prerelease: false
64
106
  version_requirements: !ruby/object:Gem::Requirement
65
107
  requirements:
66
- - - '>='
108
+ - - ">="
67
109
  - !ruby/object:Gem::Version
68
110
  version: '0'
69
111
  - !ruby/object:Gem::Dependency
70
112
  name: yard
71
113
  requirement: !ruby/object:Gem::Requirement
72
114
  requirements:
73
- - - ~>
115
+ - - "~>"
74
116
  - !ruby/object:Gem::Version
75
117
  version: '0.8'
76
118
  type: :development
77
119
  prerelease: false
78
120
  version_requirements: !ruby/object:Gem::Requirement
79
121
  requirements:
80
- - - ~>
122
+ - - "~>"
81
123
  - !ruby/object:Gem::Version
82
124
  version: '0.8'
83
125
  description: Client for http://phish.in Phish streaming API.
@@ -87,7 +129,7 @@ executables: []
87
129
  extensions: []
88
130
  extra_rdoc_files: []
89
131
  files:
90
- - .gitignore
132
+ - ".gitignore"
91
133
  - Gemfile
92
134
  - LICENSE.txt
93
135
  - README.md
@@ -97,6 +139,7 @@ files:
97
139
  - lib/phishin/api/response.rb
98
140
  - lib/phishin/api/v1.rb
99
141
  - lib/phishin/client.rb
142
+ - lib/phishin/client/cache.rb
100
143
  - lib/phishin/client/client.rb
101
144
  - lib/phishin/client/errors.rb
102
145
  - lib/phishin/client/version.rb
@@ -111,17 +154,17 @@ require_paths:
111
154
  - lib
112
155
  required_ruby_version: !ruby/object:Gem::Requirement
113
156
  requirements:
114
- - - '>='
157
+ - - ">="
115
158
  - !ruby/object:Gem::Version
116
159
  version: '0'
117
160
  required_rubygems_version: !ruby/object:Gem::Requirement
118
161
  requirements:
119
- - - '>='
162
+ - - ">="
120
163
  - !ruby/object:Gem::Version
121
164
  version: '0'
122
165
  requirements: []
123
166
  rubyforge_project:
124
- rubygems_version: 2.0.14
167
+ rubygems_version: 2.2.2
125
168
  signing_key:
126
169
  specification_version: 4
127
170
  summary: Phish.in API client