i3pystatus.scores.mlb: Update module to use new statsapi (#739)
This commit is contained in:
parent
14cfde967c
commit
68d1158c9b
@ -9,9 +9,9 @@ import time
|
||||
from datetime import datetime
|
||||
from urllib.request import urlopen
|
||||
|
||||
LIVE_URL = 'http://mlb.mlb.com/mlb/gameday/index.jsp?gid=%s'
|
||||
LIVE_URL = 'https://www.mlb.com/gameday/%s'
|
||||
SCOREBOARD_URL = 'http://m.mlb.com/scoreboard'
|
||||
API_URL = 'http://gd2.mlb.com/components/game/mlb/year_%04d/month_%02d/day_%02d/miniscoreboard.json'
|
||||
API_URL = 'https://statsapi.mlb.com/api/v1/schedule?sportId=1,51&date=%04d-%02d-%02d&gameTypes=E,S,R,A,F,D,L,W&hydrate=team(),linescore(matchup,runners),stats,game(content(media(featured,epg),summary),tickets),seriesStatus(useOverride=true)&useLatestGames=false&language=en&leagueId=103,104,420'
|
||||
|
||||
|
||||
class MLB(ScoresBackend):
|
||||
@ -190,9 +190,10 @@ class MLB(ScoresBackend):
|
||||
self.get_api_date()
|
||||
url = self.api_url % (self.date.year, self.date.month, self.date.day)
|
||||
|
||||
game_list = self.get_nested(self.api_request(url),
|
||||
'data:games:game',
|
||||
default=[])
|
||||
game_list = self.get_nested(
|
||||
self.api_request(url),
|
||||
'dates:0:games',
|
||||
default=[])
|
||||
if not isinstance(game_list, list):
|
||||
# When only one game is taking place during a given day, the game
|
||||
# data is just a single dict containing that game's data, rather
|
||||
@ -205,17 +206,25 @@ class MLB(ScoresBackend):
|
||||
team_game_map = {}
|
||||
for game in game_list:
|
||||
try:
|
||||
id_ = game['id']
|
||||
id_ = game['gamePk']
|
||||
except (KeyError, TypeError):
|
||||
continue
|
||||
|
||||
try:
|
||||
for team in (game['home_name_abbrev'], game['away_name_abbrev']):
|
||||
team = team.upper()
|
||||
if team in self.favorite_teams:
|
||||
team_game_map.setdefault(team, []).append(id_)
|
||||
except KeyError:
|
||||
continue
|
||||
away_abbrev = self.get_nested(
|
||||
game,
|
||||
'teams:away:team:abbreviation',
|
||||
default='').upper()
|
||||
home_abbrev = self.get_nested(
|
||||
game,
|
||||
'teams:home:team:abbreviation',
|
||||
default='').upper()
|
||||
if away_abbrev and home_abbrev:
|
||||
try:
|
||||
for team in (home_abbrev, away_abbrev):
|
||||
if team in self.favorite_teams:
|
||||
team_game_map.setdefault(team, []).append(id_)
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
data[id_] = game
|
||||
|
||||
@ -224,106 +233,85 @@ class MLB(ScoresBackend):
|
||||
def process_game(self, game):
|
||||
ret = {}
|
||||
|
||||
def _update(ret_key, game_key=None, callback=None, default='?'):
|
||||
ret[ret_key] = self.get_nested(game,
|
||||
game_key or ret_key,
|
||||
callback=callback,
|
||||
default=default)
|
||||
|
||||
self.logger.debug('Processing %s game data: %s',
|
||||
self.__class__.__name__, game)
|
||||
|
||||
for key in ('id', 'venue'):
|
||||
_update(key)
|
||||
linescore = self.get_nested(game, 'linescore', default={})
|
||||
|
||||
for key in ('inning', 'outs'):
|
||||
_update(key, callback=self.force_int, default=0)
|
||||
ret['id'] = game['gamePk']
|
||||
ret['inning'] = self.get_nested(linescore, 'currentInning', default=0)
|
||||
ret['outs'] = self.get_nested(linescore, 'outs', default='')
|
||||
ret['live_url'] = self.live_url % ret['id']
|
||||
|
||||
ret['live_url'] = self.live_url % game['gameday_link']
|
||||
for team in ('away', 'home'):
|
||||
team_data = self.get_nested(game, 'teams:%s' % team, default={})
|
||||
|
||||
for team in ('home', 'away'):
|
||||
_update('%s_wins' % team, '%s_win' % team,
|
||||
callback=self.force_int)
|
||||
_update('%s_losses' % team, '%s_loss' % team,
|
||||
callback=self.force_int)
|
||||
_update('%s_score' % team, '%s_team_runs' % team,
|
||||
callback=self.force_int, default=0)
|
||||
if team == 'home':
|
||||
ret['venue'] = self.get_nested(team_data, 'venue:name', default='')
|
||||
|
||||
_update('%s_abbrev' % team, '%s_name_abbrev' % team)
|
||||
for item in ('city', 'name'):
|
||||
_update('%s_%s' % (team, item), '%s_team_%s' % (team, item))
|
||||
ret['%s_city' % team] = self.get_nested(
|
||||
team_data,
|
||||
'team:locationName',
|
||||
default='')
|
||||
ret['%s_name' % team] = self.get_nested(
|
||||
team_data,
|
||||
'team:teamName',
|
||||
default='')
|
||||
ret['%s_abbrev' % team] = self.get_nested(
|
||||
team_data,
|
||||
'team:abbreviation',
|
||||
default='')
|
||||
|
||||
try:
|
||||
ret['status'] = game.get('status').lower().replace(' ', '_')
|
||||
except AttributeError:
|
||||
# During warmup ret['status'] may be a dictionary. Treat these as
|
||||
# pregame
|
||||
ret['status'] = 'pregame'
|
||||
ret['%s_wins' % team] = self.get_nested(
|
||||
team_data,
|
||||
'leagueRecord:wins',
|
||||
default=0)
|
||||
ret['%s_losses' % team] = self.get_nested(
|
||||
team_data,
|
||||
'leagueRecord:losses',
|
||||
default=0)
|
||||
|
||||
ret['%s_score' % team] = self.get_nested(
|
||||
linescore,
|
||||
'teams:%s:runs' % team,
|
||||
default=0)
|
||||
|
||||
for key in ('delay', 'postponed', 'suspended'):
|
||||
ret[key] = ''
|
||||
|
||||
ret['status'] = self.get_nested(game, 'status:detailedState', default='').replace(' ', '_').lower()
|
||||
|
||||
if ret['status'] == 'delayed_start':
|
||||
ret['status'] = 'pregame'
|
||||
ret['delay'] = game.get('reason', 'Unknown')
|
||||
elif ret['status'] == 'delayed':
|
||||
ret['delay'] = self.get_nested(game, 'status:reason', default='Unknown')
|
||||
elif ret['status'].startswith('delayed'):
|
||||
ret['status'] = 'in_progress'
|
||||
ret['delay'] = game.get('reason', 'Unknown')
|
||||
ret['delay'] = game['status']['detailedState'].split(':', 1)[-1].strip()
|
||||
elif ret['status'] == 'postponed':
|
||||
ret['postponed'] = game.get('reason', 'Unknown Reason')
|
||||
ret['postponed'] = self.get_nested(game, 'status:reason', default='Unknown Reason')
|
||||
elif ret['status'] == 'suspended':
|
||||
ret['suspended'] = game.get('reason', 'Unknown Reason')
|
||||
elif ret['status'] in ('game_over', 'completed_early'):
|
||||
ret['suspended'] = self.get_nested(game, 'status:reason', default='Unknown Reason')
|
||||
elif ret['status'].startswith('completed_early') or ret['status'] == 'game_over':
|
||||
ret['status'] = 'final'
|
||||
elif ret['status'] not in ('in_progress', 'final'):
|
||||
ret['status'] = 'pregame'
|
||||
|
||||
try:
|
||||
inning = game.get('inning', '0')
|
||||
ret['extra_innings'] = inning \
|
||||
if ret['status'] == 'final' and int(inning) != 9 \
|
||||
ret['extra_innings'] = ret['inning'] \
|
||||
if ret['status'] == 'final' and ret['inning'] != 9 \
|
||||
else ''
|
||||
except ValueError:
|
||||
ret['extra_innings'] = ''
|
||||
|
||||
top_bottom = game.get('top_inning')
|
||||
ret['top_bottom'] = self.inning_top if top_bottom == 'Y' \
|
||||
else self.inning_bottom if top_bottom == 'N' \
|
||||
top_bottom = self.get_nested(linescore, 'inningHalf', default='').lower()
|
||||
ret['top_bottom'] = self.inning_top if top_bottom == 'top' \
|
||||
else self.inning_bottom if top_bottom == 'bottom' \
|
||||
else ''
|
||||
|
||||
time_zones = {
|
||||
'PT': 'US/Pacific',
|
||||
'MT': 'US/Mountain',
|
||||
'CT': 'US/Central',
|
||||
'ET': 'US/Eastern',
|
||||
}
|
||||
game_tz = pytz.timezone(
|
||||
time_zones.get(
|
||||
game.get('time_zone', 'ET'),
|
||||
'US/Eastern'
|
||||
)
|
||||
)
|
||||
|
||||
date_and_time = []
|
||||
if 'resume_time_date' in game and game['resume_time_date']:
|
||||
date_and_time.append(game['resume_time_date'])
|
||||
elif 'time_date' in game and game['time_date']:
|
||||
date_and_time.append(game['time_date'])
|
||||
else:
|
||||
keys = ('original_date', 'time')
|
||||
if all(key in game for key in keys):
|
||||
for key in keys:
|
||||
if game[key]:
|
||||
date_and_time.append(game[key])
|
||||
if 'resume_ampm' in game and game['resume_ampm']:
|
||||
date_and_time.append(game['resume_ampm'])
|
||||
elif 'ampm' in game and game['ampm']:
|
||||
date_and_time.append(game['ampm'])
|
||||
|
||||
game_time_str = ' '.join(date_and_time)
|
||||
|
||||
try:
|
||||
game_time = datetime.strptime(game_time_str, '%Y/%m/%d %I:%M %p')
|
||||
game_time = datetime.strptime(
|
||||
self.get_nested(game, 'gameDate', default=''),
|
||||
'%Y-%m-%dT%H:%M:%SZ')
|
||||
except ValueError as exc:
|
||||
# Log when the date retrieved from the API return doesn't match the
|
||||
# expected format (to help troubleshoot API changes), and set an
|
||||
@ -333,12 +321,12 @@ class MLB(ScoresBackend):
|
||||
self.logger.error(
|
||||
'Error encountered determining %s game time for game %s:',
|
||||
self.__class__.__name__,
|
||||
game['id'],
|
||||
game['gamePk'],
|
||||
exc_info=True
|
||||
)
|
||||
game_time = datetime(1970, 1, 1)
|
||||
|
||||
ret['start_time'] = game_tz.localize(game_time).astimezone()
|
||||
ret['start_time'] = pytz.timezone('UTC').localize(game_time).astimezone()
|
||||
|
||||
self.logger.debug('Returned %s formatter data: %s',
|
||||
self.__class__.__name__, ret)
|
||||
|
Loading…
Reference in New Issue
Block a user