sleeper_api 1.8.0 → 1.9.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: da00a42dc3d3fa73feab8e1c2278f0cdcf7a274b12709c540c2f988782828269
4
- data.tar.gz: 8b2fc35f6dd3a3b546cafae1679ac0dbca75193d7886fcb12b57c5bf616da667
3
+ metadata.gz: ea2a84bc8be057968c5822116b20f53d1dac11550c8baf70d437fab4d72b427a
4
+ data.tar.gz: 3c518c6191fc0e117229a10d9ae5f7d1a04d4f8dc62db53c52e8d6af99e6a635
5
5
  SHA512:
6
- metadata.gz: c953ad4e95e986db6ef5f6f559a7cf464a9cdeaf98ccf83e4cb25f1e99008152066e5b15ad7b852de444a13fafd81b795d6b338b5ced2cebe3e9710223aa966a
7
- data.tar.gz: 4ccdabb09c1bd25a39e7f32ce6cd97c58b5237b8c18f9a030aa3d9307f26b0f736cd63cf6f3f9cfb6381305aa0f9b0b8cc038431f06bd52d37f3c74bb5edb75d
6
+ metadata.gz: 5e248beba16cf5d2ebba74570ce4856ddcefa4fa95a8c118e685d2e89ca57eea31268c848bcfc59501b25f40d0bb08bfd8c4f65d4f9f2129f799b5f8d829c053
7
+ data.tar.gz: 060bef1860b827761fdcbfc38e65e0a0a5ec4b1abb6da4e2e52d43416a400e3c574135ed4001363049728cf47f34d64e13465f9cfc00067f1c1ab03cb770e076
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [1.9.0] - 2026-10-09
2
+
3
+ ### Added
4
+
5
+ - **`avatar_url(thumb: true)`** on `User` and `League` returns
6
+ `sleepercdn.com/avatars/thumbs/{id}`: 19 KB of PNG where the full size was
7
+ 2.2 MB of `application/octet-stream` (measured 2026-10-09). The default is
8
+ unchanged.
9
+ - **`sport:` on `User#leagues`, `#rosters`, `#drafts` and `#summary`**, default
10
+ `"nfl"`, passed through to the client, which already took it. Each sport is
11
+ cached apart. Sleeper answers an unknown sport with `200` and `[]` (measured
12
+ 2026-10-09), so a typo reads as "no leagues"; it is not checked against a list.
13
+ - **`League#traded_picks`**, with `Draft#traded_picks`' three filters
14
+ (`original_owner_id:`, `previous_owner_id:`, `current_owner_id:`). `season`
15
+ stays the string Sleeper sends.
16
+ - **`League#drafts`**, as symbol-keyed hashes rather than `Draft` objects, since
17
+ a `Draft` fetches on construction.
18
+
1
19
  ## [1.8.0] - 2026-10-02
2
20
 
3
21
  ### Added
data/README.md CHANGED
@@ -76,6 +76,7 @@ user = SleeperApi.client.user('johndoe')
76
76
  user.username # => "johndoe"
77
77
  user.display_name # => "John Doe"
78
78
  user.avatar_url # => "https://sleepercdn.com/avatars/abc123"
79
+ user.avatar_url(thumb: true) # => "https://sleepercdn.com/avatars/thumbs/abc123"
79
80
  user.is_bot # => false
80
81
 
81
82
  # All leagues for current season
@@ -89,6 +90,9 @@ end
89
90
  old_leagues = user.leagues(2023)
90
91
  championships = old_leagues.select { |l| l[:status] == "finished" }
91
92
 
93
+ # Another sport (default "nfl"). An unknown sport answers [] rather than an error.
94
+ basketball = user.leagues(2026, sport: "nba")
95
+
92
96
  # Get all my rosters across all leagues
93
97
  rosters = user.rosters
94
98
  rosters.each do |roster|
@@ -129,6 +133,7 @@ league.season # => "2024"
129
133
  league.total_rosters # => 12
130
134
  league.status # => "regular"
131
135
  league.avatar_url # => "https://sleepercdn.com/avatars/abc123"
136
+ league.avatar_url(thumb: true) # => "https://sleepercdn.com/avatars/thumbs/abc123"
132
137
 
133
138
  # Formatted rosters (with team names and records)
134
139
  rosters = league.rosters
@@ -176,6 +181,13 @@ toilet_bowl_matchups = league.toilet_bowl
176
181
  matchup = toilet_bowl_matchups.first
177
182
  matchup[:team1_owner] # => "Team Beta"
178
183
  matchup[:winner_owner] # => "Team Beta"
184
+
185
+ # Traded picks (only picks that moved), with the same filters as Draft#traded_picks
186
+ picks = league.traded_picks(current_owner_id: 8)
187
+ picks.first # => { season: "2027", round: 1, roster_id: 1, previous_owner_id: 1, owner_id: 8 }
188
+
189
+ # Drafts, as hashes; open one with SleeperApi.client.draft(id)
190
+ league.drafts.map { |d| d[:status] } # => ["complete"]
179
191
  ```
180
192
 
181
193
  ### Drafts
@@ -30,6 +30,8 @@ module SleeperApi
30
30
  @transactions = nil
31
31
  @playoff_bracket = nil
32
32
  @toilet_bowl = nil
33
+ @traded_picks = nil
34
+ @drafts = nil
33
35
 
34
36
  fetch_league_data unless no_data
35
37
  end
@@ -43,9 +45,15 @@ module SleeperApi
43
45
 
44
46
  # Generate avatar URL from ID.
45
47
  #
46
- # @return [String, nil] Full avatar URL or nil if no avatar
47
- def avatar_url
48
- avatar ? "https://sleepercdn.com/avatars/#{avatar}" : nil
48
+ # The full size was 2.2 MB of `application/octet-stream` and the thumbnail
49
+ # 19 KB of PNG, measured 2026-10-09; a list of avatars wants the thumbnail.
50
+ #
51
+ # @param thumb [Boolean] The thumbnail instead of the full-size image
52
+ # @return [String, nil] Avatar URL or nil if no avatar
53
+ def avatar_url(thumb: false)
54
+ return nil unless avatar
55
+
56
+ thumb ? "https://sleepercdn.com/avatars/thumbs/#{avatar}" : "https://sleepercdn.com/avatars/#{avatar}"
49
57
  end
50
58
 
51
59
  # Get the reigning champion's roster.
@@ -172,8 +180,38 @@ module SleeperApi
172
180
  @toilet_bowl
173
181
  end
174
182
 
183
+ # Get the league's traded draft picks, as Sleeper sends them.
184
+ #
185
+ # `season` is a string ("2027"); every owner is a roster id. A pick that
186
+ # never moved is not listed.
187
+ #
188
+ # @param original_owner_id [Integer, nil] Filter by the roster the pick began with
189
+ # @param previous_owner_id [Integer, nil] Filter by previous owner
190
+ # @param current_owner_id [Integer, nil] Filter by current owner
191
+ # @return [Array<Hash>] Traded picks, symbol-keyed
192
+ def traded_picks(original_owner_id: nil, previous_owner_id: nil, current_owner_id: nil)
193
+ fetch_traded_picks unless @traded_picks
194
+ picks = @traded_picks
195
+ picks = picks.select { |pick| pick[:roster_id] == original_owner_id } if original_owner_id
196
+ picks = picks.select { |pick| pick[:previous_owner_id] == previous_owner_id } if previous_owner_id
197
+ picks = picks.select { |pick| pick[:owner_id] == current_owner_id } if current_owner_id
198
+ picks
199
+ end
200
+
201
+ # Get the league's drafts. Hashes rather than `Draft` objects, because a
202
+ # `Draft` fetches on construction: `client.draft(id)` opens one.
203
+ #
204
+ # @return [Array<Hash>] Drafts, symbol-keyed
205
+ def drafts
206
+ @drafts ||= (@client.get_league_drafts(@league_id) || []).map { |draft| deep_symbolize_keys(draft) }
207
+ end
208
+
175
209
  private
176
210
 
211
+ def fetch_traded_picks
212
+ @traded_picks ||= (@client.get_league_traded_picks(@league_id) || []).map { |pick| deep_symbolize_keys(pick) }
213
+ end
214
+
177
215
  def fetch_league_data
178
216
  @league_data ||= @client.get_league(@league_id)
179
217
  end
@@ -39,31 +39,40 @@ module SleeperApi
39
39
 
40
40
  # Generate avatar URL from ID.
41
41
  #
42
- # @return [String, nil] Full avatar URL or nil if no avatar
43
- def avatar_url
44
- avatar ? "https://sleepercdn.com/avatars/#{avatar}" : nil
42
+ # The full size was 2.2 MB of `application/octet-stream` and the thumbnail
43
+ # 19 KB of PNG, measured 2026-10-09; a list of avatars wants the thumbnail.
44
+ #
45
+ # @param thumb [Boolean] The thumbnail instead of the full-size image
46
+ # @return [String, nil] Avatar URL or nil if no avatar
47
+ def avatar_url(thumb: false)
48
+ return nil unless avatar
49
+
50
+ thumb ? "https://sleepercdn.com/avatars/thumbs/#{avatar}" : "https://sleepercdn.com/avatars/#{avatar}"
45
51
  end
46
52
 
47
53
  # Get all leagues for a specific season.
48
54
  #
49
55
  # @param season [Integer] Season year (default: current year)
56
+ # @param sport [String] Sport code (default: "nfl"). An unknown one answers
57
+ # 200 with [] (measured 2026-10-09), so a typo reads as "no leagues".
50
58
  # @return [Array<Hash>] Formatted league objects
51
59
  # @raise [ArgumentError] If season is not an integer
52
- def leagues(season = Time.now.year)
60
+ def leagues(season = Time.now.year, sport: "nfl")
53
61
  raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
54
62
 
55
- fetch_leagues(season)
63
+ fetch_leagues(season, sport)
56
64
  end
57
65
 
58
66
  # Get all rosters for this user across all leagues in a season.
59
67
  #
60
68
  # @param season [Integer] Season year (default: current year)
69
+ # @param sport [String] Sport code (default: "nfl")
61
70
  # @return [Array<Hash>] Formatted roster objects from all leagues
62
71
  # @raise [ArgumentError] If season is not an integer
63
- def rosters(season = Time.now.year)
72
+ def rosters(season = Time.now.year, sport: "nfl")
64
73
  raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
65
74
 
66
- fetch_leagues(season).flat_map do |league|
75
+ fetch_leagues(season, sport).flat_map do |league|
67
76
  league_instance = League.new(league[:league_id], @client, no_data: true)
68
77
  league_instance.rosters(user_id: @user_id)
69
78
  end
@@ -72,21 +81,23 @@ module SleeperApi
72
81
  # Get all drafts for a specific season with enhanced metadata.
73
82
  #
74
83
  # @param season [Integer] Season year (default: current year)
84
+ # @param sport [String] Sport code (default: "nfl")
75
85
  # @return [Array<Hash>] Formatted draft objects with league info
76
86
  # @raise [ArgumentError] If season is not an integer
77
- def drafts(season = Time.now.year)
87
+ def drafts(season = Time.now.year, sport: "nfl")
78
88
  raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
79
89
 
80
- format_drafts(fetch_drafts(season))
90
+ format_drafts(fetch_drafts(season, sport))
81
91
  end
82
92
 
83
93
  # Get a summary of user's league participation.
84
94
  #
85
95
  # @param season [Integer] Season year (default: current year)
96
+ # @param sport [String] Sport code (default: "nfl")
86
97
  # @return [Hash] Summary statistics
87
- def summary(season = Time.now.year)
88
- leagues_data = leagues(season)
89
- rosters_data = rosters(season)
98
+ def summary(season = Time.now.year, sport: "nfl")
99
+ leagues_data = leagues(season, sport: sport)
100
+ rosters_data = rosters(season, sport: sport)
90
101
 
91
102
  {
92
103
  season: season,
@@ -113,14 +124,15 @@ module SleeperApi
113
124
  @user_data ||= @client.get_user(@identifier)
114
125
  end
115
126
 
116
- def fetch_leagues(season)
117
- @leagues[season] ||= (@client.get_user_leagues(@user_id, season: season) || []).map do |league|
127
+ # Keyed on the sport too, or one sport's answer would serve the other's.
128
+ def fetch_leagues(season, sport)
129
+ @leagues[[sport, season]] ||= (@client.get_user_leagues(@user_id, sport: sport, season: season) || []).map do |league|
118
130
  deep_symbolize_keys(league)
119
131
  end
120
132
  end
121
133
 
122
- def fetch_drafts(season)
123
- @drafts[season] ||= (@client.get_user_drafts(@user_id, season: season) || []).map do |draft|
134
+ def fetch_drafts(season, sport)
135
+ @drafts[[sport, season]] ||= (@client.get_user_drafts(@user_id, sport: sport, season: season) || []).map do |draft|
124
136
  deep_symbolize_keys(draft)
125
137
  end
126
138
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SleeperApi
4
- VERSION = "1.8.0"
4
+ VERSION = "1.9.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.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eruity1