sportsball 0.3.29__tar.gz → 0.3.30__tar.gz

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 (208) hide show
  1. {sportsball-0.3.29/sportsball.egg-info → sportsball-0.3.30}/PKG-INFO +1 -1
  2. {sportsball-0.3.29 → sportsball-0.3.30}/setup.py +1 -1
  3. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/__init__.py +1 -1
  4. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/afl_afltables_league_model.py +3 -1
  5. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/combined/afl_combined_league_model.py +18 -0
  6. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/google/google_address_model.py +9 -0
  7. sportsball-0.3.30/sportsball/data/oddsportal/decrypt.py +98 -0
  8. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_game_model.py +7 -38
  9. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_league_model.py +48 -64
  10. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_team_model.py +7 -71
  11. {sportsball-0.3.29 → sportsball-0.3.30/sportsball.egg-info}/PKG-INFO +1 -1
  12. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/SOURCES.txt +1 -0
  13. {sportsball-0.3.29 → sportsball-0.3.30}/LICENSE +0 -0
  14. {sportsball-0.3.29 → sportsball-0.3.30}/MANIFEST.in +0 -0
  15. {sportsball-0.3.29 → sportsball-0.3.30}/README.md +0 -0
  16. {sportsball-0.3.29 → sportsball-0.3.30}/requirements.txt +0 -0
  17. {sportsball-0.3.29 → sportsball-0.3.30}/setup.cfg +0 -0
  18. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/__main__.py +0 -0
  19. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/args.py +0 -0
  20. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/cache.py +0 -0
  21. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/__init__.py +0 -0
  22. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/address_model.py +0 -0
  23. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/__init__.py +0 -0
  24. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/__init__.py +0 -0
  25. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/afl_afltables_game_model.py +0 -0
  26. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/afl_afltables_player_model.py +0 -0
  27. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/afl_afltables_team_model.py +0 -0
  28. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/afltables/afl_afltables_venue_model.py +0 -0
  29. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/aussportsbetting/__init__.py +0 -0
  30. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/aussportsbetting/afl_aussportsbetting_league_model.py +0 -0
  31. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/combined/__init__.py +0 -0
  32. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/espn/__init__.py +0 -0
  33. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/espn/afl_espn_league_model.py +0 -0
  34. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/oddsportal/__init__.py +0 -0
  35. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/afl/oddsportal/afl_oddsportal_league_model.py +0 -0
  36. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/__init__.py +0 -0
  37. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_bookie_model.py +0 -0
  38. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_game_model.py +0 -0
  39. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_league_model.py +0 -0
  40. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_odds_model.py +0 -0
  41. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_team_model.py +0 -0
  42. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/aussportsbetting/aussportsbetting_venue_model.py +0 -0
  43. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/bookie_model.py +0 -0
  44. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/__init__.py +0 -0
  45. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_address_model.py +0 -0
  46. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_game_model.py +0 -0
  47. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_league_model.py +0 -0
  48. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_player_model.py +0 -0
  49. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_team_model.py +0 -0
  50. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_venue_model.py +0 -0
  51. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/combined/combined_weather_model.py +0 -0
  52. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/__init__.py +0 -0
  53. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_bookie_model.py +0 -0
  54. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_game_model.py +0 -0
  55. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_league_model.py +0 -0
  56. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_odds_model.py +0 -0
  57. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_player_model.py +0 -0
  58. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_team_model.py +0 -0
  59. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/espn/espn_venue_model.py +0 -0
  60. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/field_type.py +0 -0
  61. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/game_model.py +0 -0
  62. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/google/__init__.py +0 -0
  63. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/google/google_news_model.py +0 -0
  64. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/league.py +0 -0
  65. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/league_model.py +0 -0
  66. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/model.py +0 -0
  67. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/__init__.py +0 -0
  68. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/combined/__init__.py +0 -0
  69. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/combined/nba_combined_league_model.py +0 -0
  70. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/espn/__init__.py +0 -0
  71. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/espn/nba_espn_league_model.py +0 -0
  72. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/nba/__init__.py +0 -0
  73. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/nba/nba_nba_game_model.py +0 -0
  74. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/nba/nba_nba_league_model.py +0 -0
  75. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/nba/nba_nba_player_model.py +0 -0
  76. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/nba/nba_nba_team_model.py +0 -0
  77. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/oddsportal/__init__.py +0 -0
  78. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/oddsportal/nba_oddsportal_league_model.py +0 -0
  79. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/sportsdb/__init__.py +0 -0
  80. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/sportsdb/nba_sportsdb_league_model.py +0 -0
  81. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/sportsreference/__init__.py +0 -0
  82. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nba/sportsreference/nba_sportsreference_league_model.py +0 -0
  83. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/__init__.py +0 -0
  84. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/combined/__init__.py +0 -0
  85. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/combined/ncaab_combined_league_model.py +0 -0
  86. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/espn/__init__.py +0 -0
  87. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/espn/ncaab_espn_league_model.py +0 -0
  88. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/oddsportal/__init__.py +0 -0
  89. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/oddsportal/ncaab_oddsportal_league_model.py +0 -0
  90. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/sportsreference/__init__.py +0 -0
  91. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaab/sportsreference/ncaab_sportsreference_league_model.py +0 -0
  92. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/__init__.py +0 -0
  93. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/combined/__init__.py +0 -0
  94. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/combined/ncaaf_combined_league_model.py +0 -0
  95. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/espn/__init__.py +0 -0
  96. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/espn/ncaaf_espn_league_model.py +0 -0
  97. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/oddsportal/__init__.py +0 -0
  98. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/ncaaf/oddsportal/ncaaf_oddsportal_league_model.py +0 -0
  99. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/news_model.py +0 -0
  100. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/__init__.py +0 -0
  101. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/aussportsbetting/__init__.py +0 -0
  102. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/aussportsbetting/nfl_aussportsbetting_league_model.py +0 -0
  103. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/combined/__init__.py +0 -0
  104. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/combined/nfl_combined_league_model.py +0 -0
  105. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/espn/__init__.py +0 -0
  106. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/espn/nfl_espn_league_model.py +0 -0
  107. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/oddsportal/__init__.py +0 -0
  108. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py +0 -0
  109. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/sportsdb/__init__.py +0 -0
  110. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py +0 -0
  111. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/odds_model.py +0 -0
  112. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/__init__.py +0 -0
  113. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_bookie_model.py +0 -0
  114. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_odds_model.py +0 -0
  115. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/oddsportal/oddsportal_venue_model.py +0 -0
  116. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/player_model.py +0 -0
  117. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/season_type.py +0 -0
  118. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/social_model.py +0 -0
  119. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsdb/__init__.py +0 -0
  120. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsdb/sportsdb_game_model.py +0 -0
  121. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsdb/sportsdb_league_model.py +0 -0
  122. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsdb/sportsdb_team_model.py +0 -0
  123. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsdb/sportsdb_venue_model.py +0 -0
  124. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/__init__.py +0 -0
  125. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/sportsreference_game_model.py +0 -0
  126. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/sportsreference_league_model.py +0 -0
  127. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/sportsreference_player_model.py +0 -0
  128. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/sportsreference_team_model.py +0 -0
  129. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/sportsreference/sportsreference_venue_model.py +0 -0
  130. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/team_model.py +0 -0
  131. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/venue_model.py +0 -0
  132. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/__init__.py +0 -0
  133. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/gribstream/__init__.py +0 -0
  134. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/gribstream/gribstream_weather_model.py +0 -0
  135. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/multi_weather_model.py +0 -0
  136. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/openmeteo/__init__.py +0 -0
  137. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather/openmeteo/openmeteo_weather_model.py +0 -0
  138. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/weather_model.py +0 -0
  139. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/wikipedia/__init__.py +0 -0
  140. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/wikipedia/wikipedia_venue_model.py +0 -0
  141. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/x/__init__.py +0 -0
  142. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/data/x/x_social_model.py +0 -0
  143. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/logger.py +0 -0
  144. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/loglevel.py +0 -0
  145. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/proxy_session.py +0 -0
  146. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/session.py +0 -0
  147. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/sportsball.py +0 -0
  148. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/vendor/__init__.py +0 -0
  149. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball/vendor/pygooglenews/__init__.py +0 -0
  150. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/dependency_links.txt +0 -0
  151. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/entry_points.txt +0 -0
  152. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/not-zip-safe +0 -0
  153. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/requires.txt +0 -0
  154. {sportsball-0.3.29 → sportsball-0.3.30}/sportsball.egg-info/top_level.txt +0 -0
  155. {sportsball-0.3.29 → sportsball-0.3.30}/tests/__init__.py +0 -0
  156. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/__init__.py +0 -0
  157. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/afl/__init__.py +0 -0
  158. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/afl/afltables/__init__.py +0 -0
  159. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/afl/afltables/afl_afltables_league_model_test.py +0 -0
  160. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/afl/afltables/afl_afltables_player_model_test.py +0 -0
  161. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/aussportsbetting/__init__.py +0 -0
  162. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/aussportsbetting/aussportsbetting_game_model_test.py +0 -0
  163. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/combined/__init__.py +0 -0
  164. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/combined/combined_game_model_test.py +0 -0
  165. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/combined/combined_player_model_test.py +0 -0
  166. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/espn/__init__.py +0 -0
  167. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/espn/espn_game_model_test.py +0 -0
  168. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/espn/espn_player_model_test.py +0 -0
  169. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/game_model_test.py +0 -0
  170. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/google/__init__.py +0 -0
  171. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/google/google_address_model_test.py +0 -0
  172. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/google/google_news_model_test.py +0 -0
  173. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/__init__.py +0 -0
  174. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/nba/__init__.py +0 -0
  175. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/nba/nba_nba_game_model_test.py +0 -0
  176. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/nba/nba_nba_league_model_test.py +0 -0
  177. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/nba/nba_nba_player_model_test.py +0 -0
  178. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/nba/nba_nba_team_model_test.py +0 -0
  179. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/sportsdb/__init__.py +0 -0
  180. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/sportsdb/nba_sportsdb_league_model_test.py +0 -0
  181. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/sportsreference/__init__.py +0 -0
  182. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nba/sportsreference/nba_sportsreference_league_model_test.py +0 -0
  183. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/ncaab/__init__.py +0 -0
  184. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/ncaab/sportsreference/__init__.py +0 -0
  185. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/ncaab/sportsreference/ncaab_sportsreference_league_model_test.py +0 -0
  186. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nfl/__init__.py +0 -0
  187. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nfl/sportsdb/__init__.py +0 -0
  188. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/nfl/sportsdb/nfl_sportsdb_league_model_test.py +0 -0
  189. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/oddsportal/__init__.py +0 -0
  190. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/oddsportal/oddsportal_game_model_test.py +0 -0
  191. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/player_model_test.py +0 -0
  192. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/social_model_test.py +0 -0
  193. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsdb/__init__.py +0 -0
  194. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsdb/sportsdb_game_model_test.py +0 -0
  195. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsdb/sportsdb_league_model_test.py +0 -0
  196. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsdb/sportsdb_team_model_test.py +0 -0
  197. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsdb/sportsdb_venue_model_test.py +0 -0
  198. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/__init__.py +0 -0
  199. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/sportsreference_game_model_test.py +0 -0
  200. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/sportsreference_league_model_test.py +0 -0
  201. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/sportsreference_player_model_test.py +0 -0
  202. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/sportsreference_team_model_test.py +0 -0
  203. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/sportsreference/sportsreference_venue_model_test.py +0 -0
  204. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/team_model_test.py +0 -0
  205. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/x/__init__.py +0 -0
  206. {sportsball-0.3.29 → sportsball-0.3.30}/tests/data/x/x_social_model_test.py +0 -0
  207. {sportsball-0.3.29 → sportsball-0.3.30}/tests/proxy_session_test.py +0 -0
  208. {sportsball-0.3.29 → sportsball-0.3.30}/tests/sportsball_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.3.29
3
+ Version: 0.3.30
4
4
  Summary: A library for pulling in and normalising sports stats.
5
5
  Home-page: https://github.com/8W9aG/sportsball
6
6
  Author: Will Sackfield
@@ -26,7 +26,7 @@ def install_requires() -> typing.List[str]:
26
26
 
27
27
  setup(
28
28
  name='sportsball',
29
- version='0.3.29',
29
+ version='0.3.30',
30
30
  description='A library for pulling in and normalising sports stats.',
31
31
  long_description=long_description,
32
32
  long_description_content_type='text/markdown',
@@ -1,3 +1,3 @@
1
1
  """The main module for sportsball."""
2
2
 
3
- __VERSION__ = "0.3.29"
3
+ __VERSION__ = "0.3.30"
@@ -145,7 +145,9 @@ class AFLAFLTablesLeagueModel(LeagueModel):
145
145
 
146
146
  @property
147
147
  def games(self) -> Iterator[GameModel]:
148
- response = self.session.get(_SEASON_URL)
148
+ with self.session.cache_disabled():
149
+ response = self.session.get(_SEASON_URL)
150
+ response.raise_for_status()
149
151
  soup = BeautifulSoup(response.text, "html.parser")
150
152
  with tqdm.tqdm(position=self.position) as pbar:
151
153
  for table in soup.find_all("table"):
@@ -71,6 +71,22 @@ AFL_TEAM_IDENTITY_MAP = {
71
71
  "North Melbourne": KANGAROOS,
72
72
  "Melbourne": MELBOURNE,
73
73
  "Collingwood": COLLINGWOOD,
74
+ # OddsPortal
75
+ "Collingwood Magpies": COLLINGWOOD,
76
+ "Port Adelaide Power": PORT_ADELAIDE,
77
+ "Richmond Tigers": RICHMOND,
78
+ "Carlton Blues": CARLTON,
79
+ "Hawthorn Hawks": HAWTHORN,
80
+ "Essendon Bombers": ESSENDON,
81
+ "Sydney Swans": SWANS,
82
+ "Adelaide Crows": ADELAIDE,
83
+ "St Kilda Saints": STKILDA,
84
+ "Brisbane Lions": BRISBANE_LIONS,
85
+ "Melbourne Demons": MELBOURNE,
86
+ "Geelong Cats": GEELONG,
87
+ "Fremantle Dockers": FREMANTLE,
88
+ "West Coast Eagles": WESTCOAST,
89
+ "Gold Coast Suns": GOLDCOAST,
74
90
  }
75
91
  BRUNSWICK_ST = "brunswick_st"
76
92
  VICTORIA_PARK = "victoria_park"
@@ -199,6 +215,8 @@ AFL_VENUE_IDENTITY_MAP = {
199
215
  "Westpac Stadium": WELLINGTON,
200
216
  "AAMI Stadium": FOOTBALL_PARK,
201
217
  "Blacktown Park": BLACKTOWN,
218
+ # OddsPortal
219
+ "Melbourne Cricket Ground": MCG,
202
220
  }
203
221
 
204
222
 
@@ -7825,6 +7825,15 @@ _CACHED_GEOCODES: dict[str, Any] = {
7825
7825
  housenumber="35",
7826
7826
  country="USA",
7827
7827
  ),
7828
+ "Corpus Christi, Texas": SportsballGeocodeTuple(
7829
+ city="Corpus Christi",
7830
+ state="TX",
7831
+ postal="",
7832
+ lat=27.742778,
7833
+ lng=-97.401944,
7834
+ housenumber="",
7835
+ country="USA",
7836
+ ),
7828
7837
  }
7829
7838
 
7830
7839
 
@@ -0,0 +1,98 @@
1
+ """A function for decrypting an odds portal dat file."""
2
+
3
+ # pylint: disable=too-many-locals
4
+ import base64
5
+ import json
6
+ import urllib.parse
7
+ from typing import Any
8
+
9
+ import requests_cache
10
+ from bs4 import BeautifulSoup
11
+ from cryptography.hazmat.backends import default_backend
12
+ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
13
+ from cryptography.hazmat.primitives.hashes import SHA256
14
+ from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
15
+
16
+ from ...proxy_session import X_NO_WAYBACK
17
+
18
+
19
+ def _find_decryption_data(
20
+ session: requests_cache.CachedSession,
21
+ soup: BeautifulSoup,
22
+ referer_url: str,
23
+ user_agent: str | None = None,
24
+ ) -> tuple[bytes, bytes]:
25
+ salt: bytes | None = None
26
+ password: bytes | None = None
27
+ for script in soup.find_all("script"):
28
+ src = script.get("src")
29
+ if src is None:
30
+ continue
31
+ if "/app.js" in src:
32
+ src_url = urllib.parse.urljoin(referer_url, src)
33
+ headers = {X_NO_WAYBACK: "1"}
34
+ if user_agent is not None:
35
+ headers["User-Agent"] = user_agent
36
+ src_response = session.get(src_url, headers=headers)
37
+ src_response.raise_for_status()
38
+ variables = src_response.text
39
+ sentinel = 'break}return e.next=9,g(r.data,"'
40
+ variables = variables[variables.find(sentinel) + len(sentinel) :]
41
+ variables = variables[
42
+ : variables.find('");case 9:return s=e.sent,l=JSON.parse(s),e.abrupt')
43
+ ]
44
+ password_str, salt_str = variables.split('","')
45
+ salt = str.encode(salt_str)
46
+ password = str.encode(password_str)
47
+ break
48
+ if salt is None:
49
+ raise ValueError("salt is null.")
50
+ if password is None:
51
+ raise ValueError("password is null.")
52
+ return salt, password
53
+
54
+
55
+ def fetch_data(
56
+ url: str,
57
+ session: requests_cache.CachedSession,
58
+ referer_url: str,
59
+ soup: BeautifulSoup,
60
+ user_agent: str | None = None,
61
+ ) -> dict[str, Any]:
62
+ """Fetch the data from the URL and decrypt it."""
63
+ salt, password = _find_decryption_data(
64
+ session, soup, referer_url, user_agent=user_agent
65
+ )
66
+ headers = {
67
+ "X-Requested-With": "XMLHttpRequest",
68
+ "Referer": referer_url,
69
+ }
70
+ if user_agent is not None:
71
+ headers["User-Agent"] = user_agent
72
+ response = session.get(
73
+ url,
74
+ headers=headers,
75
+ )
76
+ response.raise_for_status()
77
+ decoded_data = base64.b64decode(response.content).decode()
78
+ encrypted, key = decoded_data.split(":")
79
+ encrypted_bytes = base64.urlsafe_b64decode(encrypted)
80
+ key_bytes = bytes.fromhex(key)
81
+ kdf = PBKDF2HMAC(
82
+ algorithm=SHA256(),
83
+ length=32,
84
+ salt=salt,
85
+ iterations=1000,
86
+ backend=default_backend(),
87
+ )
88
+ aes_key = kdf.derive(password)
89
+ cipher = Cipher(
90
+ algorithms.AES(aes_key), modes.CBC(key_bytes), backend=default_backend()
91
+ )
92
+ decryptor = cipher.decryptor()
93
+ decrypted_bytes = decryptor.update(encrypted_bytes) + decryptor.finalize()
94
+ decrypted_data = decrypted_bytes.decode("utf-8")
95
+ end_of_json = decrypted_data.rfind("}")
96
+ if end_of_json != -1:
97
+ decrypted_data = decrypted_data[: end_of_json + 1]
98
+ return json.loads(decrypted_data)
@@ -1,6 +1,6 @@
1
1
  """OddsPortal game model."""
2
2
 
3
- # pylint: disable=too-many-locals,too-many-statements
3
+ # pylint: disable=too-many-locals,too-many-statements,line-too-long
4
4
  import datetime
5
5
  import json
6
6
  import urllib.parse
@@ -13,6 +13,7 @@ from ...cache import MEMORY
13
13
  from ...proxy_session import X_NO_WAYBACK
14
14
  from ..game_model import GameModel
15
15
  from ..league import League
16
+ from .decrypt import fetch_data
16
17
  from .oddsportal_team_model import create_oddsportal_team_model
17
18
  from .oddsportal_venue_model import create_oddsportal_venue_model
18
19
 
@@ -49,31 +50,6 @@ def _create_oddsportal_game_model(
49
50
  default_scope_id = str(event_data["defaultScopeId"])
50
51
  xhash = urllib.parse.unquote(event_data["xhash"])
51
52
 
52
- salt: bytes | None = None
53
- password: bytes | None = None
54
- for script in soup.find_all("script"):
55
- src = script.get("src")
56
- if src is None:
57
- continue
58
- if "/app.js" in src:
59
- src_url = urllib.parse.urljoin(url, src)
60
- src_response = session.get(src_url, headers={X_NO_WAYBACK: "1"})
61
- src_response.raise_for_status()
62
- variables = src_response.text
63
- sentinel = 'break}return e.next=9,g(r.data,"'
64
- variables = variables[variables.find(sentinel) + len(sentinel) :]
65
- variables = variables[
66
- : variables.find('");case 9:return s=e.sent,l=JSON.parse(s),e.abrupt')
67
- ]
68
- password_str, salt_str = variables.split('","')
69
- salt = str.encode(salt_str)
70
- password = str.encode(password_str)
71
- break
72
- if salt is None:
73
- raise ValueError("salt is null.")
74
- if password is None:
75
- raise ValueError("password is null.")
76
-
77
53
  bookie_names = event_body["providersNames"]
78
54
  home_points = None
79
55
  if event_body["homeResult"] != "":
@@ -96,6 +72,9 @@ def _create_oddsportal_game_model(
96
72
  event_body["venueCountry"],
97
73
  )
98
74
 
75
+ url = f"https://www.oddsportal.com/match-event/{version_id}-{sport_id}-{unique_id}-{default_bet_id}-{default_scope_id}-{xhash}.dat"
76
+ parsed_data = fetch_data(url, session, url, soup)
77
+
99
78
  return GameModel(
100
79
  dt=dt,
101
80
  week=None,
@@ -108,16 +87,11 @@ def _create_oddsportal_game_model(
108
87
  event_data["home"],
109
88
  league,
110
89
  home_points,
111
- version_id,
112
- sport_id,
113
- unique_id,
114
90
  default_bet_id,
115
91
  default_scope_id,
116
- xhash,
117
- salt,
118
- password,
119
92
  bookie_names,
120
93
  0,
94
+ parsed_data,
121
95
  ),
122
96
  create_oddsportal_team_model(
123
97
  session,
@@ -125,16 +99,11 @@ def _create_oddsportal_game_model(
125
99
  event_data["away"],
126
100
  league,
127
101
  away_points,
128
- version_id,
129
- sport_id,
130
- unique_id,
131
102
  default_bet_id,
132
103
  default_scope_id,
133
- xhash,
134
- salt,
135
- password,
136
104
  bookie_names,
137
105
  1,
106
+ parsed_data,
138
107
  ),
139
108
  ],
140
109
  end_dt=end_dt,
@@ -1,6 +1,6 @@
1
1
  """Odds Portal league model."""
2
2
 
3
- # pylint: disable=too-many-locals,too-many-branches,too-many-statements,protected-access
3
+ # pylint: disable=too-many-locals,too-many-branches,too-many-statements,protected-access,too-many-arguments,line-too-long
4
4
  import http
5
5
  import json
6
6
  import logging
@@ -9,12 +9,14 @@ from typing import Iterator
9
9
 
10
10
  import extruct # type: ignore
11
11
  import requests
12
+ import requests_cache
12
13
  import tqdm
13
- from bs4 import BeautifulSoup, Tag
14
+ from bs4 import BeautifulSoup
14
15
 
15
16
  from ..game_model import GameModel
16
17
  from ..league import League
17
18
  from ..league_model import LeagueModel
19
+ from .decrypt import fetch_data
18
20
  from .oddsportal_game_model import create_oddsportal_game_model
19
21
 
20
22
  # Sports
@@ -28,6 +30,40 @@ USA = "usa"
28
30
  NCAA = "ncaa"
29
31
 
30
32
 
33
+ def _process_results_pages(
34
+ url: str,
35
+ session: requests_cache.CachedSession,
36
+ soup: BeautifulSoup,
37
+ league: League,
38
+ pbar: tqdm.tqdm,
39
+ response: requests.Response,
40
+ ) -> Iterator[GameModel]:
41
+ # Fetch first page
42
+ sanitised_text = response.text[response.text.find("var pageOutrightsVar = '") :]
43
+ sanitised_text = sanitised_text[: sanitised_text.find("'")]
44
+ page_outrights = json.loads(sanitised_text)
45
+ sports_id = page_outrights["sid"]
46
+ oddsportal_id = page_outrights["id"]
47
+
48
+ current_page = 1
49
+ total_pages = None
50
+ while (current_page == 1 and total_pages is None) or (
51
+ current_page <= 0 if total_pages is None else total_pages
52
+ ):
53
+ dat_url = f"https://www.oddsportal.com/ajax-sport-country-tournament-archive_/{sports_id}/{oddsportal_id}/X134529032X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X0X512X32X0X0X0X0X0X0X131072X0X2048/1/-5/page/{current_page}//"
54
+ parsed_data = fetch_data(dat_url, session, url, soup)
55
+ d = parsed_data["d"]
56
+ for row in d["rows"]:
57
+ game_model = create_oddsportal_game_model(
58
+ session, urllib.parse.urljoin(url, row["url"]), league, False
59
+ )
60
+ pbar.update(1)
61
+ pbar.set_description(f"OddsPortal {game_model.dt}")
62
+ yield game_model
63
+ total_pages = d["pagination"]["pages"]
64
+ current_page += 1
65
+
66
+
31
67
  class OddsPortalLeagueModel(LeagueModel):
32
68
  """Odds Portal implementation of the league model."""
33
69
 
@@ -92,7 +128,7 @@ class OddsPortalLeagueModel(LeagueModel):
92
128
  response = self.session.get(url)
93
129
  response.raise_for_status()
94
130
 
95
- soup = BeautifulSoup(response.text, "html.parser")
131
+ soup = BeautifulSoup(response.text, "xml")
96
132
 
97
133
  # Find next URLs
98
134
  for option in soup.find_all("option"):
@@ -100,69 +136,17 @@ class OddsPortalLeagueModel(LeagueModel):
100
136
  if next_url.endswith("/results/") and self._path[:-1] in next_url:
101
137
  queued_urls.add(next_url)
102
138
 
103
- # Paginate through results
104
- while True:
105
- game_urls = set()
106
-
107
- # Check the react tags
108
- tournament_component = soup.find("tournament-component")
109
- if isinstance(tournament_component, Tag):
110
- matches = json.loads(str(tournament_component[":sport-data"]))
111
- component = matches.get(
112
- "tournamentGamesComponent", matches.get("d")
113
- )
114
- if component.get("total") != 0:
115
- game_urls = {
116
- urllib.parse.urljoin(url, x["url"])
117
- for x in component.get("rows", [])
118
- }
119
- if not game_urls:
120
- for a in soup.find_all("a", href=True):
121
- game_url = urllib.parse.urljoin(url, a.get("href"))
122
- if (
123
- game_url.endswith("results/")
124
- or game_url.endswith("standings/")
125
- or game_url.endswith(self._path)
126
- or game_url.endswith("outrights/")
127
- ):
128
- continue
129
- if self._path[:-1] in game_url:
130
- game_urls.add(game_url)
131
-
132
- for game_url in game_urls:
133
- if "#" in game_url:
134
- continue
135
- if (
136
- game_url.replace("results/", "") == url
137
- or game_url.replace("results/", "") in queued_urls
138
- ):
139
- continue
140
- if game_url.endswith("/archive/"):
141
- continue
142
- if len(game_url.split("/")) != 8:
143
- continue
144
- game_model = create_oddsportal_game_model(
145
- self.session,
146
- game_url,
147
- self.league,
148
- False,
149
- )
150
- pbar.update(1)
151
- pbar.set_description(f"OddsPortal {game_model.dt}")
152
- yield game_model
153
-
154
- next_a = soup.find("a", text="Next", href=True)
155
- if next_a is None:
156
- break
157
- if not isinstance(next_a, Tag):
158
- raise ValueError("next_a is not a tag.")
159
- next_url = urllib.parse.urljoin(url, str(next_a.get("href")))
160
- response = self.session.get(next_url)
161
- response.raise_for_status()
162
- soup = BeautifulSoup(response.text, "html.parser")
139
+ yield from _process_results_pages(
140
+ url,
141
+ self.session,
142
+ soup,
143
+ self.league,
144
+ pbar,
145
+ response,
146
+ )
163
147
 
164
148
  @property
165
149
  def games(self) -> Iterator[GameModel]:
166
150
  with tqdm.tqdm(position=self.position) as pbar:
167
- # yield from self._find_next(pbar)
151
+ yield from self._find_next(pbar)
168
152
  yield from self._find_previous(pbar)
@@ -1,16 +1,11 @@
1
1
  """Odds Portal team model."""
2
2
 
3
3
  # pylint: disable=too-many-arguments,duplicate-code,line-too-long,too-many-locals
4
- import base64
5
4
  import datetime
6
- import json
5
+ from typing import Any
7
6
 
8
7
  import pytest_is_running
9
8
  import requests_cache
10
- from cryptography.hazmat.backends import default_backend
11
- from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
12
- from cryptography.hazmat.primitives.hashes import SHA256
13
- from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
14
9
 
15
10
  from ...cache import MEMORY
16
11
  from ..google.google_news_model import create_google_news_models
@@ -26,46 +21,12 @@ def _create_oddsportal_team_model(
26
21
  team_name: str,
27
22
  league: League,
28
23
  points: float | None,
29
- version_id: str,
30
- sport_id: str,
31
- unique_id: str,
32
24
  default_bet_id: str,
33
25
  default_scope_id: str,
34
- xhash: str,
35
- salt: bytes,
36
- password: bytes,
37
26
  bookie_names: dict[str, str],
38
27
  team_idx: int,
28
+ parsed_data: dict[str, Any],
39
29
  ) -> TeamModel:
40
- response = session.get(
41
- f"https://www.oddsportal.com/match-event/{version_id}-{sport_id}-{unique_id}-{default_bet_id}-{default_scope_id}-{xhash}.dat",
42
- headers={
43
- "X-Requested-With": "XMLHttpRequest",
44
- },
45
- )
46
- response.raise_for_status()
47
- decoded_data = base64.b64decode(response.content).decode()
48
- encrypted, key = decoded_data.split(":")
49
- encrypted_bytes = base64.urlsafe_b64decode(encrypted)
50
- key_bytes = bytes.fromhex(key)
51
- kdf = PBKDF2HMAC(
52
- algorithm=SHA256(),
53
- length=32,
54
- salt=salt,
55
- iterations=1000,
56
- backend=default_backend(),
57
- )
58
- aes_key = kdf.derive(password)
59
- cipher = Cipher(
60
- algorithms.AES(aes_key), modes.CBC(key_bytes), backend=default_backend()
61
- )
62
- decryptor = cipher.decryptor()
63
- decrypted_bytes = decryptor.update(encrypted_bytes) + decryptor.finalize()
64
- decrypted_data = decrypted_bytes.decode("utf-8")
65
- end_of_json = decrypted_data.rfind("}")
66
- if end_of_json != -1:
67
- decrypted_data = decrypted_data[: end_of_json + 1]
68
- parsed_data = json.loads(decrypted_data)
69
30
  try:
70
31
  odds_data = parsed_data["d"]["oddsdata"]["back"][
71
32
  f"E-{default_bet_id}-{default_scope_id}-0-0-0"
@@ -111,16 +72,11 @@ def _cached_create_oddsportal_team_model(
111
72
  team_name: str,
112
73
  league: League,
113
74
  points: float | None,
114
- version_id: str,
115
- sport_id: str,
116
- unique_id: str,
117
75
  default_bet_id: str,
118
76
  default_scope_id: str,
119
- xhash: str,
120
- salt: bytes,
121
- password: bytes,
122
77
  bookie_names: dict[str, str],
123
78
  team_idx: int,
79
+ parsed_data: dict[str, Any],
124
80
  ) -> TeamModel:
125
81
  return _create_oddsportal_team_model(
126
82
  session,
@@ -128,16 +84,11 @@ def _cached_create_oddsportal_team_model(
128
84
  team_name,
129
85
  league,
130
86
  points,
131
- version_id,
132
- sport_id,
133
- unique_id,
134
87
  default_bet_id,
135
88
  default_scope_id,
136
- xhash,
137
- salt,
138
- password,
139
89
  bookie_names,
140
90
  team_idx,
91
+ parsed_data,
141
92
  )
142
93
 
143
94
 
@@ -147,16 +98,11 @@ def create_oddsportal_team_model(
147
98
  team_name: str,
148
99
  league: League,
149
100
  points: float | None,
150
- version_id: str,
151
- sport_id: str,
152
- unique_id: str,
153
101
  default_bet_id: str,
154
102
  default_scope_id: str,
155
- xhash: str,
156
- salt: bytes,
157
- password: bytes,
158
103
  bookie_names: dict[str, str],
159
104
  team_idx: int,
105
+ parsed_data: dict[str, Any],
160
106
  ) -> TeamModel:
161
107
  """Create a team model based off the odds portal response."""
162
108
  if not pytest_is_running.is_running() and dt < datetime.datetime.now().replace(
@@ -168,16 +114,11 @@ def create_oddsportal_team_model(
168
114
  team_name,
169
115
  league,
170
116
  points,
171
- version_id,
172
- sport_id,
173
- unique_id,
174
117
  default_bet_id,
175
118
  default_scope_id,
176
- xhash,
177
- salt,
178
- password,
179
119
  bookie_names,
180
120
  team_idx,
121
+ parsed_data,
181
122
  )
182
123
  with session.cache_disabled():
183
124
  return _create_oddsportal_team_model(
@@ -186,14 +127,9 @@ def create_oddsportal_team_model(
186
127
  team_name,
187
128
  league,
188
129
  points,
189
- version_id,
190
- sport_id,
191
- unique_id,
192
130
  default_bet_id,
193
131
  default_scope_id,
194
- xhash,
195
- salt,
196
- password,
197
132
  bookie_names,
198
133
  team_idx,
134
+ parsed_data,
199
135
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: sportsball
3
- Version: 0.3.29
3
+ Version: 0.3.30
4
4
  Summary: A library for pulling in and normalising sports stats.
5
5
  Home-page: https://github.com/8W9aG/sportsball
6
6
  Author: Will Sackfield
@@ -120,6 +120,7 @@ sportsball/data/nfl/oddsportal/nfl_oddsportal_league_model.py
120
120
  sportsball/data/nfl/sportsdb/__init__.py
121
121
  sportsball/data/nfl/sportsdb/nfl_sportsdb_league_model.py
122
122
  sportsball/data/oddsportal/__init__.py
123
+ sportsball/data/oddsportal/decrypt.py
123
124
  sportsball/data/oddsportal/oddsportal_bookie_model.py
124
125
  sportsball/data/oddsportal/oddsportal_game_model.py
125
126
  sportsball/data/oddsportal/oddsportal_league_model.py
File without changes
File without changes
File without changes
File without changes