diff --git a/README.md b/README.md index f06650f..e144802 100644 --- a/README.md +++ b/README.md @@ -32,14 +32,48 @@ Creating an instance of the class can raise an error if there are network issues ### Available methods +* `leagues` - Get a list of all available leagues. +* `league(league_id)` - Show details for a specific league. +* `league_seasons(league_id)` - Get a list of seasons for a specific league. +* `league_suspensions(league_id, only_active: true)` - Get a list of suspended players for the specified league. + * `only_active` controls whether expired suspensions are included or not. + * WARNING: this response can be very large, especially if `only_active` is false. * `team_search(sport_name, team_name)` - Search for the given team in the given sport for all active seasons. * `team_schedule(team_id)` - Retrieve the game schedule for the supplied team. * `team_players_list(team_id)` - Get the list of players on a specific team. +* `teams_in_division(division_name, league_id, current_season: true)` - Get all teams in the named division in the specific league. + * This is an odd API that requires the division be a name, not an ID, and requires specifying a league ID to search in. +* `team_games(team_id, include_future: true, include_today: true)` - Get all games for a specific team. +* `team_games_for_status(team_id, status: 'Final,In Progress,Forfeit')` - Get a list of all games for a specific team matching the specified type. + * Valid values for `status` are `Final`, `In Progress`, and `Forfeit`, and can be mixed and matched, separated by commas. +* `team_practices(team_id, include_future: true, include_today: true)` - Get a list of practices schedule for the specified team. +* `team_suspensions(team_id, only_active: true)` - Get a list of suspensions of players on the specified team. + * `only_active` controls whether expired suspensions are included or not. +* `game(game_id)` - Returns data about the specified game. +* `game_goals(game_id, only: nil)` - Returns a list of goals in the specified game. + * Valid values for `only` are `:home` and `:away`. If not specified, both teams' goals are included. +* `game_goalies(game_id, only: nil)` - Returns a list of goalies in the specified game. + * Valid values for `only` are `:home` and `:away`. If not specified, both teams' goalies are included. +* `game_penalties(game_id, only: nil)` - Returns a list of penalties in the specified game. + * Valid values for `only` are `:home` and `:away`. If not specified, both teams' goalies are included. +* `game_roster(game_id, only: nil)` - Returns the roster for the specified game. + * Valid values for `only` are `:home` and `:away`. If not specified, both teams' rosters are included. * `division_games_list(division_id)` - Returns all games for a specified division. +* `division_standings(division_id, type: 'Regular Season')` - Returns a ranked list of teams for the specified division. + * Valid values for `type` are `Regular Season`, `Playoffs`, and `Exhibition`. +* `division_teams(division_id)` - Lists all teams in the specified division. +* `division_leaders(division_id, type: 'Regular Season', limit: 20, metrics: [:points, :goals])` - Lists up to `limit` number of leaders for the specified division. + * Valid values for `type` are `Regular Season`, `Playoffs`, and `Exhibition`. + * Valid values for `metrics` include symbolizing anything listed in `league(league_id)['league']['view_settings']['leader_metrics']`. +* `division_suspensions(division_id, only_active: true)` - Get a list of suspensions of players in the specified division. + * `only_active` controls whether expired suspensions are included or not. +* `season(season_id)` - Show details for a specific season. * `season_divisions_list(season_id)` - Lists all divisions for the specified season. +* `season_suspensions(season_id, only_active: true)` - Get a list of suspended players for the specified season. + * `only_active` controls whether expired suspensions are included or not. ## Bug reports, feature requests, contributions Please create an issue or pull request on github. Assistance is most welcome. -There are many more endpoints available on Shift sites, but none are documented. Running a mobile app inside an emulator and watching wireshark, fiddler, etc. is how the current endpoints were discovered. +There are more endpoints available on Shift sites, but none are documented. Running a mobile app inside an emulator and watching wireshark, fiddler, etc. is how the current endpoints were discovered. diff --git a/lib/shift_stats.rb b/lib/shift_stats.rb index 37a3cd5..513501a 100644 --- a/lib/shift_stats.rb +++ b/lib/shift_stats.rb @@ -39,6 +39,26 @@ class ShiftStats end end + def leagues() + JSON.parse(@client.get(url('leagues'), header: headers).body) + end + + def league(league_id) + JSON.parse(@client.get(url("league/#{league_id}"), header: headers).body) + end + + def league_seasons(league_id) + JSON.parse(@client.get(url("league/#{league_id}/seasons"), header: headers).body) + end + + def league_suspensions(league_id, only_active: true) + query = {} + if only_active + query[:status] = 'active' + end + JSON.parse(@client.get(url("league/#{league_id}/suspensions"), query: query, header: headers).body) + end + def team_search(sport, name) JSON.parse(@client.get(url('teams'), query: {name: name, not_ended: true, sport: sport.downcase}, header: headers).body) end @@ -51,19 +71,109 @@ class ShiftStats JSON.parse(@client.get(url("team/#{team_id}/players"), query: {status: 'active'}, header: headers).body) end + def teams_in_division(division_name, league_id, current_season: true) + JSON.parse(@client.get(url('teams'), query: {division: division_name, league_id: league_id, not_ended: !!current_season}, header: headers).body) + end + + def team_games(team_id, include_future: true, include_today: true) + JSON.parse(@client.get(url("team/#{team_id}/games"), query: {future: include_future, today: include_today}, header: headers).body) + end + + def team_games_for_status(team_id, status: 'Final,In Progress,Forfeit') + JSON.parse(@client.get(url("team/#{team_id}/games"), query: {status: status}, header: headers).body) + end + + def team_practices(team_id, include_future: true, include_today: true) + JSON.parse(@client.get(url("team/#{team_id}/practices"), query: {future: include_future, today: include_today}, header: headers).body) + end + + def team_suspensions(team_id, only_active: true) + query = {} + if only_active + query[:status] = 'active' + end + JSON.parse(@client.get(url("team/#{team_id}/suspensions"), query: query, header: headers).body) + end + + def game(game_id) + JSON.parse(@client.get(url("game/#{game_id}"), header: headers).body) + end + + # only is :home or :away, optional + def game_goals(game_id, only: nil) + game_subpath(game_id, 'goals', only) + end + + # only is :home or :away, optional + def game_goalies(game_id, only: nil) + game_subpath(game_id, 'goalies', only) + end + + # only is :home or :away, optional + def game_penalties(game_id, only: nil) + game_subpath(game_id, 'penalties', only) + end + + # only is :home or :away, optional + def game_roster(game_id, only: nil) + game_subpath(game_id, 'roster', only) + end + def division_games_list(division_id) JSON.parse(@client.get(url("division/#{division_id}/games"), header: headers).body) end + # type is 'Regular Season', 'Playoffs', or 'Exhibition', required + def division_standings(division_id, type: 'Regular Season') + JSON.parse(@client.get(url("division/#{division_id}/standings"), query: {type: type}, header: headers).body) + end + + def division_teams(division_id) + JSON.parse(@client.get(url("division/#{division_id}/teams"), header: headers).body) + end + + # type is 'Regular Season', 'Playoffs', or 'Exhibition', required + # limit, required + # metrics, required + def division_leaders(division_id, type: 'Regular Season', limit: 20, metrics: [:points, :goals, :assists, :goals_against_average, :save_percentage, :wins, :shutouts, :number_first_stars, :number_stars]) + JSON.parse(@client.get(url("division/#{division_id}/leaders"), query: {limit: limit, metrics: metrics.join(','), type: type}, header: headers).body) + end + + def division_suspensions(division_id, only_active: true) + query = {} + if only_active + query[:status] = 'active' + end + JSON.parse(@client.get(url("division/#{division_id}/suspensions"), query: query, header: headers).body) + end + + def season(season_id) + JSON.parse(@client.get(url("season/#{season_id}"), header: headers).body) + end + def season_divisions_list(season_id) JSON.parse(@client.get(url("season/#{season_id}/divisions"), header: headers).body) end + def season_suspensions(season_id, only_active: true) + query = {} + if only_active + query[:status] = 'active' + end + JSON.parse(@client.get(url("season/#{season_id}/suspensions"), query: query, header: headers).body) + end + private def url(sub) return "#{@url_base}#{sub}" end + def game_subpath(game_id, path, only) + path = "home_#{path}" if only == :home + path = "away_#{path}" if only == :away + JSON.parse(@client.get(url("game/#{game_id}/#{path}"), header: headers).body) + end + def login_query {key: self.class.configuration.api_key} end diff --git a/spec/shift_stats_spec.rb b/spec/shift_stats_spec.rb index 666901a..c491a89 100644 --- a/spec/shift_stats_spec.rb +++ b/spec/shift_stats_spec.rb @@ -13,10 +13,6 @@ describe ShiftStats do team_search = s.team_search('hockey', 'bears') context 'team_search' do - it 'returns something' do - expect(team_search).to be_truthy - end - it 'returns some teams' do expect(team_search).to include 'teams' end @@ -30,32 +26,184 @@ describe ShiftStats do context 'team_schedule' do team_schedule = s.team_schedule(18827) - it 'returns something' do - expect(team_schedule).to be_truthy + it 'returns a schedule' do + expect(team_schedule).to include 'games' end end context 'team_players_list' do team_players = s.team_players_list(18827) - it 'returns something' do - expect(team_players).to be_truthy + it 'returns players' do + expect(team_players).to include 'players' end end context 'division_games_list' do division_games = s.division_games_list(3057) - it 'returns something' do - expect(division_games).to be_truthy + it 'returns a list of games' do + expect(division_games).to include 'games' end end context 'season_divisions_list' do season_divisions = s.season_divisions_list(741) - it 'returns something' do - expect(season_divisions).to be_truthy + it 'returns a list of divisions' do + expect(season_divisions).to include 'divisions' + end + end + + context 'season_suspensions' do + ret = s.season_suspensions(741, only_active: false) + + it 'returns a list of suspensions' do + expect(ret).to include 'suspensions' + end + end + + context 'leagues' do + leagues = s.leagues + + it 'returns a list of leagues' do + expect(leagues).to include 'leagues' + end + end + + context 'league' do + league = s.league(3) + + it 'returns a league' do + expect(league).to include 'league' + end + end + + context 'league_seasons' do + seasons = s.league_seasons(3) + + it 'returns a list of seasons' do + expect(seasons).to include 'seasons' + end + end + + context 'league_seasons' do + ret = s.league_suspensions(3, only_active: true) + + it 'returns a list of suspensions' do + expect(ret).to include 'suspensions' + end + end + + context 'teams_in_division' do + teams = s.teams_in_division('XPL', 317, current_season: true) + + it 'returns a list of teams' do + expect(teams).to include 'teams' + end + end + + context 'team_games' do + games = s.team_games(1, include_future: true, include_today: true) + + it 'returns a list of games' do + expect(games).to include 'games' + end + end + + context 'team_games_for_status' do + games = s.team_games_for_status(1, status: 'Final,In Progress') + + it 'returns a list of games' do + expect(games).to include 'games' + end + end + + context 'team_practices' do + practices = s.team_practices(18827, include_future: true, include_today: true) + + it 'returns a list of practices' do + expect(practices).to include 'practices' + end + end + + context 'team_suspensions' do + ret = s.team_suspensions(18827, only_active: false) + + it 'returns a list of suspensions' do + expect(ret).to include 'suspensions' + end + end + + context 'game' do + ret = s.game(128740) + + it 'returns game info' do + expect(ret).to include 'game' + end + end + + context 'game_goals' do + ret = s.game_goals(128740, only: :away) + + it 'returns a list of away goals' do + expect(ret).to include 'away_goals' + end + end + + context 'game_goalies' do + ret = s.game_goalies(128740, only: :away) + + it 'returns a list of away goalies' do + expect(ret).to include 'away_goalies' + end + end + + context 'game_penalties' do + ret = s.game_penalties(128740, only: :away) + + it 'returns a list of away penalties' do + expect(ret).to include 'away_penalties' + end + end + + context 'game_roster' do + ret = s.game_roster(128740, only: :away) + + it 'returns an away roster' do + expect(ret).to include 'away_roster' + end + end + + context 'division_standings' do + ret = s.division_standings(3057, type: 'Regular Season') + + it 'returns ranked list of teams' do + expect(ret).to include 'teams' + end + end + + context 'division_teams' do + ret = s.division_teams(3057) + + it 'returns a list of teams' do + expect(ret).to include 'teams' + end + end + + context 'division_leaders' do + ret = s.division_leaders(3057, type: 'Regular Season', limit: 5, metrics: [:points, :goals, :assists]) + + it 'returns a list of leaders' do + expect(ret).to include 'leaders' + end + end + + context 'division_suspensions' do + ret = s.division_suspensions(3057, only_active: false) + + it 'returns a list of suspensions' do + expect(ret).to include 'suspensions' end end end