sleeper_api 1.1.0 → 1.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e64262b5b1ec981daba5a470cdaed3857b5b334b4b5b974b36369bb71d10fe6
4
- data.tar.gz: 6e292f1ff2de695f2385736316d1d0329373cdfb8d944d399e42ffcda7014d2d
3
+ metadata.gz: 49f189b10709caa46c846f8733372cfd50d1dff0f66548aba5cb7ce0d32508f5
4
+ data.tar.gz: a0670835fa5f56541d041292b498722d0597a0599c724e95f9e3ed193151872c
5
5
  SHA512:
6
- metadata.gz: fcad44e534d0f99daa36897d56b228e432e5374d9e829915fed7cc71612588b9576a96147cedb07cc658cd0a590769161ccd74ef82f48ed7d1b0c2d7dc210e88
7
- data.tar.gz: ca0a00e724c6b35182add239a7a80c9b8129c3a1af2805f216f21b50971842fa968a1c902ab97686819c676390ef89e3fa0fb4635013d9f3f8f7c5aec565d7e6
6
+ metadata.gz: dd18ff49145f5c1848857f7af5e9b15f02a8aac6f7940fe85517d333a213707f524d3f54d5d211ce94de28be9e955e6e366a3db66101ce329d39264f6eabf983
7
+ data.tar.gz: 0b254fa2078732333ee53f3f1074f3700c85c28733478234cd3c303b6b2698967889ad2db33d9802b1a93d00d7dee378387bfdb1d18403f55d0104daedc934b1
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ ## [1.2.0] - 2026-08-23
2
+
3
+ ### Added
4
+
5
+ - `Client#schedule(season, season_type:, sport:)` — a season's game list, each entry `{status, date, home, away, week, game_id}`. A team's bye week is the week it appears in no game, which derives exactly: checked against 2024, 2025 and 2026, every one gives exactly one bye per team. Note `pre` (weeks 1-3) and `post` (weeks 1-4) restart week numbering, so games from different season types must never be pooled, and a season Sleeper has not scheduled yet answers 200 with `[]` rather than 404.
6
+
7
+ ### Changed
8
+
9
+ - **`base_uri` is now the bare host, `https://api.sleeper.app`, and every path carries its own `/v1`.** The schedule endpoint is served from the host root, so while the version lived in `base_uri` it was unreachable at any path a caller could pass to `make_request`. Moving the version into the paths means one mechanism for every endpoint rather than an escape hatch for the exceptions.
10
+
11
+ **This changes the text of `SleeperApi::Error`**, which quotes the path it failed on: `"Failed to fetch /user/x: 404"` is now `"Failed to fetch /v1/user/x: 404"`. Anything matching on that string needs updating — though matching on it was never sound, since the same error covers a missing user, a 5xx and a timeout alike.
12
+
1
13
  ## [1.1.0] - 2026-08-22
2
14
 
3
15
  ### Fixed
data/CLAUDE.md CHANGED
@@ -26,7 +26,9 @@ CI (`.github/workflows/ci.yml`) runs `bundle exec rake ci` on Ruby 3.2 only. The
26
26
  Four layers, with a deliberate split between HTTP and modeling:
27
27
 
28
28
  - **`SleeperApi`** (`lib/sleeper_api.rb`) — module-level config + memoized global `SleeperApi.client`. `Configuration` validates `timeout` (10–60) and `retries` (0–5), raising `SleeperApi::Error` outside those bounds.
29
- - **`Client`** — the only thing that talks HTTP. `include HTTParty` with `base_uri "https://api.sleeper.app/v1"`. Every call funnels through the private `make_request`, which handles retry-on-timeout, logging, and converts non-2xx into `SleeperApi::Error`. It also owns the 24-hour in-memory player cache.
29
+ - **`Client`** — the only thing that talks HTTP. `include HTTParty` with `base_uri "https://api.sleeper.app"` **the bare host; the `/v1` lives in each path**. That is deliberate and load-bearing: not every Sleeper endpoint is versioned. `/schedule/{sport}/{season_type}/{season}` is served from the host root, and while `base_uri` carried the version that endpoint was unreachable at any path a caller could pass in. A new endpoint spells out where it lives; do not move the version back into `base_uri` to shorten the paths.
30
+
31
+ Every call funnels through the private `make_request`, which handles retry-on-timeout, logging, and converts non-2xx into `SleeperApi::Error`. **That error quotes the path**, so the path prefix is part of a public string — v1.2.0 changed it from `"Failed to fetch /user/x: 404"` to `"Failed to fetch /v1/user/x: 404"`. `Client` also owns the 24-hour in-memory player cache.
30
32
  - **`League` / `User` / `Draft`** — resource objects. Each takes `(id, client)`, fetches eagerly in the constructor, memoizes into ivars, and exposes formatted hashes.
31
33
  - **`Helpers`** — mixed into all four. `deep_symbolize_keys` plus `player_details`, which reaches through `@client` — so any class including it must define `@client`.
32
34
 
@@ -15,7 +15,11 @@ module SleeperApi
15
15
  include Helpers
16
16
  include HTTParty
17
17
 
18
- base_uri "https://api.sleeper.app/v1"
18
+ # The host only. The API version belongs in the paths because not every
19
+ # endpoint has one: /schedule is served from the root, and while base_uri
20
+ # carried "/v1" that endpoint was unreachable at any path a caller could
21
+ # pass to make_request.
22
+ base_uri "https://api.sleeper.app"
19
23
 
20
24
  # @param config [SleeperApi::Configuration] Client configuration
21
25
  def initialize(config)
@@ -57,7 +61,7 @@ module SleeperApi
57
61
  # @return [Hash] Raw user data
58
62
  # @see https://docs.sleeper.com/#user
59
63
  def get_user(identifier)
60
- make_request("/user/#{identifier}")
64
+ make_request("/v1/user/#{identifier}")
61
65
  end
62
66
 
63
67
  # Get leagues for a user in a specific season.
@@ -68,7 +72,7 @@ module SleeperApi
68
72
  # @return [Array<Hash>] League data
69
73
  # @see https://docs.sleeper.com/#get-all-leagues-for-user
70
74
  def get_user_leagues(user_id, sport: "nfl", season: Time.now.year)
71
- make_request("/user/#{user_id}/leagues/#{sport}/#{season}")
75
+ make_request("/v1/user/#{user_id}/leagues/#{sport}/#{season}")
72
76
  end
73
77
 
74
78
  # Get drafts for a user in a specific season.
@@ -79,7 +83,7 @@ module SleeperApi
79
83
  # @return [Array<Hash>] Draft data
80
84
  # @see https://docs.sleeper.com/#get-all-drafts-for-user
81
85
  def get_user_drafts(user_id, sport: "nfl", season: Time.now.year)
82
- make_request("/user/#{user_id}/drafts/#{sport}/#{season}")
86
+ make_request("/v1/user/#{user_id}/drafts/#{sport}/#{season}")
83
87
  end
84
88
 
85
89
  # Fetch league details.
@@ -88,7 +92,7 @@ module SleeperApi
88
92
  # @return [Hash] League metadata
89
93
  # @see https://docs.sleeper.com/#get-a-specific-league
90
94
  def get_league(league_id)
91
- make_request("/league/#{league_id}")
95
+ make_request("/v1/league/#{league_id}")
92
96
  end
93
97
 
94
98
  # Get all rosters in a league.
@@ -97,7 +101,7 @@ module SleeperApi
97
101
  # @return [Array<Hash>] Roster data
98
102
  # @see https://docs.sleeper.com/#getting-rosters-in-a-league
99
103
  def get_league_rosters(league_id)
100
- make_request("/league/#{league_id}/rosters")
104
+ make_request("/v1/league/#{league_id}/rosters")
101
105
  end
102
106
 
103
107
  # Get all users in a league.
@@ -106,7 +110,7 @@ module SleeperApi
106
110
  # @return [Array<Hash>] User data
107
111
  # @see https://docs.sleeper.com/#getting-users-in-a-league
108
112
  def get_league_users(league_id)
109
- make_request("/league/#{league_id}/users")
113
+ make_request("/v1/league/#{league_id}/users")
110
114
  end
111
115
 
112
116
  # Get matchups for a specific week.
@@ -116,7 +120,7 @@ module SleeperApi
116
120
  # @return [Array<Hash>] Matchup data
117
121
  # @see https://docs.sleeper.com/#getting-matchups-in-a-league
118
122
  def get_league_matchups(league_id, week)
119
- make_request("/league/#{league_id}/matchups/#{week}")
123
+ make_request("/v1/league/#{league_id}/matchups/#{week}")
120
124
  end
121
125
 
122
126
  # Get playoff winners bracket.
@@ -125,7 +129,7 @@ module SleeperApi
125
129
  # @return [Array<Hash>] Bracket matchups
126
130
  # @see https://docs.sleeper.com/#getting-the-playoff-bracket
127
131
  def get_playoff_bracket(league_id)
128
- make_request("/league/#{league_id}/winners_bracket")
132
+ make_request("/v1/league/#{league_id}/winners_bracket")
129
133
  end
130
134
 
131
135
  # Get toilet bowl (losers bracket).
@@ -134,7 +138,7 @@ module SleeperApi
134
138
  # @return [Array<Hash>] Bracket matchups
135
139
  # @see https://docs.sleeper.com/#getting-the-playoff-bracket
136
140
  def get_toilet_bowl(league_id)
137
- make_request("/league/#{league_id}/losers_bracket")
141
+ make_request("/v1/league/#{league_id}/losers_bracket")
138
142
  end
139
143
 
140
144
  # Get transactions for a specific week.
@@ -144,7 +148,7 @@ module SleeperApi
144
148
  # @return [Array<Hash>] Transaction data
145
149
  # @see https://docs.sleeper.com/#get-transactions
146
150
  def get_transactions(league_id, week)
147
- make_request("/league/#{league_id}/transactions/#{week}")
151
+ make_request("/v1/league/#{league_id}/transactions/#{week}")
148
152
  end
149
153
 
150
154
  # Get league drafts.
@@ -153,7 +157,7 @@ module SleeperApi
153
157
  # @return [Array<Hash>] Draft data
154
158
  # @see https://docs.sleeper.com/#get-all-drafts-for-a-league
155
159
  def get_league_drafts(league_id)
156
- make_request("/league/#{league_id}/drafts")
160
+ make_request("/v1/league/#{league_id}/drafts")
157
161
  end
158
162
 
159
163
  # Get traded draft picks for a league.
@@ -162,7 +166,7 @@ module SleeperApi
162
166
  # @return [Array<Hash>] Traded picks
163
167
  # @see https://docs.sleeper.com/#get-traded-picks-in-a-draft
164
168
  def get_league_traded_picks(league_id)
165
- make_request("/league/#{league_id}/traded_picks")
169
+ make_request("/v1/league/#{league_id}/traded_picks")
166
170
  end
167
171
 
168
172
  # Fetch draft details.
@@ -171,7 +175,7 @@ module SleeperApi
171
175
  # @return [Hash] Draft metadata
172
176
  # @see https://docs.sleeper.com/#get-a-specific-draft
173
177
  def get_draft(draft_id)
174
- make_request("/draft/#{draft_id}")
178
+ make_request("/v1/draft/#{draft_id}")
175
179
  end
176
180
 
177
181
  # Get draft picks.
@@ -180,7 +184,7 @@ module SleeperApi
180
184
  # @return [Array<Hash>] Pick data
181
185
  # @see https://docs.sleeper.com/#get-all-picks-in-a-draft
182
186
  def get_draft_picks(draft_id)
183
- make_request("/draft/#{draft_id}/picks")
187
+ make_request("/v1/draft/#{draft_id}/picks")
184
188
  end
185
189
 
186
190
  # Get traded draft picks for a draft.
@@ -189,7 +193,7 @@ module SleeperApi
189
193
  # @return [Array<Hash>] Traded picks
190
194
  # @see https://docs.sleeper.com/#get-traded-picks-in-a-draft
191
195
  def get_draft_traded_picks(draft_id)
192
- make_request("/draft/#{draft_id}/traded_picks")
196
+ make_request("/v1/draft/#{draft_id}/traded_picks")
193
197
  end
194
198
 
195
199
  # Get NFL state (week, season status).
@@ -198,13 +202,36 @@ module SleeperApi
198
202
  # @return [Hash] State data
199
203
  # @see https://docs.sleeper.com/#get-nfl-state
200
204
  def get_nfl_state(sport = "nfl")
201
- nfl_state = make_request("/state/#{sport}")
205
+ nfl_state = make_request("/v1/state/#{sport}")
202
206
  nfl_state.each_with_object({}) do |(k, v), result|
203
207
  key = k.is_a?(String) ? k.to_sym : k
204
208
  result[key] = v
205
209
  end
206
210
  end
207
211
 
212
+ # Get a season's game schedule.
213
+ #
214
+ # Undocumented, and served from the host root rather than /v1 — hence the
215
+ # version living in the paths rather than in base_uri.
216
+ #
217
+ # Returns a flat array of games, each `{status, date, home, away, week,
218
+ # game_id}`. A team's bye week is the week it appears in no game; that
219
+ # derives exactly, but only within one season type — `pre` (weeks 1-3) and
220
+ # `post` (weeks 1-4) restart week numbering, so games from different season
221
+ # types must never be pooled.
222
+ #
223
+ # A season Sleeper has not scheduled yet answers 200 with an empty array
224
+ # rather than 404, so an empty result is a legitimate answer and not an
225
+ # error.
226
+ #
227
+ # @param season [Integer, String] Season year, e.g. 2026
228
+ # @param season_type [String] "regular" (default), "pre", or "post"
229
+ # @param sport [String] Sport code (default: "nfl")
230
+ # @return [HTTParty::Response] Array of games
231
+ def schedule(season, season_type: "regular", sport: "nfl")
232
+ make_request("/schedule/#{sport}/#{season_type}/#{season}")
233
+ end
234
+
208
235
  # Get trending players.
209
236
  #
210
237
  # @param sport [String] Sport code (default: "nfl")
@@ -214,7 +241,7 @@ module SleeperApi
214
241
  # @return [Array<Hash>] Trending players
215
242
  # @see https://docs.sleeper.com/#trending-players
216
243
  def trending_players(sport = "nfl", type: "add", lookback_hours: 24, limit: 25)
217
- make_request("/players/#{sport}/trending/#{type}?lookback_hours=#{lookback_hours}&limit=#{limit}")
244
+ make_request("/v1/players/#{sport}/trending/#{type}?lookback_hours=#{lookback_hours}&limit=#{limit}")
218
245
  end
219
246
 
220
247
  # Get all player data (cached for 24 hours).
@@ -225,7 +252,7 @@ module SleeperApi
225
252
  def get_players(sport = "nfl")
226
253
  return @players_cache if @players_cache && @cache_timestamp && (Time.now - @cache_timestamp) < (3600 * 24)
227
254
 
228
- response = make_request("/players/#{sport}")
255
+ response = make_request("/v1/players/#{sport}")
229
256
  @players_cache = response.parsed_response
230
257
  @cache_timestamp = Time.now
231
258
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SleeperApi
4
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sleeper_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eruity1