sports-odds-api 1.2.2 → 1.3.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -0
  3. data/README.md +11 -1
  4. data/lib/sports_odds_api/client.rb +28 -1
  5. data/lib/sports_odds_api/internal/transport/base_client.rb +5 -0
  6. data/lib/sports_odds_api/internal/transport/pooled_net_requester.rb +13 -11
  7. data/lib/sports_odds_api/internal/util.rb +61 -10
  8. data/lib/sports_odds_api/models/event.rb +197 -4
  9. data/lib/sports_odds_api/models/event_get_params.rb +22 -4
  10. data/lib/sports_odds_api/models/market.rb +206 -0
  11. data/lib/sports_odds_api/models/market_get_params.rb +150 -0
  12. data/lib/sports_odds_api/models/player_get_params.rb +3 -3
  13. data/lib/sports_odds_api/models/team.rb +107 -2
  14. data/lib/sports_odds_api/models/team_get_params.rb +3 -3
  15. data/lib/sports_odds_api/models.rb +4 -0
  16. data/lib/sports_odds_api/resources/account.rb +1 -0
  17. data/lib/sports_odds_api/resources/events.rb +11 -3
  18. data/lib/sports_odds_api/resources/leagues.rb +3 -1
  19. data/lib/sports_odds_api/resources/markets.rb +87 -0
  20. data/lib/sports_odds_api/resources/players.rb +4 -2
  21. data/lib/sports_odds_api/resources/sports.rb +1 -0
  22. data/lib/sports_odds_api/resources/stats.rb +3 -1
  23. data/lib/sports_odds_api/resources/stream.rb +3 -1
  24. data/lib/sports_odds_api/resources/teams.rb +4 -2
  25. data/lib/sports_odds_api/version.rb +1 -1
  26. data/lib/sports_odds_api.rb +3 -0
  27. data/rbi/sports_odds_api/client.rbi +12 -0
  28. data/rbi/sports_odds_api/internal/util.rbi +29 -1
  29. data/rbi/sports_odds_api/models/event.rbi +387 -3
  30. data/rbi/sports_odds_api/models/event_get_params.rbi +30 -4
  31. data/rbi/sports_odds_api/models/market.rbi +326 -0
  32. data/rbi/sports_odds_api/models/market_get_params.rbi +224 -0
  33. data/rbi/sports_odds_api/models/player_get_params.rbi +4 -4
  34. data/rbi/sports_odds_api/models/team.rbi +186 -3
  35. data/rbi/sports_odds_api/models/team_get_params.rbi +4 -4
  36. data/rbi/sports_odds_api/models.rbi +4 -0
  37. data/rbi/sports_odds_api/resources/account.rbi +1 -0
  38. data/rbi/sports_odds_api/resources/events.rbi +11 -2
  39. data/rbi/sports_odds_api/resources/leagues.rbi +1 -0
  40. data/rbi/sports_odds_api/resources/markets.rbi +79 -0
  41. data/rbi/sports_odds_api/resources/players.rbi +3 -2
  42. data/rbi/sports_odds_api/resources/sports.rbi +1 -0
  43. data/rbi/sports_odds_api/resources/stats.rbi +1 -0
  44. data/rbi/sports_odds_api/resources/stream.rbi +1 -0
  45. data/rbi/sports_odds_api/resources/teams.rbi +3 -2
  46. data/sig/sports_odds_api/client.rbs +2 -0
  47. data/sig/sports_odds_api/internal/util.rbs +14 -0
  48. data/sig/sports_odds_api/models/event.rbs +246 -3
  49. data/sig/sports_odds_api/models/event_get_params.rbs +14 -0
  50. data/sig/sports_odds_api/models/market.rbs +186 -0
  51. data/sig/sports_odds_api/models/market_get_params.rbs +133 -0
  52. data/sig/sports_odds_api/models/team.rbs +130 -3
  53. data/sig/sports_odds_api/models.rbs +4 -0
  54. data/sig/sports_odds_api/resources/events.rbs +2 -0
  55. data/sig/sports_odds_api/resources/markets.rbs +27 -0
  56. metadata +39 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f689a7b1270baa4209b9172d7de7ad334f3931c5dbb7e810724c01502cea09aa
4
- data.tar.gz: f10d47f2bc573bfad258aaa4a14883e05e94e1fb343eaacc50f1ad842b967c59
3
+ metadata.gz: ce905e962b28a44ec834ba7ff8a966df7e8d021dc8394a71bf3386663abc6e60
4
+ data.tar.gz: 6348dd6bac833a96fbfa69ffa87ead1266430e4de7b725589c7cf84dec764e0a
5
5
  SHA512:
6
- metadata.gz: 3a88d1344291e1d8bcc85d3414e38f1f9b16f2d23e9b8ce13ccef14637f5606c556de3054f6efcba69c0b97690fc24331816d16aa5022c7cd2c84ac42a8719de
7
- data.tar.gz: 4ad9da993cb19e8a3ea0398ec730f46d4fb5c71032c69bb481c5900d0b7f7950500f545458b9b6d360ab94ab8c84df4efe232447a960d6163c4e552b0a3962af
6
+ metadata.gz: 87f0ef7c34d0ff1266e9fd949f0d76661ce131bc901f6bfd136ccc10d65ee0fcf83a18455be5aac0c428a5a97b472a5a053e41982bb70995b24e4c8732c62f35
7
+ data.tar.gz: 7999f18438c8422fe9d09bbac7e0001e3b5fe7eb7e9ac83be2d1188ca646caed4b3ead17a41934603123deacb1dcd986eb1912a0ebb870e198cba23b996a98e3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.3.0](https://github.com/SportsGameOdds/sports-odds-api-ruby/compare/v1.2.3...v1.3.0) (2026-07-18)
4
+
5
+
6
+ ### Features
7
+
8
+ * add support for the /markets endpoint ([ce01d75](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/ce01d759933fc8c79d15ae84720da6d0b94eccf3))
9
+ * initial stlc build ([51bb9f0](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/51bb9f0ae4bb9e49d056c0cedebaddb6db207f98))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * declare base64 dependency for Ruby 3.4+ compatibility ([b238e6a](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/b238e6a09ddbbbb7f06e5317a296ad2b8bca5779))
15
+
16
+ ## 1.2.3 (2026-07-08)
17
+
18
+ Full Changelog: [v1.2.2...v1.2.3](https://github.com/SportsGameOdds/sports-odds-api-ruby/compare/v1.2.2...v1.2.3)
19
+
20
+ ### Bug Fixes
21
+
22
+ * calling `break` out of streams should be instantaneous ([537aad0](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/537aad0b2ceb50068372914cba30d0379fc7ec3d))
23
+ * **client:** always add content-length to post body, even when empty ([99718bd](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/99718bd9cebc1fee4c5efb390607345cdb27f281))
24
+ * **client:** loosen json header parsing ([0307d97](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/0307d97a3844180cc3227902b52baeb37d319a86))
25
+ * **docs:** fix mcp installation instructions for remote servers ([e60c40c](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/e60c40ccdca70f2e59548db754db3cb8e72e8cf9))
26
+ * issue where json.parse errors when receiving HTTP 204 with nobody ([bb722ce](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/bb722cee2d0fbadc59bb38ab7fb8c3276ac60654))
27
+
28
+
29
+ ### Chores
30
+
31
+ * **docs:** remove www prefix ([a4bf528](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/a4bf528f53d3fc10396f2f39e4ab122ccc393178))
32
+ * **internal:** codegen related update ([2aebae3](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/2aebae36d92c62daa0156477d60a1a0624f9ab77))
33
+ * **internal:** update `actions/checkout` version ([ab57614](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/ab57614a39b81bf558804846d9bad83e50cb8834))
34
+ * move `cgi` into dependencies for ruby 4 ([0ea92c6](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/0ea92c68f0c0eb91e49103b03ce11531f5f1e99d))
35
+
36
+
37
+ ### Documentation
38
+
39
+ * prominently feature MCP server setup in root SDK readmes ([ff8bb53](https://github.com/SportsGameOdds/sports-odds-api-ruby/commit/ff8bb53a4a14cf7c78b33070e17d483cd60e5cfa))
40
+
3
41
  ## 1.2.2 (2025-11-26)
4
42
 
5
43
  Full Changelog: [v1.2.1...v1.2.2](https://github.com/SportsGameOdds/sports-odds-api-ruby/compare/v1.2.1...v1.2.2)
data/README.md CHANGED
@@ -4,6 +4,16 @@ Get live betting odds, spreads, and totals for NFL, NBA, MLB, and 50 additional
4
4
 
5
5
  [![Gem Version](https://img.shields.io/gem/v/sports-odds-api.svg?label=rubygems%20(stable))](https://rubygems.org/gems/sports-odds-api)
6
6
 
7
+ ## MCP Server
8
+
9
+ Use the Sports Game Odds MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.
10
+
11
+ [![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=sports-odds-api-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsInNwb3J0cy1vZGRzLWFwaS1tY3AiXSwiZW52Ijp7IlNQT1JUU19PRERTX0FQSV9LRVlfSEVBREVSIjoiTXkgQVBJIEtleSBQYXJhbSJ9fQ)
12
+ [![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22sports-odds-api-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22sports-odds-api-mcp%22%5D%2C%22env%22%3A%7B%22SPORTS_ODDS_API_KEY_HEADER%22%3A%22My%20API%20Key%20Param%22%7D%7D)
13
+
14
+ > Note: You may need to set environment variables in your MCP client.
15
+
16
+ ## Documentation
7
17
  This library provides convenient access to the Sports Game Odds REST API from any Ruby 3.2.0+ application.
8
18
 
9
19
  The REST API documentation can be found on [sportsgameodds.com](https://sportsgameodds.com/docs/). The full API of this library can be found in [api.md](api.md).
@@ -26,7 +36,7 @@ The REST API documentation can be found on [sportsgameodds.com](https://sportsga
26
36
  Add to your application's `Gemfile`:
27
37
 
28
38
  ```ruby
29
- gem "sports-odds-api", "~> 1.2.2"
39
+ gem "sports-odds-api", "~> 1.2.3"
30
40
  ```
31
41
 
32
42
  Or install manually:
@@ -23,27 +23,39 @@ module SportsOddsAPI
23
23
  # @return [String, nil]
24
24
  attr_reader :api_key_param
25
25
 
26
+ # Get info about Events (includes odds, results, teams, and other metadata)
26
27
  # @return [SportsOddsAPI::Resources::Events]
27
28
  attr_reader :events
28
29
 
30
+ # Get metadata on supported Markets
31
+ # @return [SportsOddsAPI::Resources::Markets]
32
+ attr_reader :markets
33
+
34
+ # Get Team-related data
29
35
  # @return [SportsOddsAPI::Resources::Teams]
30
36
  attr_reader :teams
31
37
 
38
+ # Get Player-related data
32
39
  # @return [SportsOddsAPI::Resources::Players]
33
40
  attr_reader :players
34
41
 
42
+ # Get League-related data
35
43
  # @return [SportsOddsAPI::Resources::Leagues]
36
44
  attr_reader :leagues
37
45
 
46
+ # Get Sport-related data
38
47
  # @return [SportsOddsAPI::Resources::Sports]
39
48
  attr_reader :sports
40
49
 
50
+ # Get data on specific Stats
41
51
  # @return [SportsOddsAPI::Resources::Stats]
42
52
  attr_reader :stats
43
53
 
54
+ # Get data related to your Account & API key
44
55
  # @return [SportsOddsAPI::Resources::Account]
45
56
  attr_reader :account
46
57
 
58
+ # Get info about Events (includes odds, results, teams, and other metadata)
47
59
  # @return [SportsOddsAPI::Resources::Stream]
48
60
  attr_reader :stream
49
61
 
@@ -88,6 +100,19 @@ module SportsOddsAPI
88
100
  )
89
101
  base_url ||= "https://api.sportsgameodds.com/v2"
90
102
 
103
+ headers = {}
104
+ custom_headers_env = ENV["SPORTS_GAME_ODDS_CUSTOM_HEADERS"]
105
+ unless custom_headers_env.nil?
106
+ parsed = {}
107
+ custom_headers_env.split("\n").each do |line|
108
+ colon = line.index(":")
109
+ unless colon.nil?
110
+ parsed[line[0...colon].strip] = line[(colon + 1)..].strip
111
+ end
112
+ end
113
+ headers = parsed.merge(headers)
114
+ end
115
+
91
116
  @api_key_header = api_key_header&.to_s
92
117
  @api_key_param = api_key_param&.to_s
93
118
 
@@ -96,10 +121,12 @@ module SportsOddsAPI
96
121
  timeout: timeout,
97
122
  max_retries: max_retries,
98
123
  initial_retry_delay: initial_retry_delay,
99
- max_retry_delay: max_retry_delay
124
+ max_retry_delay: max_retry_delay,
125
+ headers: headers
100
126
  )
101
127
 
102
128
  @events = SportsOddsAPI::Resources::Events.new(client: self)
129
+ @markets = SportsOddsAPI::Resources::Markets.new(client: self)
103
130
  @teams = SportsOddsAPI::Resources::Teams.new(client: self)
104
131
  @players = SportsOddsAPI::Resources::Players.new(client: self)
105
132
  @leagues = SportsOddsAPI::Resources::Leagues.new(client: self)
@@ -315,6 +315,11 @@ module SportsOddsAPI
315
315
  SportsOddsAPI::Internal::Util.deep_merge(*[req[:body], opts[:extra_body]].compact)
316
316
  end
317
317
 
318
+ # Generated methods always pass `req[:body]` for operations that define a
319
+ # request body, so only elide the content-type header when the operation
320
+ # has no body at all, not when an optional body param was omitted.
321
+ headers.delete("content-type") if body.nil? && !req.key?(:body)
322
+
318
323
  url = SportsOddsAPI::Internal::Util.join_parsed_uri(
319
324
  @base_url_components,
320
325
  {**req, path: path, query: query}
@@ -75,7 +75,7 @@ module SportsOddsAPI
75
75
 
76
76
  case body
77
77
  in nil
78
- nil
78
+ req["content-length"] ||= 0 unless req["transfer-encoding"]
79
79
  in String
80
80
  req["content-length"] ||= body.bytesize.to_s unless req["transfer-encoding"]
81
81
  req.body_stream = SportsOddsAPI::Internal::Util::ReadIOAdapter.new(body, &blk)
@@ -153,17 +153,19 @@ module SportsOddsAPI
153
153
  end
154
154
 
155
155
  self.class.calibrate_socket_timeout(conn, deadline)
156
- conn.request(req) do |rsp|
157
- y << [req, rsp]
158
- break if finished
159
-
160
- rsp.read_body do |bytes|
161
- y << bytes.force_encoding(Encoding::BINARY)
162
- break if finished
163
-
164
- self.class.calibrate_socket_timeout(conn, deadline)
156
+ ::Kernel.catch(:jump) do
157
+ conn.request(req) do |rsp|
158
+ y << [req, rsp]
159
+ ::Kernel.throw(:jump) if finished
160
+
161
+ rsp.read_body do |bytes|
162
+ y << bytes.force_encoding(Encoding::BINARY)
163
+ ::Kernel.throw(:jump) if finished
164
+
165
+ self.class.calibrate_socket_timeout(conn, deadline)
166
+ end
167
+ eof = true
165
168
  end
166
- eof = true
167
169
  end
168
170
  end
169
171
  ensure
@@ -157,7 +157,7 @@ module SportsOddsAPI
157
157
  in Hash | nil => coerced
158
158
  coerced
159
159
  else
160
- message = "Expected a #{Hash} or #{SportsOddsAPI::Internal::Type::BaseModel}, got #{data.inspect}"
160
+ message = "Expected a #{Hash} or #{SportsOddsAPI::Internal::Type::BaseModel}, got #{input.inspect}"
161
161
  raise ArgumentError.new(message)
162
162
  end
163
163
  end
@@ -237,6 +237,11 @@ module SportsOddsAPI
237
237
  end
238
238
  end
239
239
 
240
+ # @type [Regexp]
241
+ #
242
+ # https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3
243
+ RFC_3986_NOT_PCHARS = /[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/
244
+
240
245
  class << self
241
246
  # @api private
242
247
  #
@@ -247,6 +252,15 @@ module SportsOddsAPI
247
252
  "#{uri.scheme}://#{uri.host}#{":#{uri.port}" unless uri.port == uri.default_port}"
248
253
  end
249
254
 
255
+ # @api private
256
+ #
257
+ # @param path [String, Integer]
258
+ #
259
+ # @return [String]
260
+ def encode_path(path)
261
+ path.to_s.gsub(SportsOddsAPI::Internal::Util::RFC_3986_NOT_PCHARS) { ERB::Util.url_encode(_1) }
262
+ end
263
+
250
264
  # @api private
251
265
  #
252
266
  # @param path [String, Array<String>]
@@ -259,7 +273,7 @@ module SportsOddsAPI
259
273
  in []
260
274
  ""
261
275
  in [String => p, *interpolations]
262
- encoded = interpolations.map { ERB::Util.url_encode(_1) }
276
+ encoded = interpolations.map { encode_path(_1) }
263
277
  format(p, *encoded)
264
278
  end
265
279
  end
@@ -485,11 +499,42 @@ module SportsOddsAPI
485
499
  end
486
500
 
487
501
  # @type [Regexp]
488
- JSON_CONTENT = %r{^application/(?:vnd(?:\.[^.]+)*\+)?json(?!l)}
502
+ JSON_CONTENT = %r{^application/(?:[a-zA-Z0-9.-]+\+)?json(?!l)}
489
503
  # @type [Regexp]
490
504
  JSONL_CONTENT = %r{^application/(:?x-(?:n|l)djson)|(:?(?:x-)?jsonl)}
491
505
 
492
506
  class << self
507
+ # @api private
508
+ #
509
+ # @param query [Hash{Symbol=>Object}]
510
+ #
511
+ # @return [Hash{Symbol=>Object}]
512
+ def encode_query_params(query)
513
+ out = {}
514
+ query.each { write_query_param_element!(out, _1, _2) }
515
+ out
516
+ end
517
+
518
+ # @api private
519
+ #
520
+ # @param collection [Hash{Symbol=>Object}]
521
+ # @param key [String]
522
+ # @param element [Object]
523
+ #
524
+ # @return [nil]
525
+ private def write_query_param_element!(collection, key, element)
526
+ case element
527
+ in Hash
528
+ element.each do |name, value|
529
+ write_query_param_element!(collection, "#{key}[#{name}]", value)
530
+ end
531
+ in Array
532
+ collection[key] = element.map(&:to_s).join(",")
533
+ else
534
+ collection[key] = element.to_s
535
+ end
536
+ end
537
+
493
538
  # @api private
494
539
  #
495
540
  # @param y [Enumerator::Yielder]
@@ -540,16 +585,15 @@ module SportsOddsAPI
540
585
  y << "Content-Disposition: form-data"
541
586
 
542
587
  unless key.nil?
543
- name = ERB::Util.url_encode(key.to_s)
544
- y << "; name=\"#{name}\""
588
+ y << "; name=\"#{key}\""
545
589
  end
546
590
 
547
591
  case val
548
592
  in SportsOddsAPI::FilePart unless val.filename.nil?
549
- filename = ERB::Util.url_encode(val.filename)
593
+ filename = encode_path(val.filename)
550
594
  y << "; filename=\"#{filename}\""
551
595
  in Pathname | IO
552
- filename = ERB::Util.url_encode(::File.basename(val.to_path))
596
+ filename = encode_path(::File.basename(val.to_path))
553
597
  y << "; filename=\"#{filename}\""
554
598
  else
555
599
  end
@@ -566,6 +610,7 @@ module SportsOddsAPI
566
610
  #
567
611
  # @return [Array(String, Enumerable<String>)]
568
612
  private def encode_multipart_streaming(body)
613
+ # rubocop:disable Style/CaseEquality
569
614
  # RFC 1521 Section 7.2.1 says we should have 70 char maximum for boundary length
570
615
  boundary = SecureRandom.urlsafe_base64(46)
571
616
 
@@ -575,7 +620,7 @@ module SportsOddsAPI
575
620
  in Hash
576
621
  body.each do |key, val|
577
622
  case val
578
- in Array if val.all? { primitive?(_1) }
623
+ in Array if val.all? { primitive?(_1) || SportsOddsAPI::Internal::Type::FileInput === _1 }
579
624
  val.each do |v|
580
625
  write_multipart_chunk(y, boundary: boundary, key: key, val: v, closing: closing)
581
626
  end
@@ -591,6 +636,7 @@ module SportsOddsAPI
591
636
 
592
637
  fused_io = fused_enum(strio) { closing.each(&:call) }
593
638
  [boundary, fused_io]
639
+ # rubocop:enable Style/CaseEquality
594
640
  end
595
641
 
596
642
  # @api private
@@ -657,7 +703,8 @@ module SportsOddsAPI
657
703
  def decode_content(headers, stream:, suppress_error: false)
658
704
  case (content_type = headers["content-type"])
659
705
  in SportsOddsAPI::Internal::Util::JSON_CONTENT
660
- json = stream.to_a.join
706
+ return nil if (json = stream.to_a.join).empty?
707
+
661
708
  begin
662
709
  JSON.parse(json, symbolize_names: true)
663
710
  rescue JSON::ParserError => e
@@ -667,7 +714,11 @@ module SportsOddsAPI
667
714
  in SportsOddsAPI::Internal::Util::JSONL_CONTENT
668
715
  lines = decode_lines(stream)
669
716
  chain_fused(lines) do |y|
670
- lines.each { y << JSON.parse(_1, symbolize_names: true) }
717
+ lines.each do
718
+ next if _1.empty?
719
+
720
+ y << JSON.parse(_1, symbolize_names: true)
721
+ end
671
722
  end
672
723
  in %r{^text/event-stream}
673
724
  lines = decode_lines(stream)
@@ -40,6 +40,7 @@ module SportsOddsAPI
40
40
  optional :players, -> { SportsOddsAPI::Internal::Type::HashOf[SportsOddsAPI::Event::Player] }
41
41
 
42
42
  # @!attribute results
43
+ # Nested results in the format `{periodID}.{statEntityID}.{statID} → number`.
43
44
  #
44
45
  # @return [Hash{Symbol=>Hash{Symbol=>Hash{Symbol=>Float}}}, nil]
45
46
  optional :results,
@@ -67,16 +68,27 @@ module SportsOddsAPI
67
68
 
68
69
  # @!method initialize(activity: nil, event_id: nil, info: nil, league_id: nil, manual: nil, odds: nil, players: nil, results: nil, sport_id: nil, status: nil, teams: nil, type: nil)
69
70
  # @param activity [SportsOddsAPI::Models::Event::Activity]
71
+ #
70
72
  # @param event_id [String]
73
+ #
71
74
  # @param info [SportsOddsAPI::Models::Event::Info]
75
+ #
72
76
  # @param league_id [String]
77
+ #
73
78
  # @param manual [Boolean]
79
+ #
74
80
  # @param odds [Hash{Symbol=>SportsOddsAPI::Models::Event::Odd}]
81
+ #
75
82
  # @param players [Hash{Symbol=>SportsOddsAPI::Models::Event::Player}]
76
- # @param results [Hash{Symbol=>Hash{Symbol=>Hash{Symbol=>Float}}}]
83
+ #
84
+ # @param results [Hash{Symbol=>Hash{Symbol=>Hash{Symbol=>Float}}}] Nested results in the format `{periodID}.{statEntityID}.{statID} → number`.
85
+ #
77
86
  # @param sport_id [String]
87
+ #
78
88
  # @param status [SportsOddsAPI::Models::Event::Status]
89
+ #
79
90
  # @param teams [SportsOddsAPI::Models::Event::Teams]
91
+ #
80
92
  # @param type [String]
81
93
 
82
94
  # @see SportsOddsAPI::Models::Event#activity
@@ -98,13 +110,130 @@ module SportsOddsAPI
98
110
 
99
111
  # @see SportsOddsAPI::Models::Event#info
100
112
  class Info < SportsOddsAPI::Internal::Type::BaseModel
113
+ # @!attribute broadcasts
114
+ #
115
+ # @return [Array<SportsOddsAPI::Models::Event::Info::Broadcast>, nil]
116
+ optional :broadcasts, -> { SportsOddsAPI::Internal::Type::ArrayOf[SportsOddsAPI::Event::Info::Broadcast] }
117
+
118
+ # @!attribute referee
119
+ #
120
+ # @return [SportsOddsAPI::Models::Event::Info::Referee, nil]
121
+ optional :referee, -> { SportsOddsAPI::Event::Info::Referee }
122
+
101
123
  # @!attribute season_week
102
124
  #
103
125
  # @return [String, nil]
104
126
  optional :season_week, String, api_name: :seasonWeek
105
127
 
106
- # @!method initialize(season_week: nil)
128
+ # @!attribute venue
129
+ #
130
+ # @return [SportsOddsAPI::Models::Event::Info::Venue, nil]
131
+ optional :venue, -> { SportsOddsAPI::Event::Info::Venue }
132
+
133
+ # @!method initialize(broadcasts: nil, referee: nil, season_week: nil, venue: nil)
134
+ # @param broadcasts [Array<SportsOddsAPI::Models::Event::Info::Broadcast>]
135
+ # @param referee [SportsOddsAPI::Models::Event::Info::Referee]
107
136
  # @param season_week [String]
137
+ # @param venue [SportsOddsAPI::Models::Event::Info::Venue]
138
+
139
+ class Broadcast < SportsOddsAPI::Internal::Type::BaseModel
140
+ # @!attribute broadcaster_id
141
+ #
142
+ # @return [String, nil]
143
+ optional :broadcaster_id, String, api_name: :broadcasterID
144
+
145
+ # @!attribute name
146
+ #
147
+ # @return [String, nil]
148
+ optional :name, String
149
+
150
+ # @!attribute type
151
+ #
152
+ # @return [Symbol, SportsOddsAPI::Models::Event::Info::Broadcast::Type, nil]
153
+ optional :type, enum: -> { SportsOddsAPI::Event::Info::Broadcast::Type }
154
+
155
+ # @!method initialize(broadcaster_id: nil, name: nil, type: nil)
156
+ # @param broadcaster_id [String]
157
+ # @param name [String]
158
+ # @param type [Symbol, SportsOddsAPI::Models::Event::Info::Broadcast::Type]
159
+
160
+ # @see SportsOddsAPI::Models::Event::Info::Broadcast#type
161
+ module Type
162
+ extend SportsOddsAPI::Internal::Type::Enum
163
+
164
+ TV = :tv
165
+ WEBSTREAM = :webstream
166
+ SUBSCRIPTION = :subscription
167
+ SPORTSBOOK = :sportsbook
168
+
169
+ # @!method self.values
170
+ # @return [Array<Symbol>]
171
+ end
172
+ end
173
+
174
+ # @see SportsOddsAPI::Models::Event::Info#referee
175
+ class Referee < SportsOddsAPI::Internal::Type::BaseModel
176
+ # @!attribute name
177
+ #
178
+ # @return [String, nil]
179
+ optional :name, String
180
+
181
+ # @!method initialize(name: nil)
182
+ # @param name [String]
183
+ end
184
+
185
+ # @see SportsOddsAPI::Models::Event::Info#venue
186
+ class Venue < SportsOddsAPI::Internal::Type::BaseModel
187
+ # @!attribute address
188
+ #
189
+ # @return [String, nil]
190
+ optional :address, String
191
+
192
+ # @!attribute capacity
193
+ #
194
+ # @return [Float, nil]
195
+ optional :capacity, Float
196
+
197
+ # @!attribute city
198
+ #
199
+ # @return [String, nil]
200
+ optional :city, String
201
+
202
+ # @!attribute country_code
203
+ #
204
+ # @return [String, nil]
205
+ optional :country_code, String, api_name: :countryCode
206
+
207
+ # @!attribute country_name
208
+ #
209
+ # @return [String, nil]
210
+ optional :country_name, String, api_name: :countryName
211
+
212
+ # @!attribute name
213
+ #
214
+ # @return [String, nil]
215
+ optional :name, String
216
+
217
+ # @!attribute region_code
218
+ #
219
+ # @return [String, nil]
220
+ optional :region_code, String, api_name: :regionCode
221
+
222
+ # @!attribute region_name
223
+ #
224
+ # @return [String, nil]
225
+ optional :region_name, String, api_name: :regionName
226
+
227
+ # @!method initialize(address: nil, capacity: nil, city: nil, country_code: nil, country_name: nil, name: nil, region_code: nil, region_name: nil)
228
+ # @param address [String]
229
+ # @param capacity [Float]
230
+ # @param city [String]
231
+ # @param country_code [String]
232
+ # @param country_name [String]
233
+ # @param name [String]
234
+ # @param region_code [String]
235
+ # @param region_name [String]
236
+ end
108
237
  end
109
238
 
110
239
  class Odd < SportsOddsAPI::Internal::Type::BaseModel
@@ -261,6 +390,21 @@ module SportsOddsAPI
261
390
  # @return [String, nil]
262
391
  optional :bookmaker_id, String, api_name: :bookmakerID
263
392
 
393
+ # @!attribute close_odds
394
+ #
395
+ # @return [String, nil]
396
+ optional :close_odds, String, api_name: :closeOdds
397
+
398
+ # @!attribute close_over_under
399
+ #
400
+ # @return [String, nil]
401
+ optional :close_over_under, String, api_name: :closeOverUnder
402
+
403
+ # @!attribute close_spread
404
+ #
405
+ # @return [String, nil]
406
+ optional :close_spread, String, api_name: :closeSpread
407
+
264
408
  # @!attribute is_main_line
265
409
  #
266
410
  # @return [Boolean, nil]
@@ -276,6 +420,21 @@ module SportsOddsAPI
276
420
  # @return [String, nil]
277
421
  optional :odds, String
278
422
 
423
+ # @!attribute open_odds
424
+ #
425
+ # @return [String, nil]
426
+ optional :open_odds, String, api_name: :openOdds
427
+
428
+ # @!attribute open_over_under
429
+ #
430
+ # @return [String, nil]
431
+ optional :open_over_under, String, api_name: :openOverUnder
432
+
433
+ # @!attribute open_spread
434
+ #
435
+ # @return [String, nil]
436
+ optional :open_spread, String, api_name: :openSpread
437
+
279
438
  # @!attribute over_under
280
439
  #
281
440
  # @return [String, nil]
@@ -286,12 +445,18 @@ module SportsOddsAPI
286
445
  # @return [String, nil]
287
446
  optional :spread, String
288
447
 
289
- # @!method initialize(available: nil, bookmaker_id: nil, is_main_line: nil, last_updated_at: nil, odds: nil, over_under: nil, spread: nil)
448
+ # @!method initialize(available: nil, bookmaker_id: nil, close_odds: nil, close_over_under: nil, close_spread: nil, is_main_line: nil, last_updated_at: nil, odds: nil, open_odds: nil, open_over_under: nil, open_spread: nil, over_under: nil, spread: nil)
290
449
  # @param available [Boolean]
291
450
  # @param bookmaker_id [String]
451
+ # @param close_odds [String]
452
+ # @param close_over_under [String]
453
+ # @param close_spread [String]
292
454
  # @param is_main_line [Boolean]
293
455
  # @param last_updated_at [Time]
294
456
  # @param odds [String]
457
+ # @param open_odds [String]
458
+ # @param open_over_under [String]
459
+ # @param open_spread [String]
295
460
  # @param over_under [String]
296
461
  # @param spread [String]
297
462
  end
@@ -328,19 +493,47 @@ module SportsOddsAPI
328
493
  # @return [String, nil]
329
494
  optional :player_id, String, api_name: :playerID
330
495
 
496
+ # @!attribute status
497
+ #
498
+ # @return [Symbol, SportsOddsAPI::Models::Event::Player::Status, nil]
499
+ optional :status, enum: -> { SportsOddsAPI::Event::Player::Status }
500
+
501
+ # @!attribute status_details
502
+ #
503
+ # @return [String, nil]
504
+ optional :status_details, String, api_name: :statusDetails
505
+
331
506
  # @!attribute team_id
332
507
  #
333
508
  # @return [String, nil]
334
509
  optional :team_id, String, api_name: :teamID
335
510
 
336
- # @!method initialize(alias_: nil, first_name: nil, last_name: nil, name: nil, photo: nil, player_id: nil, team_id: nil)
511
+ # @!method initialize(alias_: nil, first_name: nil, last_name: nil, name: nil, photo: nil, player_id: nil, status: nil, status_details: nil, team_id: nil)
337
512
  # @param alias_ [String]
338
513
  # @param first_name [String]
339
514
  # @param last_name [String]
340
515
  # @param name [String]
341
516
  # @param photo [String]
342
517
  # @param player_id [String]
518
+ # @param status [Symbol, SportsOddsAPI::Models::Event::Player::Status]
519
+ # @param status_details [String]
343
520
  # @param team_id [String]
521
+
522
+ # @see SportsOddsAPI::Models::Event::Player#status
523
+ module Status
524
+ extend SportsOddsAPI::Internal::Type::Enum
525
+
526
+ IR = :ir
527
+ ACTIVE = :active
528
+ OUT = :out
529
+ SUSPENDED = :suspended
530
+ QUESTIONABLE = :questionable
531
+ DOUBTFUL = :doubtful
532
+ PROBABLE = :probable
533
+
534
+ # @!method self.values
535
+ # @return [Array<Symbol>]
536
+ end
344
537
  end
345
538
 
346
539
  # @see SportsOddsAPI::Models::Event#status