rito 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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +30 -0
  3. data/LICENSE +21 -0
  4. data/README.md +182 -0
  5. data/lib/rito/client.rb +118 -0
  6. data/lib/rito/connection.rb +39 -0
  7. data/lib/rito/endpoints/account_v1.rb +45 -0
  8. data/lib/rito/endpoints/base.rb +35 -0
  9. data/lib/rito/endpoints/lol/challenges_v1.rb +31 -0
  10. data/lib/rito/endpoints/lol/champion_mastery_v4.rb +33 -0
  11. data/lib/rito/endpoints/lol/champion_v3.rb +17 -0
  12. data/lib/rito/endpoints/lol/clash_v1.rb +27 -0
  13. data/lib/rito/endpoints/lol/league_v4.rb +58 -0
  14. data/lib/rito/endpoints/lol/match_v5.rb +34 -0
  15. data/lib/rito/endpoints/lol/spectator_v5.rb +22 -0
  16. data/lib/rito/endpoints/lol/status_v4.rb +15 -0
  17. data/lib/rito/endpoints/lol/summoner_v4.rb +35 -0
  18. data/lib/rito/endpoints/lol/tournament_v5.rb +69 -0
  19. data/lib/rito/endpoints/lor.rb +95 -0
  20. data/lib/rito/endpoints/tft.rb +123 -0
  21. data/lib/rito/endpoints/valorant.rb +92 -0
  22. data/lib/rito/errors.rb +55 -0
  23. data/lib/rito/instrumentation.rb +17 -0
  24. data/lib/rito/middleware/authentication.rb +21 -0
  25. data/lib/rito/middleware/rate_limit_observe.rb +32 -0
  26. data/lib/rito/middleware/rate_limit_throttle.rb +58 -0
  27. data/lib/rito/middleware/riot_errors.rb +81 -0
  28. data/lib/rito/models/account.rb +38 -0
  29. data/lib/rito/models/lol.rb +80 -0
  30. data/lib/rito/models/match.rb +71 -0
  31. data/lib/rito/models/summoner.rb +23 -0
  32. data/lib/rito/rate_limiting/adaptive_limiter.rb +71 -0
  33. data/lib/rito/rate_limiting/bucket.rb +83 -0
  34. data/lib/rito/rate_limiting/header_parser.rb +53 -0
  35. data/lib/rito/rate_limiting/null_limiter.rb +11 -0
  36. data/lib/rito/rate_limiting/redis_limiter.rb +153 -0
  37. data/lib/rito/routing.rb +79 -0
  38. data/lib/rito/version.rb +5 -0
  39. data/lib/rito.rb +71 -0
  40. metadata +109 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 882b1dd78a0168c537a254240ff33562776b50a95ee04e17864229bde2cde2b0
4
+ data.tar.gz: ad4ec1b37559654409118de196adcdcb082f813a186e92688988adb8ebba3379
5
+ SHA512:
6
+ metadata.gz: d0cef7acb7d9d98b2176dae271f24ccd23037c4d091be4e5896ff71a08682bd9657a072bf3ede3bb7ef5c328f55ff7826b2624e8305d6895746d99b0400338ed
7
+ data.tar.gz: 1f54d50efe21dc86999746be59cc29704610288b8cd595a2e09b97fe78831edef5ed6a1e81815f0afd60277733ce1cc8d3a2be22807302ebfaac6bb21d15b522
data/CHANGELOG.md ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (2026-09-05)
4
+
5
+ Initial release.
6
+
7
+ - **HTTP layer**: Faraday 2.x with a per-host connection cache, JSON
8
+ request/response middleware, and transport retries (5xx, connection
9
+ failures) via faraday-retry.
10
+ - **Routing**: platform vs regional routing values with automatic escalation
11
+ (`na1 → americas`), SEA→ASIA normalization for account-v1, and separate
12
+ VALORANT platform sets (`na1, eu, ap, kr, latam, br`; console: `na, eu, ap`).
13
+ - **Rate limiting**: `AdaptiveLimiter` (default) learns limits from
14
+ `X-App-Rate-Limit` / `X-Method-Rate-Limit` headers, syncs counters from
15
+ `*-Count` headers, throttles pre-emptively, handles 429s by scope
16
+ (application / method / service) honoring `Retry-After` with exponential
17
+ backoff + jitter fallback. `NullLimiter` for reactive-only mode.
18
+ `RedisLimiter` for multi-process deployments (soft dependency on `redis`).
19
+ - **Errors**: mapped hierarchy (400/401/403/404/405/415/429/5xx,
20
+ ConnectionError/TimeoutError/SSLError); `RateLimited` carries
21
+ `retry_after` and `limit_type`.
22
+ - **Models**: frozen `Data` classes with liberal mapping; unknown fields
23
+ preserved in `.raw`.
24
+ - **Coverage**: account-v1; LoL summoner-v4, match-v5, champion-mastery-v4,
25
+ champion-v3, league-v4, league-exp-v4, spectator-v5, lol-status-v4, clash-v1,
26
+ lol-challenges-v1, tournament-v5 (+ stub); TFT summoner/league/match/status/
27
+ spectator; VALORANT content/match/console-match/ranked/status; LoR
28
+ match/ranked/status/deck/inventory (RSO); riftbound-content-v1.
29
+ - **Instrumentation**: `request.rito` ActiveSupport::Notifications events
30
+ (no-op without ActiveSupport).
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kodbilenadam
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,182 @@
1
+ # Rito
2
+
3
+ A modern, production-ready Ruby client for the Riot Games API: League of
4
+ Legends, TFT, VALORANT, Legends of Runeterra, Riftbound, and the Riot Account API.
5
+
6
+ Full routing-value handling, header-driven adaptive rate limiting, frozen
7
+ `Data` models, and a single runtime dependency (Faraday).
8
+
9
+ ## Installation
10
+
11
+ ```ruby
12
+ gem "rito"
13
+ ```
14
+
15
+ ## Quick start
16
+
17
+ ```ruby
18
+ require "rito"
19
+
20
+ Rito.configure do |c|
21
+ c.api_key = ENV.fetch("RIOT_API_KEY")
22
+ c.region = :na1
23
+ end
24
+
25
+ client = Rito::Client.new
26
+
27
+ account = client.account.by_riot_id("Hide on bush", "KR1", region: :asia)
28
+ summoner = client.summoner.by_puuid(account.puuid, region: :kr)
29
+ match_ids = client.matches.ids_by_puuid(account.puuid, region: :asia, count: 5)
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ Class-level config with per-client overrides (later wins):
35
+
36
+ ```ruby
37
+ Rito.api_key # default: ENV["RIOT_API_KEY"]
38
+ Rito.bearer_token # default: ENV["RIOT_RSO_TOKEN"] (RSO endpoints)
39
+ Rito.region # default routing value, e.g. :na1
40
+ Rito.max_retries # 429 / transport retries (default: 3)
41
+ Rito.rate_limiter # rate limit strategy (default: AdaptiveLimiter)
42
+
43
+ # per-client, for multi-key apps:
44
+ client = Rito::Client.new(api_key: "RGAPI-...", region: :kr)
45
+ ```
46
+
47
+ ## Routing values
48
+
49
+ Endpoints declare whether they are platform-routed (`na1`, `kr`, ...) or
50
+ regionally routed (`americas`, `europe`, `asia`, `sea`). You pass whichever you
51
+ have; the client escalates automatically:
52
+
53
+ ```ruby
54
+ client.summoner.by_puuid(puuid, region: :kr) # platform host: kr
55
+ client.matches.ids_by_puuid(puuid, region: :kr) # regional host: asia (escalated)
56
+ client.account.by_puuid(puuid, region: :sea) # account-v1 has no SEA host → asia
57
+ ```
58
+
59
+ ## Rate limiting
60
+
61
+ The default `AdaptiveLimiter` learns your key's limits from
62
+ `X-App-Rate-Limit` / `X-Method-Rate-Limit` headers, syncs counters from
63
+ `*-Count` headers, throttles pre-emptively, and handles 429s:
64
+
65
+ - `Retry-After` present → blocks that long (app-scope blocks the whole
66
+ key+region; method-scope blocks only the endpoint).
67
+ - `Retry-After` missing → exponential backoff with jitter.
68
+ - No `X-Rate-Limit-Type` header → service-level 429 → endpoint-only backoff.
69
+
70
+ Exhausted retries raise `Rito::RateLimited` (with `.retry_after` and
71
+ `.limit_type`). Opt out with `Rito::RateLimiting::NullLimiter`.
72
+
73
+ ### Multi-worker deployments
74
+
75
+ Each process using the default `AdaptiveLimiter` tracks limits independently,
76
+ so a multi-worker setup (Puma cluster, multiple hosts) can collectively exceed
77
+ one key's limits. Use the Redis limiter for shared state:
78
+
79
+ ```ruby
80
+ limiter = Rito::RateLimiting::RedisLimiter.new(redis: Redis.new)
81
+ client = Rito::Client.new(rate_limiter: limiter)
82
+ ```
83
+
84
+ Note: `acquire!` blocks the calling thread while throttled — fine in
85
+ background jobs; in web requests prefer jobs or `max_retries: 0` with
86
+ explicit `Rito::RateLimited` handling.
87
+
88
+ ### Multi-process (Redis)
89
+
90
+ ```ruby
91
+ gem "redis" # soft dependency
92
+
93
+ limiter = Rito::RateLimiting::RedisLimiter.new(redis: Redis.new)
94
+ client = Rito::Client.new(rate_limiter: limiter)
95
+ ```
96
+
97
+ ## Errors
98
+
99
+ ```
100
+ Rito::Error
101
+ ├── BadRequest (400) ├── MethodNotAllowed (405)
102
+ ├── Unauthorized (401) ├── UnsupportedMediaType (415)
103
+ ├── Forbidden (403) ├── RateLimited (429)
104
+ ├── NotFound (404) ├── ServerError / ServiceUnavailable (5xx)
105
+ └── ConnectionError (TimeoutError, SSLError)
106
+ ```
107
+
108
+ Every error carries `.status` and `.response`. Messages include the method,
109
+ URL, and Riot's error detail.
110
+
111
+ ## Models
112
+
113
+ Responses are frozen `Data` objects. Documented fields are typed accessors;
114
+ unknown fields Riot adds later are preserved in `.raw`:
115
+
116
+ ```ruby
117
+ entry = client.leagues.entries_by_summoner_id(summoner_id).first
118
+ entry.tier # => "DIAMOND"
119
+ entry.winrate # => 57.14
120
+ entry.raw # => full payload hash
121
+ ```
122
+
123
+ ## Coverage
124
+
125
+ | Accessor | API |
126
+ | --- | --- |
127
+ | `client.account` | account-v1 |
128
+ | `client.summoner` | summoner-v4 |
129
+ | `client.matches` | match-v5 (matches, matchlist, timeline) |
130
+ | `client.champion_masteries` | champion-mastery-v4 |
131
+ | `client.champions` | champion-v3 (rotations) |
132
+ | `client.leagues` / `client.league_exp` | league-v4 / league-exp-v4 |
133
+ | `client.spectator` | spectator-v5 (`active_game` returns `nil` on 404) |
134
+ | `client.lol_status` | lol-status-v4 |
135
+ | `client.clash` | clash-v1 |
136
+ | `client.challenges` | lol-challenges-v1 |
137
+ | `client.tournaments` / `client.tournament_stub` | tournament-v5 / stub-v5 |
138
+ | `client.tft.summoner` / `.leagues` / `.matches` / `.status` / `.spectator` | tft-summoner-v1, tft-league-v1, tft-match-v1, tft-status-v1, spectator-tft-v5 |
139
+ | `client.val.content` / `.matches` / `.console_matches` / `.ranked` / `.status` | val-content-v1, val-match-v1, val-console-match-v1, val-ranked-v1, val-status-v1 |
140
+ | `client.lor.matches` / `.ranked` / `.status` / `.decks` / `.inventory` | lor-match-v1, lor-ranked-v1, lor-status-v1, lor-deck-v1 / lor-inventory-v1 (RSO) |
141
+ | `client.riftbound` | riftbound-content-v1 |
142
+
143
+ Note: VALORANT uses its own platform routing values (`na1, eu, ap, kr, latam, br`;
144
+ console: `na, eu, ap`) — the client validates against the right set per product.
145
+
146
+ ## Testing your own app
147
+
148
+ `Rito` plays well with WebMock. Recorded fixtures via VCR:
149
+
150
+ ```
151
+ bundle exec rake cassettes # re-record (needs RIOT_API_KEY_TEST in .env)
152
+ bundle exec rake test
153
+ ```
154
+
155
+ ## Instrumentation
156
+
157
+ If ActiveSupport is present (e.g. in a Rails app), every request emits a
158
+ `request.rito` notification:
159
+
160
+ ```ruby
161
+ ActiveSupport::Notifications.subscribe("request.rito") do |*, payload|
162
+ Rails.logger.info(
163
+ "#{payload[:http_method]} #{payload[:url]} -> #{payload[:status]} " \
164
+ "in #{payload[:duration_ms]}ms (attempts: #{payload[:attempts]})"
165
+ )
166
+ end
167
+ ```
168
+
169
+ Without ActiveSupport, instrumentation is a no-op.
170
+
171
+ ## Development
172
+
173
+ ```
174
+ bundle install
175
+ bundle exec rake test
176
+ ```
177
+
178
+ Ruby 3.2+ required (`Data.define`).
179
+
180
+ ## License
181
+
182
+ MIT
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ class Client
5
+ attr_reader :api_key, :bearer_token, :region, :limiter, :max_retries,
6
+ :open_timeout, :timeout, :adapter
7
+
8
+ def initialize(api_key: nil, bearer_token: nil, region: nil, rate_limiter: nil,
9
+ max_retries: nil, open_timeout: nil, timeout: nil, adapter: nil)
10
+ @api_key = api_key || Rito.api_key
11
+ @bearer_token = bearer_token || Rito.bearer_token
12
+ @region = region || Rito.region
13
+ @limiter = rate_limiter || Rito.rate_limiter || RateLimiting::AdaptiveLimiter.new
14
+ @max_retries = max_retries || Rito.max_retries
15
+ @open_timeout = open_timeout || Rito.open_timeout
16
+ @timeout = timeout || Rito.timeout
17
+ @adapter = adapter || Rito.adapter
18
+ @connection = Connection.new(self)
19
+
20
+ validate!
21
+ end
22
+
23
+ def account
24
+ Endpoints::AccountV1.new(self)
25
+ end
26
+
27
+ def summoner
28
+ Endpoints::Lol::SummonerV4.new(self)
29
+ end
30
+
31
+ def matches
32
+ Endpoints::Lol::MatchV5.new(self)
33
+ end
34
+
35
+ def champion_masteries
36
+ Endpoints::Lol::ChampionMasteryV4.new(self)
37
+ end
38
+
39
+ def champions
40
+ Endpoints::Lol::ChampionV3.new(self)
41
+ end
42
+
43
+ def leagues
44
+ Endpoints::Lol::LeagueV4.new(self)
45
+ end
46
+
47
+ def league_exp
48
+ Endpoints::Lol::LeagueExpV4.new(self)
49
+ end
50
+
51
+ def spectator
52
+ Endpoints::Lol::SpectatorV5.new(self)
53
+ end
54
+
55
+ def lol_status
56
+ Endpoints::Lol::StatusV4.new(self)
57
+ end
58
+
59
+ def clash
60
+ Endpoints::Lol::ClashV1.new(self)
61
+ end
62
+
63
+ def challenges
64
+ Endpoints::Lol::ChallengesV1.new(self)
65
+ end
66
+
67
+ def tournaments
68
+ Endpoints::Lol::TournamentV5.new(self)
69
+ end
70
+
71
+ def tournament_stub
72
+ Endpoints::Lol::TournamentStubV5.new(self)
73
+ end
74
+
75
+ def tft
76
+ Rito::Tft::Api.new(self)
77
+ end
78
+
79
+ def val
80
+ Rito::Val::Api.new(self)
81
+ end
82
+
83
+ def lor
84
+ Rito::Lor::Api.new(self)
85
+ end
86
+
87
+ def riftbound
88
+ Endpoints::Riftbound.new(self)
89
+ end
90
+
91
+ def request(method, path, routing_kind:, routing_value: nil, params: {}, body: nil)
92
+ region = Routing.resolve(routing_kind, routing_value || @region)
93
+ connection = @connection.for_host(Routing.host_for(region))
94
+ response = connection.run_request(method, path, body, {}) do |req|
95
+ req.params.update(params) unless params.empty?
96
+ end
97
+ # 5xx responses reaching here are final: faraday-retry has exhausted
98
+ # its retries (or the status was not retryable).
99
+ raise_server_error!(response) if response.status >= 500
100
+ response
101
+ end
102
+
103
+ private
104
+
105
+ def raise_server_error!(response)
106
+ status = response.status
107
+ error_class = status == 503 ? ServiceUnavailable : ServerError
108
+ raise error_class.new("#{status} (after transport retries)", response: response)
109
+ end
110
+
111
+ def validate!
112
+ raise ConfigError, 'api_key or bearer_token is required' if @api_key.to_s.empty? && @bearer_token.to_s.empty?
113
+ return if Routing.platform?(@region) || Routing.regional?(@region)
114
+
115
+ raise ConfigError, "unknown region: #{@region.inspect}"
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ class Connection
5
+ def initialize(client)
6
+ @client = client
7
+ @connections = {}
8
+ @mutex = Mutex.new
9
+ end
10
+
11
+ def for_host(host)
12
+ @mutex.synchronize do
13
+ @connections[host] ||= build(host)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def build(host)
20
+ Faraday.new("https://#{host}") do |f|
21
+ f.options.open_timeout = @client.open_timeout
22
+ f.options.timeout = @client.timeout
23
+ f.request :json
24
+ f.request :retry,
25
+ max: @client.max_retries,
26
+ retry_statuses: [500, 503, 504],
27
+ interval: 0.5,
28
+ backoff_factor: 2,
29
+ exceptions: [Faraday::ConnectionFailed, Faraday::TimeoutError, Faraday::RetriableResponse]
30
+ f.use Middleware::RateLimitThrottle, client: @client
31
+ f.use Middleware::Authentication, client: @client
32
+ f.use Middleware::RiotErrors, client: @client
33
+ f.use Middleware::RateLimitObserve, client: @client
34
+ f.response :json, content_type: /\bjson$/
35
+ f.adapter @client.adapter
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ class AccountV1 < Base
6
+ ROUTING = :regional
7
+
8
+ def by_riot_id(game_name, tag_line, region: nil)
9
+ Models::Account.from_api(
10
+ get("/riot/account/v1/accounts/by-riot-id/#{escape(game_name)}/#{escape(tag_line)}", region)
11
+ )
12
+ end
13
+
14
+ def by_puuid(puuid, region: nil)
15
+ Models::Account.from_api(
16
+ get("/riot/account/v1/accounts/by-puuid/#{escape(puuid)}", region)
17
+ )
18
+ end
19
+
20
+ def active_shard(game, puuid, region: nil)
21
+ Models::ActiveShard.from_api(
22
+ get("/riot/account/v1/active-shards/by-game/#{escape(game)}/by-puuid/#{escape(puuid)}", region)
23
+ )
24
+ end
25
+
26
+ def region_by_game(game, puuid, region: nil)
27
+ Models::AccountRegion.from_api(
28
+ get("/riot/account/v1/region/by-game/#{escape(game)}/by-puuid/#{escape(puuid)}", region)
29
+ )
30
+ end
31
+
32
+ # Requires the client to be configured with a bearer_token (RSO).
33
+ def me(region: nil)
34
+ Models::Account.from_api(get('/riot/account/v1/accounts/me', region))
35
+ end
36
+
37
+ private
38
+
39
+ def get(path, region)
40
+ # account-v1 has no SEA host; normalize it to ASIA.
41
+ super(path, Routing.regional_for_account(region || @client.region))
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ class Base
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ private
11
+
12
+ def get(path, region = nil, params: {})
13
+ @client.request(:get, path, routing_kind: routing_kind, routing_value: region, params: params).body
14
+ end
15
+
16
+ def post(path, region = nil, params: {}, body: nil)
17
+ @client.request(:post, path, routing_kind: routing_kind, routing_value: region,
18
+ params: params, body: body).body
19
+ end
20
+
21
+ def put(path, region = nil, params: {}, body: nil)
22
+ @client.request(:put, path, routing_kind: routing_kind, routing_value: region,
23
+ params: params, body: body).body
24
+ end
25
+
26
+ def routing_kind
27
+ self.class::ROUTING
28
+ end
29
+
30
+ def escape(segment)
31
+ ERB::Util.url_encode(segment.to_s)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class ChallengesV1 < Base
7
+ ROUTING = :platform
8
+
9
+ def config(region: nil)
10
+ get('/lol/challenges/v1/challenges/config', region)
11
+ end
12
+
13
+ def percentiles(region: nil)
14
+ get('/lol/challenges/v1/challenges/percentiles', region)
15
+ end
16
+
17
+ def leaderboard(challenge_id, level, top: nil, page: nil, region: nil)
18
+ params = {}
19
+ params['top'] = top if top
20
+ params['page'] = page if page
21
+ get("/lol/challenges/v1/challenges/#{escape(challenge_id)}/leaderboards/by-level/#{escape(level)}", region,
22
+ params: params)
23
+ end
24
+
25
+ def player_data(puuid, region: nil)
26
+ get("/lol/challenges/v1/player-data/#{escape(puuid)}", region)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class ChampionMasteryV4 < Base
7
+ ROUTING = :platform
8
+
9
+ def for_puuid(puuid, region: nil)
10
+ get("/lol/champion-mastery/v4/champion-masteries/by-puuid/#{escape(puuid)}", region)
11
+ .map { |hash| Models::ChampionMastery.from_api(hash) }
12
+ end
13
+
14
+ def for_puuid_and_champion(puuid, champion_id, region: nil)
15
+ path = "/lol/champion-mastery/v4/champion-masteries/by-puuid/#{escape(puuid)}" \
16
+ "/by-champion/#{escape(champion_id)}"
17
+ Models::ChampionMastery.from_api(get(path, region))
18
+ end
19
+
20
+ def top_for_puuid(puuid, count: nil, region: nil)
21
+ params = {}
22
+ params['count'] = count if count
23
+ get("/lol/champion-mastery/v4/champion-masteries/by-puuid/#{escape(puuid)}/top", region, params: params)
24
+ .map { |hash| Models::ChampionMastery.from_api(hash) }
25
+ end
26
+
27
+ def score(puuid, region: nil)
28
+ get("/lol/champion-mastery/v4/scores/by-puuid/#{escape(puuid)}", region)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class ChampionV3 < Base
7
+ ROUTING = :platform
8
+
9
+ def rotations(region: nil)
10
+ Models::ChampionInfo.from_api(
11
+ get('/lol/platform/v3/champion-rotations', region)
12
+ )
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class ClashV1 < Base
7
+ ROUTING = :platform
8
+
9
+ def players_by_summoner_id(summoner_id, region: nil)
10
+ get("/lol/clash/v1/players/by-summoner/#{escape(summoner_id)}", region)
11
+ end
12
+
13
+ def team(team_id, region: nil)
14
+ get("/lol/clash/v1/teams/#{escape(team_id)}", region)
15
+ end
16
+
17
+ def tournaments(region: nil)
18
+ get('/lol/clash/v1/tournaments', region)
19
+ end
20
+
21
+ def tournament_by_team(team_id, region: nil)
22
+ get("/lol/clash/v1/tournaments/by-team/#{escape(team_id)}", region)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class LeagueV4 < Base
7
+ ROUTING = :platform
8
+
9
+ def challenger(queue, region: nil)
10
+ Models::LeagueList.from_api(
11
+ get("/lol/league/v4/challengerleagues/by-queue/#{escape(queue)}", region)
12
+ )
13
+ end
14
+
15
+ def grandmaster(queue, region: nil)
16
+ Models::LeagueList.from_api(
17
+ get("/lol/league/v4/grandmasterleagues/by-queue/#{escape(queue)}", region)
18
+ )
19
+ end
20
+
21
+ def master(queue, region: nil)
22
+ Models::LeagueList.from_api(
23
+ get("/lol/league/v4/masterleagues/by-queue/#{escape(queue)}", region)
24
+ )
25
+ end
26
+
27
+ def entries_by_summoner_id(summoner_id, region: nil)
28
+ get("/lol/league/v4/entries/by-summoner/#{escape(summoner_id)}", region)
29
+ .map { |hash| Models::LeagueEntry.from_api(hash) }
30
+ end
31
+
32
+ def entries(tier, division, page: nil, region: nil)
33
+ params = {}
34
+ params['page'] = page if page
35
+ get("/lol/league/v4/entries/#{escape(tier)}/#{escape(division)}", region, params: params)
36
+ .map { |hash| Models::LeagueEntry.from_api(hash) }
37
+ end
38
+
39
+ def league(league_id, region: nil)
40
+ Models::LeagueList.from_api(
41
+ get("/lol/league/v4/leagues/#{escape(league_id)}", region)
42
+ )
43
+ end
44
+ end
45
+
46
+ class LeagueExpV4 < Base
47
+ ROUTING = :platform
48
+
49
+ def entries(queue, tier, division, page: nil, region: nil)
50
+ params = {}
51
+ params['page'] = page if page
52
+ get("/lol/league-exp/v4/entries/#{escape(queue)}/#{escape(tier)}/#{escape(division)}", region, params: params)
53
+ .map { |hash| Models::LeagueEntry.from_api(hash) }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rito
4
+ module Endpoints
5
+ module Lol
6
+ class MatchV5 < Base
7
+ ROUTING = :regional
8
+
9
+ def by_id(match_id, region: nil)
10
+ Models::Match.from_api(
11
+ get("/lol/match/v5/matches/#{escape(match_id)}", region)
12
+ )
13
+ end
14
+
15
+ def ids_by_puuid(puuid, region: nil, start: nil, count: nil, queue: nil,
16
+ type: nil, start_time: nil, end_time: nil)
17
+ params = {}
18
+ params['start'] = start if start
19
+ params['count'] = count if count
20
+ params['queue'] = queue if queue
21
+ params['type'] = type if type
22
+ params['startTime'] = start_time if start_time
23
+ params['endTime'] = end_time if end_time
24
+
25
+ get("/lol/match/v5/matches/by-puuid/#{escape(puuid)}/ids", region, params: params)
26
+ end
27
+
28
+ def timeline_by_id(match_id, region: nil)
29
+ get("/lol/match/v5/matches/#{escape(match_id)}/timeline", region)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end