sleeper_api 1.6.0 → 1.8.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 +4 -4
- data/CHANGELOG.md +26 -0
- data/CLAUDE.md +1 -1
- data/README.md +13 -1
- data/lib/sleeper_api/client.rb +34 -1
- data/lib/sleeper_api/version.rb +1 -1
- data/lib/sleeper_api.rb +3 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: da00a42dc3d3fa73feab8e1c2278f0cdcf7a274b12709c540c2f988782828269
|
|
4
|
+
data.tar.gz: 8b2fc35f6dd3a3b546cafae1679ac0dbca75193d7886fcb12b57c5bf616da667
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c953ad4e95e986db6ef5f6f559a7cf464a9cdeaf98ccf83e4cb25f1e99008152066e5b15ad7b852de444a13fafd81b795d6b338b5ced2cebe3e9710223aa966a
|
|
7
|
+
data.tar.gz: 4ccdabb09c1bd25a39e7f32ce6cd97c58b5237b8c18f9a030aa3d9307f26b0f736cd63cf6f3f9cfb6381305aa0f9b0b8cc038431f06bd52d37f3c74bb5edb75d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,29 @@
|
|
|
1
|
+
## [1.8.0] - 2026-10-02
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- **`Client#player_news(player_id, sport: "nfl", limit: 10)`** fetches one
|
|
6
|
+
player's recent news from the undocumented
|
|
7
|
+
`api.sleeper.com/players/{sport}/{id}/news`, newest first: RotoWire,
|
|
8
|
+
FantasyPros and RotoBaller items with a `metadata` title, description and
|
|
9
|
+
usually an analysis. Measured 2026-10-02: Sleeper returns at most 10 whatever
|
|
10
|
+
the limit, there is no paging, and an unknown id answers `200` with `[]`. The
|
|
11
|
+
path exists on the web host only.
|
|
12
|
+
|
|
13
|
+
## [1.7.0] - 2026-10-02
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- **`Client#player(player_id, sport: "nfl")`** fetches one player from the
|
|
18
|
+
undocumented `/v1/players/{sport}/{id}`: the same fields as a catalog row, in
|
|
19
|
+
about 1.2 KB rather than the 14.6 MB `#get_players` downloads. It is live and
|
|
20
|
+
uncached, so it is the way to read an `injury_status` or `depth_chart_order`
|
|
21
|
+
fresher than a nightly catalog.
|
|
22
|
+
- **`SleeperApi::PlayerNotFound`, a subclass of `SleeperApi::Error`.** An
|
|
23
|
+
unknown player id is a `404`, checked live 2026-10-02, unlike an unknown
|
|
24
|
+
user's `200` and `null`. Any other failure is still a plain
|
|
25
|
+
`SleeperApi::Error`.
|
|
26
|
+
|
|
1
27
|
## [1.6.0] - 2026-09-28
|
|
2
28
|
|
|
3
29
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -70,7 +70,7 @@ Four layers, with a deliberate split between HTTP and modeling:
|
|
|
70
70
|
|
|
71
71
|
**Guard nil defensively.** Sleeper omits fields freely — users without `metadata`, rosters without `players`, matchups without `points`. Real leagues hit these; the spec fixtures often don't. Use `&.dig` rather than `[]` on anything nested off an API response.
|
|
72
72
|
|
|
73
|
-
**Never fan out `get_players`.** It's a multi-megabyte payload of every NFL player. It's cached for 24h in an ivar on the client instance — which means the cache dies with the client. Consumers holding a short-lived client re-download it every time.
|
|
73
|
+
**Never fan out `get_players`.** It's a multi-megabyte payload of every NFL player. It's cached for 24h in an ivar on the client instance — which means the cache dies with the client. Consumers holding a short-lived client re-download it every time. For one player, `#player(id)` fetches `/v1/players/nfl/{id}` live (~1.2 KB, undocumented, uncached); an unknown id is a **404** there, not the `200`/`null` an unknown user gets, and becomes `PlayerNotFound`. `#player_news(id)` is that player's news on `WEB_HOST` only (`.app` 404s the path): at most 10 items whatever `limit` says, and an unknown id is `200` with `[]`, not a 404.
|
|
74
74
|
|
|
75
75
|
### Undocumented endpoints carry undocumented vocabularies
|
|
76
76
|
|
data/README.md
CHANGED
|
@@ -243,10 +243,20 @@ Access player data with automatic caching:
|
|
|
243
243
|
# Get all players (cached for 24 hours)
|
|
244
244
|
players = client.get_players
|
|
245
245
|
|
|
246
|
-
# Find specific player
|
|
246
|
+
# Find specific player (reads the cached catalog above)
|
|
247
247
|
player = client.get_player_by_id("1234")
|
|
248
248
|
puts "#{player['first_name']} #{player['last_name']} - #{player['position']}"
|
|
249
249
|
|
|
250
|
+
# One player, live and uncached: ~1.2 KB instead of the whole catalog.
|
|
251
|
+
# Use it for a fresher injury_status or depth_chart_order than the catalog has.
|
|
252
|
+
fresh = client.player("1234")
|
|
253
|
+
puts "#{fresh['injury_status']} (#{fresh['injury_body_part']})"
|
|
254
|
+
|
|
255
|
+
# One player's recent news, newest first (at most 10, from api.sleeper.com)
|
|
256
|
+
client.player_news("1234").each do |item|
|
|
257
|
+
puts "#{item['source']}: #{item.dig('metadata', 'title')}"
|
|
258
|
+
end
|
|
259
|
+
|
|
250
260
|
# Get trending players
|
|
251
261
|
trending_adds = client.trending_players(type: "add", limit: 10)
|
|
252
262
|
trending_drops = client.trending_players(type: "drop", limit: 10)
|
|
@@ -370,6 +380,8 @@ end
|
|
|
370
380
|
|
|
371
381
|
- SleeperApi::UserNotFound - a subclass of SleeperApi::Error: no Sleeper user has that identifier. Permanent, so rescue it before SleeperApi::Error if you retry the rest
|
|
372
382
|
|
|
383
|
+
- SleeperApi::PlayerNotFound - a subclass of SleeperApi::Error: `client.player` was given an id Sleeper does not have. Permanent, like UserNotFound
|
|
384
|
+
|
|
373
385
|
- ArgumentError - Invalid parameters passed to methods
|
|
374
386
|
|
|
375
387
|
## Performance Considerations
|
data/lib/sleeper_api/client.rb
CHANGED
|
@@ -472,6 +472,35 @@ module SleeperApi
|
|
|
472
472
|
get_players(sport)[player_id]
|
|
473
473
|
end
|
|
474
474
|
|
|
475
|
+
# Fetch one player, live: about 1.2 KB where #get_players is 14.6 MB, and
|
|
476
|
+
# not cached. Undocumented; same fields as a catalog row.
|
|
477
|
+
#
|
|
478
|
+
# Sleeper answers an unknown id with 404, unlike an unknown user's 200 and
|
|
479
|
+
# null, and that 404 becomes {SleeperApi::PlayerNotFound}.
|
|
480
|
+
#
|
|
481
|
+
# @param player_id [String] Player ID
|
|
482
|
+
# @param sport [String] Sport code (default: "nfl")
|
|
483
|
+
# @return [HTTParty::Response] The player's raw data
|
|
484
|
+
# @raise [SleeperApi::PlayerNotFound] If no player has that ID
|
|
485
|
+
def player(player_id, sport: "nfl")
|
|
486
|
+
make_request(path("v1", "players", sport, player_id),
|
|
487
|
+
not_found: -> { PlayerNotFound.new("No Sleeper player #{player_id.to_s.inspect}") })
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
# One player's recent news, newest first: RotoWire, FantasyPros and
|
|
491
|
+
# RotoBaller items, each with a `metadata` title, description and usually
|
|
492
|
+
# an analysis. Undocumented and on WEB_HOST only; Sleeper returns at most
|
|
493
|
+
# 10 whatever the limit, and an unknown id answers 200 with [].
|
|
494
|
+
#
|
|
495
|
+
# @param player_id [String] Player ID
|
|
496
|
+
# @param sport [String] Sport code (default: "nfl")
|
|
497
|
+
# @param limit [Integer] How many items, up to 10
|
|
498
|
+
# @return [HTTParty::Response] The items, newest first
|
|
499
|
+
def player_news(player_id, sport: "nfl", limit: 10)
|
|
500
|
+
query = URI.encode_www_form(limit: limit)
|
|
501
|
+
make_request("#{path("players", sport, player_id, "news")}?#{query}", host: WEB_HOST)
|
|
502
|
+
end
|
|
503
|
+
|
|
475
504
|
private
|
|
476
505
|
|
|
477
506
|
# Every request path is built here, from escaped segments. An unescaped
|
|
@@ -503,9 +532,11 @@ module SleeperApi
|
|
|
503
532
|
#
|
|
504
533
|
# @param path [String] API endpoint path
|
|
505
534
|
# @param host [String, nil] a different host, e.g. WEB_HOST
|
|
535
|
+
# @param not_found [Proc, nil] builds the error a 404 raises, for an
|
|
536
|
+
# endpoint where 404 means "no such thing" rather than a failure
|
|
506
537
|
# @return [HTTParty::Response]
|
|
507
538
|
# @raise [SleeperApi::Error] On HTTP errors or timeouts
|
|
508
|
-
def make_request(path, host: nil)
|
|
539
|
+
def make_request(path, host: nil, not_found: nil)
|
|
509
540
|
named = host ? "#{host}#{path}" : path
|
|
510
541
|
options = { timeout: @config.timeout }
|
|
511
542
|
options[:base_uri] = host if host
|
|
@@ -519,6 +550,8 @@ module SleeperApi
|
|
|
519
550
|
response
|
|
520
551
|
else
|
|
521
552
|
@config.logger&.error("Failed to fetch #{named}: #{response.code}")
|
|
553
|
+
raise not_found.call if not_found && response.code == 404
|
|
554
|
+
|
|
522
555
|
raise SleeperApi::Error, "Failed to fetch #{named}: #{response.code}"
|
|
523
556
|
end
|
|
524
557
|
rescue Net::OpenTimeout, Net::ReadTimeout => e
|
data/lib/sleeper_api/version.rb
CHANGED
data/lib/sleeper_api.rb
CHANGED
|
@@ -13,6 +13,9 @@ module SleeperApi
|
|
|
13
13
|
# Error — retrying will not help — so a caller can rescue it on its own.
|
|
14
14
|
class UserNotFound < Error; end
|
|
15
15
|
|
|
16
|
+
# The id names no Sleeper player. Permanent, like UserNotFound.
|
|
17
|
+
class PlayerNotFound < Error; end
|
|
18
|
+
|
|
16
19
|
class << self
|
|
17
20
|
attr_writer :configuration
|
|
18
21
|
end
|