sleeper_api 1.0.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.
@@ -0,0 +1,399 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SleeperApi
4
+ class League
5
+ include Helpers
6
+
7
+ # League attributes from the API.
8
+ ATTRIBUTES = %w[name league_id total_rosters status sport settings season_type season scoring_settings
9
+ roster_positions previous_league_id draft_id bracket_id bracket_overrides_id loser_bracket_id
10
+ loser_bracket_overrides_id group_id avatar company_id shard last_message_id last_author_avatar
11
+ last_author_display_name last_author_id last_author_is_bot last_message_attachment
12
+ last_message_text_map last_message_time last_pinned_message_id last_read_id metadata].freeze
13
+
14
+ attr_reader :league_id, :weeks
15
+
16
+ # @param league_id [String] League identifier
17
+ # @param client [SleeperApi::Client] HTTP client instance
18
+ # @param no_data [Boolean] Skip initial data fetch (default: false)
19
+ # @raise [ArgumentError] If league_id is empty
20
+ def initialize(league_id, client, no_data: false)
21
+ raise ArgumentError, "league_id must be a non-empty string" if league_id.to_s.empty?
22
+
23
+ @league_id = league_id
24
+ @client = client
25
+ @weeks = 1..17
26
+ @league_data = nil
27
+ @league_rosters = nil
28
+ @league_users = nil
29
+ @matchups = nil
30
+ @transactions = nil
31
+ @playoff_bracket = nil
32
+ @toilet_bowl = nil
33
+
34
+ fetch_league_data unless no_data
35
+ end
36
+
37
+ # Dynamically define attribute readers for league data.
38
+ ATTRIBUTES.each do |attr|
39
+ define_method(attr) do
40
+ @league_data[attr]
41
+ end
42
+ end
43
+
44
+ # Generate avatar URL from ID.
45
+ #
46
+ # @return [String, nil] Full avatar URL or nil if no avatar
47
+ def avatar_url
48
+ avatar ? "https://sleepercdn.com/avatars/#{avatar}" : nil
49
+ end
50
+
51
+ # Get the reigning champion's roster.
52
+ #
53
+ # @return [Hash, nil] Formatted roster data or nil if no champion data
54
+ def reigning_champ
55
+ roster_id = @league_data&.dig("metadata", "latest_league_winner_roster_id")
56
+ return nil unless roster_id
57
+
58
+ roster_id = roster_id.to_i
59
+ rosters(roster_id: roster_id)
60
+ end
61
+
62
+ # Get all league users (raw data).
63
+ #
64
+ # @return [Array<Hash>] Raw user data from API
65
+ def league_rosters
66
+ fetch_rosters unless @league_rosters
67
+ @league_rosters
68
+ end
69
+
70
+ # Get all matchups across all weeks.
71
+ #
72
+ # @return [Hash{Integer => Array<Hash>}] Week number to matchup data
73
+ def league_users
74
+ fetch_users unless @league_users
75
+ @league_users
76
+ end
77
+
78
+ # Get all matchups across all weeks.
79
+ #
80
+ # @return [Hash{Integer => Array<Hash>}] Week number to matchup data
81
+ def matchups
82
+ fetch_matchups unless @matchups&.keys&.sort == @weeks.to_a.sort
83
+ @matchups
84
+ end
85
+
86
+ # Get formatted rosters with team names, records, and player lists.
87
+ #
88
+ # @param roster_id [Integer, nil] Filter by specific roster
89
+ # @param user_id [String, nil] Filter by user owner
90
+ # @return [Array<Hash>] Formatted roster objects
91
+ #
92
+ # @example Get all rosters
93
+ # rosters = league.rosters
94
+ # roster = rosters.first
95
+ # puts "#{roster[:owner_display_name]}: #{roster[:wins]}-#{roster[:losses]}"
96
+ #
97
+ # @example Get my roster
98
+ # my_roster = league.rosters(user_id: my_user_id)
99
+ def rosters(roster_id: nil, user_id: nil)
100
+ fetch_rosters unless @league_rosters
101
+ fetch_users unless @league_users
102
+
103
+ format_rosters(roster_id: roster_id, user_id: user_id)
104
+ end
105
+
106
+ # Get formatted matchups for a specific week.
107
+ #
108
+ # @param week [Integer] Week number (1-17)
109
+ # @return [Array<Hash>] Matchup data with scoring breakdown
110
+ # @raise [ArgumentError] If week is invalid
111
+ #
112
+ # @example
113
+ # matchups = league.matchups_by_week(week: 5)
114
+ # matchups.each do |matchup|
115
+ # matchup[:rosters].each do |team|
116
+ # puts "#{team[:points]} points from #{team[:starters].length} starters"
117
+ # end
118
+ # end
119
+ def matchups_by_week(week: nil)
120
+ raise ArgumentError, "Week must be between 1 and 17" unless @weeks.include?(week)
121
+
122
+ fetch_matchups([week]) unless @matchups&.key?(week)
123
+ format_matchups(week)
124
+ end
125
+
126
+ # Get formatted league users with team names and commissioner status.
127
+ #
128
+ # @return [Array<Hash>] Formatted user objects
129
+ #
130
+ # @example
131
+ # users = league.users
132
+ # users.each do |user|
133
+ # role = user[:commissioner] ? "(Commissioner)" : ""
134
+ # puts "#{user[:display_name]} #{role}"
135
+ # end
136
+ def users
137
+ fetch_users unless @fetch_users
138
+ format_users
139
+ end
140
+
141
+ # Get formatted transactions for a specific week.
142
+ #
143
+ # @param week [Integer] Week number (1-17)
144
+ # @return [Array<Hash>] Transaction data with adds/drops and draft picks
145
+ # @raise [ArgumentError] If week is invalid
146
+ #
147
+ # @example
148
+ # transactions = league.transactions(week: 5)
149
+ # transactions.each do |tx|
150
+ # puts "#{tx[:type]}: #{tx[:adds]&.length || 0} adds, #{tx[:drops]&.length || 0} drops"
151
+ # end
152
+ def transactions(week: nil)
153
+ raise ArgumentError, "Week must be between 1 and 17" unless @weeks.include?(week)
154
+
155
+ fetch_transactions([week]) unless @transactions&.key?(week)
156
+ format_transactions(week)
157
+ end
158
+
159
+ # Get formatted playoff bracket with team names.
160
+ #
161
+ # @return [Array<Hash>] Bracket matchups with winner/loser team names
162
+ def playoff_bracket
163
+ fetch_playoff_bracket unless @playoff_bracket
164
+ @playoff_bracket
165
+ end
166
+
167
+ # Get formatted toilet bowl (losers bracket) with team names.
168
+ #
169
+ # @return [Array<Hash>] Bracket matchups with winner/loser team names
170
+ def toilet_bowl
171
+ fetch_toilet_bowl unless @toilet_bowl
172
+ @toilet_bowl
173
+ end
174
+
175
+ private
176
+
177
+ def fetch_league_data
178
+ @league_data ||= @client.get_league(@league_id)
179
+ end
180
+
181
+ def fetch_rosters
182
+ @league_rosters ||= @client.get_league_rosters(@league_id)
183
+ end
184
+
185
+ def fetch_users
186
+ @league_users ||= @client.get_league_users(@league_id)
187
+ end
188
+
189
+ def fetch_matchups(weeks = @weeks)
190
+ @matchups ||= {}
191
+ weeks.each do |week|
192
+ next if @matchups[week]
193
+
194
+ @matchups[week] = @client.get_league_matchups(@league_id, week)
195
+ end
196
+ end
197
+
198
+ def fetch_transactions(weeks = @weeks)
199
+ @transactions ||= {}
200
+ weeks.each do |week|
201
+ next if @transactions[week]
202
+
203
+ @transactions[week] = @client.get_transactions(@league_id, week)
204
+ end
205
+ end
206
+
207
+ def fetch_playoff_bracket
208
+ return @playoff_bracket if @playoff_bracket
209
+
210
+ response = @client.get_playoff_bracket(@league_id)
211
+ @playoff_bracket = response.parsed_response.map do |matchup|
212
+ deep_symbolize_keys(matchup).merge(
213
+ team1_owner: users.find do |user|
214
+ user[:user_id] == rosters(roster_id: matchup["t1"])&.first&.dig(:owner_id)
215
+ end&.dig(:team_name),
216
+ team2_owner: users.find do |user|
217
+ user[:user_id] == rosters(roster_id: matchup["t2"])&.first&.dig(:owner_id)
218
+ end&.dig(:team_name),
219
+ winner_owner: if matchup["w"]
220
+ users.find do |user|
221
+ user[:user_id] == rosters(roster_id: matchup["w"])&.first&.dig(:owner_id)
222
+ end&.dig(:team_name)
223
+ end,
224
+ loser_owner: if matchup["l"]
225
+ users.find do |user|
226
+ user[:user_id] == rosters(roster_id: matchup["l"])&.first&.dig(:owner_id)
227
+ end&.dig(:team_name)
228
+ end
229
+ )
230
+ end
231
+ @playoff_bracket
232
+ end
233
+
234
+ def fetch_toilet_bowl
235
+ return @toilet_bowl if @toilet_bowl
236
+
237
+ response = @client.get_toilet_bowl(@league_id)
238
+ @toilet_bowl = response.parsed_response.map do |matchup|
239
+ deep_symbolize_keys(matchup).merge(
240
+ team1_owner: users.find do |u|
241
+ u[:user_id] == rosters(roster_id: matchup["t1"])&.first&.dig(:owner_id)
242
+ end&.dig(:team_name),
243
+ team2_owner: users.find do |u|
244
+ u[:user_id] == rosters(roster_id: matchup["t2"])&.first&.dig(:owner_id)
245
+ end&.dig(:team_name),
246
+ winner_owner: if matchup["w"]
247
+ users.find do |u|
248
+ u[:user_id] == rosters(roster_id: matchup["w"])&.first&.dig(:owner_id)
249
+ end&.dig(:team_name)
250
+ end,
251
+ loser_owner: if matchup["l"]
252
+ users.find do |u|
253
+ u[:user_id] == rosters(roster_id: matchup["l"])&.first&.dig(:owner_id)
254
+ end&.dig(:team_name)
255
+ end
256
+ )
257
+ end
258
+ @toilet_bowl
259
+ end
260
+
261
+ def format_rosters(roster_id: nil, user_id: nil)
262
+ rosters = @league_rosters
263
+
264
+ rosters = rosters.select { |roster| roster["roster_id"] == roster_id } if roster_id
265
+
266
+ rosters = rosters.select { |roster| roster["owner_id"] == user_id } if user_id
267
+
268
+ rosters.map do |roster|
269
+ user = @league_users.find { |user| user["user_id"] == roster["owner_id"] }
270
+ roster_metadata = roster["metadata"]
271
+ roster_settings = roster["settings"]
272
+
273
+ {
274
+ roster_id: roster["roster_id"],
275
+ league_id: roster["league_id"],
276
+ owner_id: roster["owner_id"],
277
+ owner_display_name: user&.dig("display_name") || "Unknown",
278
+ team_name: user&.dig("metadata", "team_name") || "Unknown",
279
+ team_icon: user&.dig("metadata", "avatar"),
280
+ starters: roster["starters"] || [],
281
+ injured_reserve: roster["reserve"] || [],
282
+ taxi: roster["taxi"] || [],
283
+ bench: (roster["players"] || []) - (roster["starters"] || []) - (roster["reserve"] || []) - (roster["taxi"] || []),
284
+ total_points: roster_settings&.dig("fpts"),
285
+ wins: roster_settings&.dig("wins"),
286
+ ties: roster_settings&.dig("ties"),
287
+ losses: roster_settings&.dig("losses"),
288
+ remaining_faab: (@league_data&.dig("settings",
289
+ "waiver_budget") || 0) - (roster_settings&.dig("waiver_budget_used") || 0),
290
+ faab_used: roster_settings&.dig("waiver_budget_used"),
291
+ waiver_position: roster_settings&.dig("waiver_position"),
292
+ streak: roster_metadata&.dig("streak"),
293
+ co_owners: roster["co_owner"],
294
+ keepers: roster["keepers"],
295
+ players_map: roster["player_map"],
296
+ players: roster["players"],
297
+ metadata: roster_metadata.is_a?(Hash) ? roster_metadata.transform_keys(&:to_sym) : roster_metadata,
298
+ settings: roster_settings.is_a?(Hash) ? roster_settings.transform_keys(&:to_sym) : roster_settings
299
+ }
300
+ end
301
+ end
302
+
303
+ def format_matchups(week)
304
+ week_matchups = @matchups[week] || []
305
+ return [] if week_matchups.empty?
306
+
307
+ week_matchups.group_by { |match| match["matchup_id"] }.map do |matchup_id, matchup_entries|
308
+ next unless matchup_id
309
+
310
+ {
311
+ matchup_id: matchup_id,
312
+ rosters: matchup_entries.map do |roster|
313
+ starters = roster["starters"]
314
+
315
+ bench = roster["players"] - starters
316
+ {
317
+ roster_id: roster["roster_id"],
318
+ points: roster["points"],
319
+ custom_points: roster["custom_points"],
320
+ total_points: roster["points"] + (roster["custom_points"] || 0),
321
+ starters: starters,
322
+ bench: bench,
323
+ starter_points: (starters || []).map do |starter_id|
324
+ { starter_id => roster["players_points"]&.dig(starter_id) || 0 }
325
+ end,
326
+ bench_points: bench.map do |bench_player_id|
327
+ { bench_player_id => roster["players_points"]&.dig(bench_player_id) || 0 }
328
+ end
329
+ }
330
+ end
331
+ }
332
+ end
333
+ end
334
+
335
+ def format_users
336
+ (@league_users || []).map do |user|
337
+ user_settings = user["settings"]
338
+ user_metadata = user["metadata"]
339
+
340
+ {
341
+ user_id: user["user_id"],
342
+ username: user["username"],
343
+ display_name: user["display_name"],
344
+ avatar_id: user["avatar"],
345
+ team_name: user_metadata["team_name"],
346
+ commissioner: user["is_owner"],
347
+ is_bot: user["is_bot"],
348
+ metadata: user_metadata.is_a?(Hash) ? user_metadata.transform_keys(&:to_sym) : user_metadata,
349
+ settings: user_settings.is_a?(Hash) ? user_settings.transform_keys(&:to_sym) : user_settings
350
+ }
351
+ end
352
+ end
353
+
354
+ def format_transactions(week)
355
+ (@transactions[week] || []).map do |transaction|
356
+ draft_picks = transaction["draft_picks"]&.map do |pick|
357
+ {
358
+ season: pick["season"],
359
+ round: pick["round"],
360
+ original_roster_id: pick["owner_id"],
361
+ previous_roster_id: pick["previous_owner_id"],
362
+ new_roster_id: pick["owner_id"]
363
+ }
364
+ end || []
365
+ waiver_budget = transaction["waiver_budget"]&.map do |budget|
366
+ {
367
+ amount: budget["amount"],
368
+ receiving_roster: budget["receiver"],
369
+ sending_roster: budget["sender"]
370
+ }
371
+ end || []
372
+
373
+ transaction_metadata = transaction["metadata"]
374
+
375
+ {
376
+ week: week,
377
+ transaction_id: transaction["transaction_id"],
378
+ status: transaction["status"],
379
+ type: transaction["type"],
380
+ created_at: transaction["created"],
381
+ status_updated_at: transaction["status_updated"],
382
+ roster_ids: transaction["roster_ids"] || [],
383
+ adds: transaction["adds"]&.map do |player_id, roster_id|
384
+ { player_id: player_id, roster_id: roster_id }
385
+ end || [],
386
+ drops: transaction["drops"]&.map do |player_id, roster_id|
387
+ { player_id: player_id, roster_id: roster_id }
388
+ end || [],
389
+ waiver_bid: transaction["settings"]&.dig("waiver_bid"),
390
+ waiver_order: transaction["settings"]&.dig("seq"),
391
+ draft_picks: draft_picks,
392
+ waiver_budget: waiver_budget,
393
+ metadata: transaction_metadata.is_a?(Hash) ? transaction_metadata.transform_keys(&:to_sym) : transaction_metadata,
394
+ created_by_user_id: transaction["creator"]
395
+ }
396
+ end
397
+ end
398
+ end
399
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SleeperApi
4
+ class User
5
+ include Helpers
6
+
7
+ # User attributes from the API.
8
+ ATTRIBUTES = %w[username user_id display_name avatar email cookies created currencies data_updated deleted is_bot
9
+ metadata notifications pending phone real_name solicitable summoner_name summoner_region token
10
+ verification].freeze
11
+
12
+ attr_reader :identifier
13
+
14
+ # @param identifier [String, Integer] Username or user ID
15
+ # @param client [SleeperApi::Client] HTTP client instance
16
+ # @raise [ArgumentError] If identifier is empty
17
+ # @raise [SleeperApi::Error] If user data is invalid
18
+ def initialize(identifier, client)
19
+ raise ArgumentError, "identifier must be a non-empty string" if identifier.to_s.empty?
20
+
21
+ @identifier = identifier
22
+ @client = client
23
+ @user_data = nil
24
+ @leagues = nil
25
+ @drafts = nil
26
+
27
+ fetch_user_data
28
+ @user_id = @user_data["user_id"] || raise(SleeperApi::Error, "Invalid user data: user_id not found")
29
+ end
30
+
31
+ # Dynamically define attribute readers for user data.
32
+ ATTRIBUTES.each do |attr|
33
+ define_method(attr) do
34
+ @user_data[attr]
35
+ end
36
+ end
37
+
38
+ # Generate avatar URL from ID.
39
+ #
40
+ # @return [String, nil] Full avatar URL or nil if no avatar
41
+ def avatar_url
42
+ avatar ? "https://sleepercdn.com/avatars/#{avatar}" : nil
43
+ end
44
+
45
+ # Get all leagues for a specific season.
46
+ #
47
+ # @param season [Integer] Season year (default: current year)
48
+ # @return [Array<Hash>] Formatted league objects
49
+ # @raise [ArgumentError] If season is not an integer
50
+ def leagues(season = Time.now.year)
51
+ raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
52
+
53
+ fetch_leagues(season) unless @leagues
54
+ end
55
+
56
+ # Get all rosters for this user across all leagues in a season.
57
+ #
58
+ # @param season [Integer] Season year (default: current year)
59
+ # @return [Array<Hash>] Formatted roster objects from all leagues
60
+ # @raise [ArgumentError] If season is not an integer
61
+ def rosters(season = Time.now.year)
62
+ raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
63
+
64
+ fetch_leagues(season) unless @leagues
65
+ (@leagues || []).flat_map do |league|
66
+ league_instance = League.new(league[:league_id], @client, no_data: true)
67
+ league_instance.rosters(user_id: @user_id)
68
+ end
69
+ end
70
+
71
+ # Get all drafts for a specific season with enhanced metadata.
72
+ #
73
+ # @param season [Integer] Season year (default: current year)
74
+ # @return [Array<Hash>] Formatted draft objects with league info
75
+ # @raise [ArgumentError] If season is not an integer
76
+ def drafts(season = Time.now.year)
77
+ raise ArgumentError, "season must be a valid year" unless season.is_a?(Integer)
78
+
79
+ fetch_drafts(season) unless @drafts
80
+ format_drafts
81
+ end
82
+
83
+ # Get a summary of user's league participation.
84
+ #
85
+ # @param season [Integer] Season year (default: current year)
86
+ # @return [Hash] Summary statistics
87
+ def summary(season = Time.now.year)
88
+ leagues_data = leagues(season)
89
+ rosters_data = rosters(season)
90
+
91
+ {
92
+ season: season,
93
+ total_leagues: leagues_data.length,
94
+ winning_record: rosters_data.select { |r| r[:wins] > r[:losses] },
95
+ total_wins: rosters_data.sum { |r| r[:wins] },
96
+ total_losses: rosters_data.sum { |r| r[:losses] },
97
+ total_ties: rosters_data.sum { |r| r[:ties] },
98
+ avg_record: if rosters_data.any?
99
+ {
100
+ wins: rosters_data.sum { |r| r[:wins].to_f } / rosters_data.length,
101
+ losses: rosters_data.sum { |r| r[:losses].to_f } / rosters_data.length,
102
+ ties: rosters_data.sum { |r| r[:ties].to_f } / rosters_data.length
103
+ }
104
+ end,
105
+ best_team: rosters_data.max_by { |r| r[:wins].to_i - r[:losses].to_i },
106
+ worst_team: rosters_data.min_by { |r| r[:wins].to_i - r[:losses].to_i }
107
+ }
108
+ end
109
+
110
+ private
111
+
112
+ def fetch_user_data
113
+ @user_data ||= @client.get_user(@identifier)
114
+ end
115
+
116
+ def fetch_leagues(season)
117
+ @leagues ||= (@client.get_user_leagues(@user_id, season: season) || []).map do |league|
118
+ deep_symbolize_keys(league)
119
+ end
120
+ end
121
+
122
+ def fetch_drafts(season)
123
+ @drafts ||= (@client.get_user_drafts(@user_id, season: season) || []).map { |draft| deep_symbolize_keys(draft) }
124
+ end
125
+
126
+ def format_drafts
127
+ (@drafts || []).map do |draft|
128
+ draft.merge(
129
+ league_name: draft.dig(:metadata, :name),
130
+ scoring_type: draft.dig(:metadata, :scoring_type),
131
+ total_teams: draft.dig(:settings, :teams),
132
+ rounds: draft.dig(:settings, :rounds)
133
+ )
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SleeperApi
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,87 @@
1
+ require_relative "sleeper_api/version"
2
+ require_relative "sleeper_api/helpers"
3
+ require_relative "sleeper_api/client"
4
+ require_relative "sleeper_api/league"
5
+ require_relative "sleeper_api/user"
6
+ require_relative "sleeper_api/draft"
7
+
8
+ module SleeperApi
9
+ class Error < StandardError; end
10
+
11
+ class << self
12
+ attr_writer :configuration
13
+ end
14
+
15
+ # Configure the gem globally.
16
+ #
17
+ # @yieldparam [SleeperApi::Configuration] config
18
+ # @example
19
+ # SleeperApi.configure do |config|
20
+ # config.timeout = 20
21
+ # config.retries = 5
22
+ # config.logger = Logger.new('sleeper.log')
23
+ # end
24
+ def self.configure
25
+ self.configuration ||= Configuration.new
26
+ yield(configuration)
27
+ end
28
+
29
+ # Get the configured client instance.
30
+ #
31
+ # @return [SleeperApi::Client]
32
+ def self.client
33
+ @client ||= Client.new(configuration)
34
+ end
35
+
36
+ # Get the global configuration.
37
+ #
38
+ # @return [SleeperApi::Configuration]
39
+ def self.configuration
40
+ @configuration ||= Configuration.new
41
+ end
42
+
43
+ # Configuration for SleeperApi client behavior.
44
+ #
45
+ # @attr timeout [Integer] HTTP request timeout (10-60 seconds)
46
+ # @attr retries [Integer] Maximum retry attempts (0-5)
47
+ # @attr logger [Logger, nil] Logger for debugging requests
48
+ class Configuration
49
+ attr_accessor :logger
50
+ attr_reader :timeout, :retries
51
+
52
+ MIN_TIMEOUT = 10
53
+ MAX_TIMEOUT = 60
54
+ MIN_RETRIES = 0
55
+ MAX_RETRIES = 5
56
+
57
+ def initialize
58
+ @timeout = 30
59
+ @retries = 3
60
+ @logger = nil
61
+ end
62
+
63
+ # Set HTTP timeout with validation.
64
+ #
65
+ # @param value [Integer] Timeout in seconds
66
+ # @raise [SleeperApi::Error] If outside valid range
67
+ def timeout=(value)
68
+ unless value.between?(MIN_TIMEOUT, MAX_TIMEOUT)
69
+ raise SleeperApi::Error, "Timeout must be between #{MIN_TIMEOUT} and #{MAX_TIMEOUT} seconds"
70
+ end
71
+
72
+ @timeout = value
73
+ end
74
+
75
+ # Set retry count with validation.
76
+ #
77
+ # @param value [Integer] Number of retries
78
+ # @raise [SleeperApi::Error] If outside valid range
79
+ def retries=(value)
80
+ unless value.between?(MIN_RETRIES, MAX_RETRIES)
81
+ raise SleeperApi::Error, "Retries must be between #{MIN_RETRIES} and #{MAX_RETRIES}"
82
+ end
83
+
84
+ @retries = value
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,4 @@
1
+ module SleeperApi
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/sleeper_api/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "sleeper_api"
7
+ spec.version = SleeperApi::VERSION
8
+ spec.authors = ["Eruity1"]
9
+ spec.email = ["ethanruity@icloud.com"]
10
+
11
+ spec.summary = "Comprehensive Ruby wrapper for the Sleeper's fantasy sports API"
12
+ spec.description = "A comprehensive Ruby gem for interacting with Sleeper's fantasy football API. Features include league management, user profiles, draft data, matchups, transactions, player data with caching, and comprehensive error handling. Built with performance and reliability in mind for production applications."
13
+ spec.homepage = "https://github.com/eruity1/sleeper_api"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
18
+
19
+ spec.metadata["homepage_uri"] = spec.homepage
20
+ spec.metadata["source_code_uri"] = spec.homepage
21
+ spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
22
+ spec.metadata["documentation_uri"] = "#{spec.homepage}/blob/main/README.md"
23
+
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
27
+ all_files = `git ls-files`.split("\n")
28
+ test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
29
+ ci_files = `git ls-files -- .github/*`.split("\n")
30
+
31
+ spec.files = all_files - test_files
32
+ spec.files += ["sig/sleeper_api.rbs"]
33
+
34
+ spec.files -= [
35
+ "players_cache.json",
36
+ "coverage/",
37
+ ".rspec_status",
38
+ ].select { |file| File.exist?(file) }
39
+
40
+ spec.bindir = "exe"
41
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
42
+ spec.require_paths = ["lib"]
43
+
44
+ spec.add_dependency "httparty", "~> 0.21"
45
+
46
+ spec.add_development_dependency "rake", "~> 13.0"
47
+ spec.add_development_dependency "rspec", "~> 3.13"
48
+ spec.add_development_dependency "rubocop", "~> 1.80"
49
+ spec.add_development_dependency "rubocop-performance", "~> 1.26"
50
+ spec.add_development_dependency "rubocop-rspec", "~> 3.7"
51
+ spec.add_development_dependency "simplecov", "~> 0.21"
52
+ spec.add_development_dependency "webmock", "~> 3.14"
53
+ end