ruby-lol 1.0.0 → 1.1.1

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
  SHA1:
3
- metadata.gz: 7473a66c2ba969476e7a30e8fe148e4c974dc70b
4
- data.tar.gz: c50df90099feec488dca9afd5c17ba85624ca915
3
+ metadata.gz: f57d825feb79e42f3ebd252a9925ff247c6fd13d
4
+ data.tar.gz: 58acfbbf4839d94e1bfeaccb4161f0ddd9df2016
5
5
  SHA512:
6
- metadata.gz: a7efd709d007876b0c9e8972cc4b8af6d91c0956a4c1c695f2c5ae69c8652097539526d3bd3c33bfd4c5ea00046b2139981cd3bc0a3f9b90922ac8ca9dd2e996
7
- data.tar.gz: 5d27adae5e92111f5ec95bcc74a1b7f44f176509576773c3ee8cf59e0953c10acfaf291c93ac58ef575c5952f1e4eb80d594697135647f2e2a4aa2c0dd02f812
6
+ metadata.gz: a693d189f419894e304e744b9ddafcddf9dedee2dd5adf35daa4047621d113520b17f018aa4fcb7890f80625ce64270a89995b3ef5c66c40964fe20b82b2804a
7
+ data.tar.gz: b7a9734744ba482d66ae9e7c4e1b78e1fc722f1c18a307cede2563267436a5520b8241b1f0c60b52f7b44ec42b126d078b1af7a5d73ca7ef867182655a579a5a
data/Guardfile CHANGED
@@ -1,7 +1,7 @@
1
1
  # A sample Guardfile
2
2
  # More info at https://github.com/guard/guard#readme
3
3
 
4
- guard :rspec do
4
+ guard :rspec, cmd: "bundle exec rspec" do
5
5
  watch(%r{^spec/.+_spec\.rb$})
6
6
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
7
  watch('spec/spec_helper.rb') { "spec" }
@@ -21,4 +21,3 @@ guard :rspec do
21
21
  watch(%r{^spec/acceptance/(.+)\.feature$})
22
22
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
23
  end
24
-
data/README.md CHANGED
@@ -27,12 +27,15 @@ Or install it yourself as:
27
27
  ```ruby
28
28
  require 'lol'
29
29
 
30
- client = Lol::Client.new "my_api_key", {region: "euw"}
30
+ client = Lol::Client.new "my_api_key", region: "euw"
31
31
  # => <Lol::Client:0x000000020c0b28 @api_key="my_api_key", @region="euw", @cached=false>
32
32
 
33
- # NEW! You can cache requests using Redis now
33
+ # You can cache requests using Redis now
34
34
  # ttl defaults to 900
35
- client = Lol::Client.new "my_api_key", {region: "euw", redis: "redis://localhost:6379", ttl: 900}
35
+ client = Lol::Client.new "my_api_key", region: "euw", redis: "redis://localhost:6379", ttl: 900
36
+
37
+ # You can specify your rate limits so that the library will throttle requests to avoid errors
38
+ client = Lol::Client.new "new_api_key", region: "euw", rate_limit_requests: 1, rate_limit_seconds: 10
36
39
 
37
40
  # Available Requests
38
41
  client.champion
data/lib/lol.rb CHANGED
@@ -2,6 +2,7 @@ require 'active_support/core_ext/string/inflections'
2
2
  require 'httparty'
3
3
  require 'uri'
4
4
  require 'redis'
5
+ require 'glutton_ratelimit'
5
6
 
6
7
  module Lol
7
8
  # Takes a hash and returns a copy of it with the keys that have been underscored
@@ -13,69 +13,73 @@ module Lol
13
13
  # @return [Integer] the ttl on cached requests
14
14
  attr_reader :ttl
15
15
 
16
+ # @!attribute[r] rate_limiter
17
+ # @return [Object] the rate limiter, if one exists (else nil)
18
+ attr_reader :rate_limiter
19
+
16
20
  # @return [ChampionRequest]
17
21
  def champion
18
- @champion_request ||= ChampionRequest.new(api_key, region, cache_store)
22
+ @champion_request ||= ChampionRequest.new(api_key, region, cache_store, rate_limiter)
19
23
  end
20
24
 
21
25
  # @return [ChampionMasteryRequest]
22
26
  def champion_mastery
23
- @champion_mastery_request ||= ChampionMasteryRequest.new(api_key, region, cache_store)
27
+ @champion_mastery_request ||= ChampionMasteryRequest.new(api_key, region, cache_store, rate_limiter)
24
28
  end
25
29
 
26
30
  # @return [MatchRequest]
27
31
  def match
28
- @match_request ||= MatchRequest.new(api_key, region, cache_store)
32
+ @match_request ||= MatchRequest.new(api_key, region, cache_store, rate_limiter)
29
33
  end
30
34
 
31
35
  # @return [LeagueRequest]
32
36
  def league
33
- @league_request ||= LeagueRequest.new(api_key, region, cache_store)
37
+ @league_request ||= LeagueRequest.new(api_key, region, cache_store, rate_limiter)
34
38
  end
35
39
 
36
40
  # @return [RunesRequest]
37
41
  def runes
38
- @runes_request ||= RunesRequest.new(api_key, region, cache_store)
42
+ @runes_request ||= RunesRequest.new(api_key, region, cache_store, rate_limiter)
39
43
  end
40
44
 
41
45
  # @return [MasteriesRequest]
42
46
  def masteries
43
- @masteries_request ||= MasteriesRequest.new(api_key, region, cache_store)
47
+ @masteries_request ||= MasteriesRequest.new(api_key, region, cache_store, rate_limiter)
44
48
  end
45
49
 
46
50
  # @return [SpectatorRequest]
47
51
  def spectator
48
- @spectator_request ||= SpectatorRequest.new(api_key, region, cache_store)
52
+ @spectator_request ||= SpectatorRequest.new(api_key, region, cache_store, rate_limiter)
49
53
  end
50
54
 
51
55
  # @return [SummonerRequest]
52
56
  def summoner
53
- @summoner_request ||= SummonerRequest.new(api_key, region, cache_store)
57
+ @summoner_request ||= SummonerRequest.new(api_key, region, cache_store, rate_limiter)
54
58
  end
55
59
 
56
60
  # @return [StaticRequest]
57
61
  def static
58
- @static_request ||= StaticRequest.new(api_key, region, cache_store)
62
+ @static_request ||= StaticRequest.new(api_key, region, cache_store, rate_limiter)
59
63
  end
60
64
 
61
65
  # @return [LolStatusRequest]
62
66
  def lol_status
63
- @lol_status ||= LolStatusRequest.new(api_key, region, cache_store)
67
+ @lol_status ||= LolStatusRequest.new(api_key, region, cache_store, rate_limiter)
64
68
  end
65
69
 
66
70
  # @return [CurrentGameRequest]
67
71
  def current_game
68
- @current_game ||= CurrentGameRequest.new(api_key, region, cache_store)
72
+ @current_game ||= CurrentGameRequest.new(api_key, region, cache_store, rate_limiter)
69
73
  end
70
74
 
71
75
  # @return [FeaturedGamesRequest]
72
76
  def featured_games
73
- @featured_games ||= FeaturedGamesRequest.new(api_key, region, cache_store)
77
+ @featured_games ||= FeaturedGamesRequest.new(api_key, region, cache_store, rate_limiter)
74
78
  end
75
79
 
76
80
  # @return [TournamentProviderRequest]
77
81
  def tournament
78
- @tournament ||= TournamentRequest.new(api_key, region, cache_store)
82
+ @tournament ||= TournamentRequest.new(api_key, region, cache_store, rate_limiter)
79
83
  end
80
84
 
81
85
  # Initializes a Lol::Client
@@ -84,11 +88,14 @@ module Lol
84
88
  # @option options [String] :region ("EUW") The region on which the requests will be made
85
89
  # @option options [String] :redis the redis url to use for caching
86
90
  # @option options [Integer] :ttl (900) the cache ttl
91
+ # @option options [Fixnum] :rate_limit_requests number of requests
92
+ # @option options [Fixnum] :rate_limit_seconds number of seconds to limit the rate in
87
93
  # @return [Lol::Client]
88
94
  def initialize api_key, options = {}
89
95
  @api_key = api_key
90
96
  @region = options.delete(:region) || "euw"
91
97
  set_up_cache(options.delete(:redis), options.delete(:ttl))
98
+ set_up_rate_limiter(options.delete(:rate_limit_requests), options.delete(:rate_limit_seconds))
92
99
  end
93
100
 
94
101
  def set_up_cache(redis_url, ttl)
@@ -99,6 +106,13 @@ module Lol
99
106
  @redis = Redis.new :url => redis_url
100
107
  end
101
108
 
109
+ def set_up_rate_limiter(number_of_requests, number_of_seconds)
110
+ return @rate_limited = false unless number_of_requests
111
+
112
+ @rate_limited = true
113
+ @rate_limiter = GluttonRatelimit::AveragedThrottle.new number_of_requests, number_of_seconds
114
+ end
115
+
102
116
  # Returns an options hash with cache keys
103
117
  # @return [Hash]
104
118
  def cache_store
@@ -109,6 +123,11 @@ module Lol
109
123
  }
110
124
  end
111
125
 
126
+ # @return [Boolean] true if requests are automatically rate limited
127
+ def rate_limited?
128
+ @rate_limiter
129
+ end
130
+
112
131
  # @return [Boolean] true if requests are cached
113
132
  def cached?
114
133
  @cached
@@ -10,13 +10,11 @@ module Lol
10
10
 
11
11
  # Get match by match ID.
12
12
  # @param [Integer] match_id Match ID
13
- # @param [String] tournament_code Optional tournament code the match belongs to
13
+ # @option options [Integer] forAccountId Optional used to identify the participant to be unobfuscated
14
+ # @option options [Integer] forPlatformId Optional used to identify the participant to be unobfuscated (for when user have changed regions)
14
15
  # @return [DynamicModel] Match representation
15
- def find match_id, tournament_code: nil
16
- url = "matches/#{match_id}".tap do |u|
17
- u << "/by-tournament-code/#{tournament_code}" if tournament_code
18
- end
19
- DynamicModel.new perform_request api_url url
16
+ def find options={}, match_id:
17
+ DynamicModel.new perform_request api_url "matches/#{match_id}", options
20
18
  end
21
19
 
22
20
  # Get match timeline by match ID.
@@ -33,6 +31,14 @@ module Lol
33
31
  perform_request api_url "matches/by-tournament-code/#{tournament_code}/ids"
34
32
  end
35
33
 
34
+ # Get match by match ID and tournament code.
35
+ # @param [Integer] match_id Match ID
36
+ # @param [String] tournament_code Tournament code the match belongs to
37
+ # @return [DynamicModel] Match representation
38
+ def find_by_tournament match_id, tournament_code
39
+ DynamicModel.new perform_request api_url "matches/#{match_id}/by-tournament-code/#{tournament_code}"
40
+ end
41
+
36
42
  # Get matchlist for ranked games played on given account ID and platform ID and filtered using given filter parameters, if any.
37
43
  # @param [Integer] account_id Account ID
38
44
  # @param [Hash] options the options to pass to the call
@@ -24,6 +24,10 @@ module Lol
24
24
  # @return [Object] the cache_store
25
25
  attr_reader :cache_store
26
26
 
27
+ # @!attribute[r] rate_limiter
28
+ # @return [Object] the rate limiter, if one exists (else nil)
29
+ attr_reader :rate_limiter
30
+
27
31
  # Returns the supported API Version.
28
32
  # @return [String] v3
29
33
  def self.api_version
@@ -54,15 +58,16 @@ module Lol
54
58
  # @option cache_store [Boolean] :cached should the request be cached
55
59
  # @option cacche_store [Integer] :ttl ttl for cache keys
56
60
  # @return [Request]
57
- def initialize api_key, region, cache_store = {}
58
- @cache_store = cache_store
61
+ def initialize api_key, region, cache_store = {}, rate_limiter = nil
62
+ @cache_store = cache_store
63
+ @rate_limiter = rate_limiter
59
64
  raise InvalidCacheStore if cached? && !store.is_a?(Redis)
60
65
  @api_key = api_key
61
- @region = region
66
+ @region = region
62
67
  end
63
68
 
64
69
  def platform
65
- self.class.platforms[region.to_sym]
70
+ self.class.platforms[region.downcase.to_sym]
66
71
  end
67
72
 
68
73
  # Returns the supported API Version.
@@ -103,7 +108,8 @@ module Lol
103
108
  uri.to_s
104
109
  end
105
110
 
106
- # Calls the API via HTTParty and handles errors
111
+ # Calls the API via HTTParty and handles errors caching it if a cache is
112
+ # enabled and rate limiting it if a rate limiter is configured
107
113
  # @param url [String] the url to call
108
114
  # @param verb [Symbol] HTTP verb to use. Defaults to :get
109
115
  # @param body [Hash] Body for POST request
@@ -115,11 +121,18 @@ module Lol
115
121
  if can_cache && result = store.get("#{clean_url(url)}#{options_id}")
116
122
  return JSON.parse(result)
117
123
  end
118
- response = perform_uncached_request url, verb, body, options
124
+ response = perform_rate_limited_request(url, verb, body, options)
119
125
  store.setex "#{clean_url(url)}#{options_id}", ttl, response.to_json if can_cache
120
126
  response
121
127
  end
122
128
 
129
+ def perform_rate_limited_request url, verb = :get, body = nil, options = {}
130
+ return perform_uncached_request(url, verb, body, options) unless rate_limiter
131
+ @rate_limiter.times 1 do
132
+ perform_uncached_request(url, verb, body, options)
133
+ end
134
+ end
135
+
123
136
  def perform_uncached_request url, verb = :get, body = nil, options = {}
124
137
  options[:headers] ||= {}
125
138
  options[:headers].merge!({
@@ -7,7 +7,7 @@ module Lol
7
7
 
8
8
  # @!visibility private
9
9
  def api_base_url
10
- "https://global.api.riotgames.com"
10
+ "https://americas.api.riotgames.com"
11
11
  end
12
12
 
13
13
  # Creates a tournament provider and returns its ID.
@@ -26,10 +26,9 @@ module Lol
26
26
  # @param [String] name Name of the tournament
27
27
  # @return [Integer] Tournament ID
28
28
  def create_tournament provider_id:, name: nil
29
- body = {
30
- "providerId" => provider_id,
31
- "name" => name
32
- }.compact
29
+ body = { "providerId" => provider_id, "name" => name }.delete_if do |k, v|
30
+ v.nil?
31
+ end
33
32
  perform_request api_url("tournaments"), :post, body
34
33
  end
35
34
 
@@ -1,3 +1,3 @@
1
1
  module Lol
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.1"
3
3
  end
@@ -35,4 +35,5 @@ Gem::Specification.new do |spec|
35
35
  spec.add_runtime_dependency "httparty", "0.14.0" # due to https://github.com/jnunemaker/httparty/issues/533
36
36
  spec.add_runtime_dependency "activesupport"
37
37
  spec.add_runtime_dependency "redis"
38
+ spec.add_runtime_dependency "glutton_ratelimit"
38
39
  end
@@ -45,6 +45,23 @@ describe Client do
45
45
  expect(champion_request.cache_store).to eq(real_redis.cache_store)
46
46
  end
47
47
  end
48
+
49
+ context "rate_limiting" do
50
+ let(:client) { Client.new "foo", rate_limit_requests: 10 }
51
+
52
+ it "sets rate limiting if specified in the options" do
53
+ expect(client.rate_limited?).to be_truthy
54
+ end
55
+
56
+ it "instantiates a rate limiter if it is in the options" do
57
+ expect(client.rate_limiter).not_to be_nil
58
+ end
59
+
60
+ it "passes the rate limiter to the request" do
61
+ champion_request = client.champion
62
+ expect(champion_request.rate_limiter).to eq(client.rate_limiter)
63
+ end
64
+ end
48
65
  end
49
66
 
50
67
  describe "#cached?" do
@@ -65,7 +82,7 @@ describe Client do
65
82
  end
66
83
 
67
84
  it "initializes the ChampionRequest with the current API key and region" do
68
- expect(ChampionRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
85
+ expect(ChampionRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
69
86
 
70
87
  subject.champion
71
88
  end
@@ -77,7 +94,7 @@ describe Client do
77
94
  end
78
95
 
79
96
  it "initializes the MatchRequest with the current API key and region" do
80
- expect(MatchRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
97
+ expect(MatchRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
81
98
 
82
99
  subject.match
83
100
  end
@@ -89,7 +106,7 @@ describe Client do
89
106
  end
90
107
 
91
108
  it "initializes the RunesRequest with the current API key and region" do
92
- expect(RunesRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
109
+ expect(RunesRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
93
110
 
94
111
  subject.runes
95
112
  end
@@ -101,7 +118,7 @@ describe Client do
101
118
  end
102
119
 
103
120
  it "initializes the MasteriesRequest with the current API key and region" do
104
- expect(MasteriesRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
121
+ expect(MasteriesRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
105
122
 
106
123
  subject.masteries
107
124
  end
@@ -113,7 +130,7 @@ describe Client do
113
130
  end
114
131
 
115
132
  it "initializes the LeagueRequest with the current API key and region" do
116
- expect(LeagueRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
133
+ expect(LeagueRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
117
134
 
118
135
  subject.league
119
136
  end
@@ -125,7 +142,7 @@ describe Client do
125
142
  end
126
143
 
127
144
  it "initializes the SummonerRequest with the current API key and region" do
128
- expect(SummonerRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
145
+ expect(SummonerRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
129
146
 
130
147
  subject.summoner
131
148
  end
@@ -137,7 +154,7 @@ describe Client do
137
154
  end
138
155
 
139
156
  it "initializes the StaticRequest with the current API key and region" do
140
- expect(StaticRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store)
157
+ expect(StaticRequest).to receive(:new).with(subject.api_key, subject.region, subject.cache_store, subject.rate_limiter)
141
158
 
142
159
  subject.static
143
160
  end
@@ -11,22 +11,9 @@ describe MatchRequest do
11
11
  end
12
12
 
13
13
  describe "#find" do
14
- context "without a tournament code" do
15
- let(:result) { subject.find 1 }
16
- before { stub_request subject, 'match', "matches/1" }
17
-
18
- it "returns a DynamicModel" do
19
- expect(result).to be_a DynamicModel
20
- end
21
- end
22
-
23
- context "with a tournament code" do
24
- let(:result) { subject.find 1, tournament_code: 2 }
25
- before { stub_request subject, 'match-with-tc', "matches/1/by-tournament-code/2" }
26
-
27
- it "returns a DynamicModel" do
28
- expect(result).to be_a DynamicModel
29
- end
14
+ it "returns a DynamicModel" do
15
+ stub_request subject, 'match', "matches/1"
16
+ expect(subject.find match_id: 1).to be_a DynamicModel
30
17
  end
31
18
  end
32
19
 
@@ -42,7 +29,14 @@ describe MatchRequest do
42
29
  stub_request subject, 'ids-by-tc', "matches/by-tournament-code/1/ids"
43
30
  result = subject.ids_by_tournament_code '1'
44
31
  expect(result).to be_a Array
45
- expect(result.map(&:class).uniq).to eq [Integer]
32
+ expect(result.map(&:class).uniq).to eq [Fixnum]
33
+ end
34
+ end
35
+
36
+ describe "#find_by_tournament" do
37
+ it "returns a DynamicModel" do
38
+ stub_request subject, 'match-with-tc', "matches/1/by-tournament-code/2"
39
+ expect(subject.find_by_tournament 1, 2).to be_a DynamicModel
46
40
  end
47
41
  end
48
42
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lol
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Giovanni Intini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-24 00:00:00.000000000 Z
11
+ date: 2017-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -240,6 +240,20 @@ dependencies:
240
240
  - - ">="
241
241
  - !ruby/object:Gem::Version
242
242
  version: '0'
243
+ - !ruby/object:Gem::Dependency
244
+ name: glutton_ratelimit
245
+ requirement: !ruby/object:Gem::Requirement
246
+ requirements:
247
+ - - ">="
248
+ - !ruby/object:Gem::Version
249
+ version: '0'
250
+ type: :runtime
251
+ prerelease: false
252
+ version_requirements: !ruby/object:Gem::Requirement
253
+ requirements:
254
+ - - ">="
255
+ - !ruby/object:Gem::Version
256
+ version: '0'
243
257
  description: Ruby wrapper to Riot Games API. Maps results to full blown ruby objects.
244
258
  email:
245
259
  - giovanni@mikamai.com