diff --git a/espn_api/base_league.py b/espn_api/base_league.py index 9f7c3fd2..4c69e599 100644 --- a/espn_api/base_league.py +++ b/espn_api/base_league.py @@ -30,7 +30,6 @@ def __repr__(self): def _fetch_league(self, SettingsClass = BaseSettings): data = self.espn_request.get_league() - self.currentMatchupPeriod = data['status']['currentMatchupPeriod'] self.scoringPeriodId = data['scoringPeriodId'] self.firstScoringPeriod = data['status']['firstScoringPeriod'] @@ -49,7 +48,6 @@ def _fetch_league(self, SettingsClass = BaseSettings): def _fetch_draft(self): '''Creates list of Pick objects from the leagues draft''' data = self.espn_request.get_league_draft() - # League has not drafted yet if not data.get('draftDetail', {}).get('drafted'): return diff --git a/espn_api/requests/espn_requests.py b/espn_api/requests/espn_requests.py index 924d12f5..c60e78ac 100644 --- a/espn_api/requests/espn_requests.py +++ b/espn_api/requests/espn_requests.py @@ -17,21 +17,6 @@ class ESPNUnknownError(Exception): pass -def checkRequestStatus(status: int, cookies=None, league_id=None) -> None: - if cookies is None: - cookies = {} - if league_id is None: - league_id = "" - if status == 401: - raise ESPNAccessDenied(f"League {league_id} cannot be accessed with espn_s2={cookies.get('espn_s2')} and swid={cookies.get('SWID')}") - - elif status == 404: - raise ESPNInvalidLeague(f"League {league_id} does not exist") - - elif status != 200: - raise ESPNUnknownError(f"ESPN returned an HTTP {status}") - - class EspnFantasyRequests(object): def __init__(self, sport: str, year: int, league_id: int, cookies: dict = None, logger: Logger = None): if sport not in FANTASY_SPORTS: @@ -49,19 +34,54 @@ def __init__(self, sport: str, year: int, league_id: int, cookies: dict = None, else: self.LEAGUE_ENDPOINT += "/seasons/" + str(year) + "/segments/0/leagues/" + str(league_id) + def checkRequestStatus(self, status: int, extend: str = "", params: dict = None, headers: dict = None) -> dict: + '''Handles ESPN API response status codes and endpoint format switching''' + if status == 401: + # If the current LEAGUE_ENDPOINT was using the /leagueHistory/ endpoint, switch to "/seasons/" endpoint + if "/leagueHistory/" in self.LEAGUE_ENDPOINT: + base_endpoint = self.LEAGUE_ENDPOINT.split("/leagueHistory/")[0] + self.LEAGUE_ENDPOINT = f"{base_endpoint}/seasons/{self.year}/segments/0/leagues/{self.league_id}" + else: + # If the current LEAGUE_ENDPOINT was using /seasons, switch to the "/leagueHistory/" endpoint + base_endpoint = self.LEAGUE_ENDPOINT.split(f"/seasons/")[0] + self.LEAGUE_ENDPOINT = f"{base_endpoint}/leagueHistory/{self.league_id}?seasonId={self.year}" + + #try the alternate endpoint + r = requests.get(self.LEAGUE_ENDPOINT + extend, params=params, headers=headers, cookies=self.cookies) + + if r.status_code == 200: + # Return the updated response if alternate works + return r.json() + + # If all endpoints failed, raise the corresponding error + raise ESPNAccessDenied(f"League {self.league_id} cannot be accessed with espn_s2={self.cookies.get('espn_s2')} and swid={self.cookies.get('SWID')}") + + elif status == 404: + raise ESPNInvalidLeague(f"League {self.league_id} does not exist") + + elif status != 200: + raise ESPNUnknownError(f"ESPN returned an HTTP {status}") + + # If no issues with the status code, return None + return None + def league_get(self, params: dict = None, headers: dict = None, extend: str = ''): endpoint = self.LEAGUE_ENDPOINT + extend r = requests.get(endpoint, params=params, headers=headers, cookies=self.cookies) - checkRequestStatus(r.status_code, cookies=self.cookies, league_id=self.league_id) + alternate_response = self.checkRequestStatus(r.status_code, extend=extend, params=params, headers=headers) + + + response = alternate_response if alternate_response else r.json() if self.logger: - self.logger.log_request(endpoint=endpoint, params=params, headers=headers, response=r.json()) - return r.json() if self.year > 2017 else r.json()[0] + self.logger.log_request(endpoint=self.LEAGUE_ENDPOINT + extend, params=params, headers=headers, response=response) + + return response[0] if isinstance(response, list) else response def get(self, params: dict = None, headers: dict = None, extend: str = ''): endpoint = self.ENDPOINT + extend r = requests.get(endpoint, params=params, headers=headers, cookies=self.cookies) - checkRequestStatus(r.status_code) + self.checkRequestStatus(r.status_code) if self.logger: self.logger.log_request(endpoint=endpoint, params=params, headers=headers, response=r.json()) @@ -73,7 +93,7 @@ def get_league(self): 'view': ['mTeam', 'mRoster', 'mMatchup', 'mSettings', 'mStandings'] } data = self.league_get(params=params) - return data + return data def get_pro_schedule(self): '''Gets the current sports professional team schedules''' diff --git a/tests/football/integration/test_league.py b/tests/football/integration/test_league.py index d9a89316..bf4113b4 100644 --- a/tests/football/integration/test_league.py +++ b/tests/football/integration/test_league.py @@ -15,8 +15,10 @@ def test_past_league(self): self.assertEqual(league.nfl_week, 18) def test_private_league(self): - with self.assertRaises(Exception): - League(368876, 2018) + ''' Test for switching to fallback API endpoint for private leagues. Random, incorrect cookies used to force fallback. ''' + league = League(368876, 2018, 'AEF1234567890ABCDE1234567890ABCD', '{D0C25A4C-2A0D-4E56-8E7F-20A10B663272}') + + self.assertEqual(league.espn_request.LEAGUE_ENDPOINT, "https://lm-api-reads.fantasy.espn.com/apis/v3/games/ffl/leagueHistory/368876?seasonId=2018") def test_unknown_league(self): with self.assertRaises(Exception):