def _display_standings(standings_type, display_title, date_str, args_filter, rank_tag='divisionRank', header_tags=('league', 'division')): if date_str is None: season_str = time.strftime("%Y") url_date_str = '' else: season_str = datetime.strftime(datetime.strptime(date_str, "%Y-%m-%d"), "%Y") url_date_str = '&date=' + date_str url = STANDINGS_URL.format(standings_type=standings_type, league_ids=_get_league_ids(args_filter), season=season_str, date=url_date_str) json_data = util.request_json(url, 'standings') border = displayutil.Border(use_unicode=config.UNICODE) outl = list() if display_title != '': outl.append(_get_title_header(display_title, border)) needs_line_hr = False for record in json_data['records']: if args_filter and standings_type == 'byDivision' and args_filter in DIVISION_FILTERS: pass _get_standings_display_for_record(outl, standings_type, record, header_tags, rank_tag, border, needs_line_hr) print('\n'.join(outl))
def _lookup_inning_timestamp_via_live(game_pk, inning, inning_half='top', overwrite_json=True): LOG.info("Retrieving inning info to locate '{} {}' inning".format( inning_half, inning)) # playbyplay_url = 'http://statsapi.mlb.com/api/v1/game/{gamepk}/playByPlay'.format(gamepk=game_pk) #playbyplay_url = 'http://statsapi.mlb.com/api/v1/game/{gamepk}/playByPlay?fields=allPlays,about,startTime,inning,halfInning'.format(gamepk=game_pk) url = 'https://statsapi.mlb.com/api/v1/game/{gamepk}/feed/live'.format( gamepk=game_pk) json_data = util.request_json(url, 'live') #json_data = util.request_json(live_url, 'live') if 'liveData' in json_data and 'plays' in json_data[ 'liveData'] and 'allPlays' in json_data['liveData']['plays']: if json_data['liveData']['plays']['allPlays'] is None or len( json_data['liveData']['plays']['allPlays']) < 1: LOG.debug("_lookup_inning_timestamp: no play data for %s", url) return None, None, None, None else: LOG.debug("_lookup_inning_timestamp: no live data for %s", url) return None, None, None, None first_play = None for play in json_data['liveData']['plays']['allPlays']: if first_play is None: first_play_timestamp_str = str(play['about']['startTts']) first_play_timestamp = datetime.strptime( first_play_timestamp_str, '%Y%m%d_%H%M%S').replace(tzinfo=timezone.utc).timestamp() LOG.debug("First play: %s", first_play_timestamp_str) LOG.debug("First play data: %s", play) if str(play['about']['inning']) == inning and str( play['about']['halfInning']) == inning_half: inning_start_timestamp_str = str(play['about']['startTts']) inning_start_timestamp = datetime.strptime( inning_start_timestamp_str, '%Y%m%d_%H%M%S').replace(tzinfo=timezone.utc).timestamp() LOG.info("Found inning start: %s", inning_start_timestamp_str) LOG.debug("Inning start play data: %s", play) return first_play_timestamp, first_play_timestamp_str, inning_start_timestamp, inning_start_timestamp_str LOG.warn("Could not locate '{} {}' inning".format(inning_half, inning)) return first_play, first_play_timestamp_str, None, None
def display_standings(standings_type, display_title, date_str, rank_tag='divisionRank', header_tags=('conference', 'division')): url = STANDINGS_URL.format(standings_type=standings_type, date=date_str) json_data = util.request_json(url, 'standings') border = displayutil.Border(use_unicode=config.UNICODE) outl = list() if display_title != '': outl.append( '{color_on}{name:22}\t{win:^2} {ot:^2} {loss:^2} {point:^3} {streak}{color_off}' .format(color_on=border.border_color, name=' {thickborder} {title} {thickborder}'.format( title=display_title, thickborder=border.doubledash * int((29 - len(display_title)) / 2 - 1)), win='W', ot='OT', loss='L', point='P', streak='Streak', color_off=ANSI.reset())) needs_line_hr = False for record in json_data['records']: if standings_type == record['standingsType']: if needs_line_hr > 0: pass # outl.append('-' * 10) header = '' for tag in header_tags: if tag in record: if 'name' in record[tag]: header = _add_to_header(header, record[tag]['name']) else: header = _add_to_header(header, record[tag]) if header: header = '{color_on}{b1} {title} {b2}{color_off}'.format( color_on=border.border_color, title=header, b1=border.dash * 3, b2=border.dash * (41 - len(header)), color_off=ANSI.reset()) outl.append(' {}'.format(header)) needs_line_hr = True else: LOG.error('Unexpected: standingsType=%s, not %s', record['standingsType'], standings_type) for teamrec in record['teamRecords']: clinch = '' if 'clinchIndicator' in teamrec: clinch = teamrec['clinchIndicator'] + '-' rank = '' if rank_tag in teamrec: rank = teamrec[rank_tag] color_on = '' color_off = '' if _is_fav(teamrec['team']['name']): if config.CONFIG.parser['fav_colour'] != '': color_on = ANSI.fg(config.CONFIG.parser['fav_colour']) color_off = ANSI.reset() outl.append( '{color_on}{rank:2} {clinch}{name:22}\t{win:2} {ot:2} {loss:2} {point:3} [{streak}]{color_off}' .format(color_on=color_on, rank=rank, clinch=clinch, name=teamrec['team']['name'], win=teamrec['leagueRecord']['wins'], ot=teamrec['leagueRecord']['ot'], loss=teamrec['leagueRecord']['losses'], point=teamrec['points'], streak=teamrec['streak']['streakCode'], color_off=color_off)) print('\n'.join(outl))
def _get_games_by_date(date_str=None): if date_str is None: date_str = time.strftime("%Y-%m-%d") if config.SAVE_JSON_FILE_BY_TIMESTAMP: json_file = os.path.join( config.CONFIG.dir, 'gamedata-{}.json'.format(time.strftime("%Y-%m-%d-%H%M"))) else: json_file = os.path.join(config.CONFIG.dir, 'gamedata.json') LOG.debug('Getting game data...') url = ( '{0}/schedule?&startDate={1}&endDate={1}&expand=' 'schedule.teams,schedule.linescore,schedule.game.content.media.epg' ).format(config.CONFIG.api_url, date_str) json_data = util.request_json(url, 'gamedata') game_records = dict() # we return this dictionary if json_data is None: LOG.error("No JSON data returned for %s", date_str) return None if json_data['dates'] is None or len(json_data['dates']) < 1: LOG.debug("_get_games_by_date: no game data for %s", date_str) return None for game in json_data['dates'][0]['games']: # LOG.debug('game: {}'.format(game)) game_pk_str = str(game['gamePk']) game_records[game_pk_str] = dict() game_rec = game_records[game_pk_str] game_rec['game_pk'] = game_pk_str game_rec['abstractGameState'] = str( game['status']['abstractGameState']) # Preview, Live, Final game_rec['detailedState'] = str( game['status']['detailedState'] ) # is something like: Scheduled, Live, Final, In Progress, Critical game_rec['nhldate'] = datetime.strptime(str(game['gameDate']), "%Y-%m-%dT%H:%M:%SZ") game_rec['away_name'] = str(game['teams']['away']['team']['name']) game_rec['away_abbrev'] = str( game['teams']['away']['team']['abbreviation'].lower()) game_rec['away_score'] = str(game['teams']['away']['score']) game_rec['home_name'] = str(game['teams']['home']['team']['name']) game_rec['home_abbrev'] = str( game['teams']['home']['team']['abbreviation'].lower()) game_rec['home_score'] = str(game['teams']['home']['score']) game_rec['favourite'] = is_fav(game_rec) # game_rec['nhltv_link'] = 'http://nhl.com/tv/{0}/'.format(game_pk_str) # linescore game_rec['linescore'] = dict() game_rec['linescore']['currentPeriod'] = str( game['linescore']['currentPeriod']) if 'currentPeriodOrdinal' in game['linescore']: game_rec['linescore']['currentPeriodOrdinal'] = str( game['linescore'] ['currentPeriodOrdinal']) # : "2nd", "OT", "SO" game_rec['linescore']['currentPeriodTimeRemaining'] = str( game['linescore'] ['currentPeriodTimeRemaining']) # : "18:58", "Final" game_rec['linescore']['hasShootout'] = bool( game['linescore']['hasShootout']) else: game_rec['linescore']['currentPeriodOrdinal'] = 'Not Started' game_rec['linescore']['currentPeriodTimeRemaining'] = '20:00' game_rec['linescore']['hasShootout'] = False # epg game_rec['feed'] = dict() if 'media' in game['content'] and 'epg' in game['content']['media']: for media in game['content']['media']['epg']: if media['title'] == 'NHLTV': for stream in media['items']: if stream[ 'mediaFeedType'] != 'COMPOSITE' and stream[ 'mediaFeedType'] != 'ISO': feedtype = str(stream['mediaFeedType']).lower( ) # home, away, national, french, ... game_rec['feed'][feedtype] = dict() game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) game_rec['feed'][feedtype]['eventId'] = str( stream['eventId']) game_rec['feed'][feedtype][ 'callLetters'] = str(stream['callLetters']) elif media['title'] == 'Extended Highlights': feedtype = 'condensed' if len(media['items']) > 0: game_rec['feed'][feedtype] = dict() stream = media['items'][0] game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) for playback_item in stream['playbacks']: if playback_item[ 'name'] == config.CONFIG.playback_scenario: game_rec['feed'][feedtype][ 'playback_url'] = playback_item['url'] elif media['title'] == 'Recap': feedtype = 'recap' if len(media['items']) > 0: game_rec['feed'][feedtype] = dict() stream = media['items'][0] game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) for playback_item in stream['playbacks']: if playback_item[ 'name'] == config.CONFIG.playback_scenario: game_rec['feed'][feedtype][ 'playback_url'] = playback_item['url'] elif media['title'] == 'Audio': for stream in media['items']: feedtype = 'audio-' + str( stream['mediaFeedType']).lower( ) # home, away, national, french, ... game_rec['feed'][feedtype] = dict() game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) game_rec['feed'][feedtype]['eventId'] = str( stream['eventId']) game_rec['feed'][feedtype]['callLetters'] = str( stream['callLetters']) return game_records
def _get_games_by_date(self, date_str=None): if date_str is None: date_str = time.strftime("%Y-%m-%d") # https://statsapi.mlb.com/api/v1/schedule?sportId=1&startDate=2018-03-26&endDate=2018-03-26&hydrate=schedule.teams,schedule.linescore,schedule.game.content.media.epg # hydrate = 'hydrate=schedule.teams,schedule.linescore,schedule.game.content.media.epg' hydrate = 'hydrate=broadcasts(all),game(content(all)),linescore,team' # hydrate = 'hydrate=linescore,team,game(content(summary,media(epg)),tickets)' url = '{0}/api/v1/schedule?sportId=1&startDate={1}&endDate={1}&{2}'.format( config.CONFIG.api_url, date_str, hydrate) json_data = util.request_json(url, 'gamedata') game_records = dict() # we return this dictionary if json_data['dates'] is None or len(json_data['dates']) < 1: LOG.debug( "_get_games_by_date: no game data for {}".format(date_str)) return None for game in json_data['dates'][0]['games']: # LOG.debug('game: {}'.format(game)) game_pk_str = str(game['gamePk']) game_records[game_pk_str] = dict() game_rec = game_records[game_pk_str] game_rec['game_pk'] = game_pk_str game_rec['abstractGameState'] = str( game['status']['abstractGameState']) # Preview, Live, Final game_rec['codedGameState'] = str( game['status'] ['codedGameState']) # is something like: F, O, C, I # is something like: Scheduled, Live, Final, In Progress, Critical, Postponed: game_rec['detailedState'] = str(game['status']['detailedState']) game_rec['doubleHeader'] = str(game['doubleHeader']) game_rec['gameNumber'] = str(game['gameNumber']) game_rec['mlbdate'] = parser.parse(str(game['gameDate'])) game_rec['gamesInSeries'] = str(game['gamesInSeries']) game_rec['seriesGameNumber'] = str(game['seriesGameNumber']) game_rec['linescore'] = dict() if 'linescore' in game: game_rec['linescore']['raw'] = game['linescore'] if 'Delayed' in game_rec['detailedState']: game_rec['linescore']['currentInning'] = str( game_rec['detailedState']) game_rec['linescore'][ 'currentInningOrdinal'] = 'Not Started' game_rec['linescore']['inningState'] = '' elif 'currentInning' in game['linescore']: game_rec['linescore']['currentInning'] = str( game['linescore']['currentInning']) else: game_rec['linescore']['currentInningOrdinal'] = '0' if 'currentInningOrdinal' in game['linescore']: game_rec['linescore']['currentInningOrdinal'] = str( game['linescore']['currentInningOrdinal']) if 'inningState' in game['linescore']: game_rec['linescore']['inningState'] = str( game['linescore']['inningState'])[:3] else: game_rec['linescore']['inningState'] = str( game['linescore']['inningHalf'])[:3] else: game_rec['linescore'][ 'currentInningOrdinal'] = 'Not Started' game_rec['linescore']['inningState'] = '' else: game_rec['linescore']['currentInning'] = 'n/a' game_rec['linescore']['inningState'] = '' game_rec['linescore']['currentInningOrdinal'] = game_rec[ 'detailedState'] for teamtype in ('home', 'away'): # pprint.pprint(game['teams']) game_rec[teamtype] = dict() # seems to be two different formats for away/home team info(!) if 'name' in game['teams'][teamtype][ 'team'] and 'abbrev' in game['teams'][teamtype][ 'team']['name']: game_rec[teamtype] = { 'abbrev': str(game['teams'][teamtype]['team']['name'] ['abbrev']).lower(), 'display': str(game['teams'][teamtype]['team']['name'] ['display']), 'brief': str(game['teams'][teamtype]['team']['name']['brief']), 'full': str(game['teams'][teamtype]['team']['name']['full']), 'league': str(game['teams'][teamtype]['league']), 'division': str(game['teams'][teamtype]['division']), } elif 'abbreviation' in game['teams'][teamtype]['team']: game_rec[teamtype] = { 'abbrev': str(game['teams'][teamtype]['team'] ['abbreviation']).lower(), 'display': str(game['teams'][teamtype]['team']['shortName']), 'brief': str(game['teams'][teamtype]['team']['teamName']), 'full': str(game['teams'][teamtype]['team']['name']), 'league': 'n/a', 'division': 'n/a', } else: LOG.error("Unexpected game['teams'] for teamtype=%s", teamtype) pprint.pprint(game['teams'][teamtype]) game_rec[teamtype] = { 'abbrev': 'n/a', 'display': 'n/a', 'brief': 'n/a', 'full': 'n/a', 'league': 'n/a', 'division': 'n/a', } if 'linescore' in game and teamtype in game['linescore'][ 'teams'] and 'runs' in game['linescore']['teams'][ teamtype]: game_rec['linescore'][teamtype] = { 'runs': str(game['linescore']['teams'][teamtype]['runs']), 'hits': str(game['linescore']['teams'][teamtype]['hits']), 'errors': str(game['linescore']['teams'][teamtype]['errors']), } else: game_rec['linescore'][teamtype] = { 'runs': '0', 'hits': '0', 'errors': '0' } game_rec['favourite'] = is_fav(game_rec) game_rec['feed'] = dict() if game_rec['abstractGameState'] == 'Preview': continue # epg if 'media' in game['content'] and 'epg' in game['content']['media']: for media in game['content']['media']['epg']: if media['title'] == 'MLBTV': for stream in media['items']: if stream[ 'mediaFeedType'] != 'COMPOSITE' and stream[ 'mediaFeedType'] != 'ISO': feedtype = str(stream['mediaFeedType']).lower( ) # home, away, national, french, ... game_rec['feed'][feedtype] = dict() if 'mediaId' in stream: game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaId']) game_rec['feed'][feedtype][ 'mediaState'] = str( stream['mediaState']) game_rec['feed'][feedtype][ 'eventId'] = str(stream['id']) game_rec['feed'][feedtype][ 'callLetters'] = str( stream['callLetters']) if 'epgAlternate' in game['content']['media']: for media in game['content']['media']['epgAlternate']: if media['title'] == 'Extended Highlights': feedtype = 'condensed' if len(media['items']) > 0: game_rec['feed'][feedtype] = dict() stream = media['items'][0] game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) for playback_item in stream['playbacks']: if playback_item[ 'name'] == config.CONFIG.playback_scenario: game_rec['feed'][feedtype][ 'playback_url'] = playback_item[ 'url'] elif media['title'] == 'Daily Recap': feedtype = 'recap' if len(media['items']) > 0: game_rec['feed'][feedtype] = dict() stream = media['items'][0] game_rec['feed'][feedtype][ 'mediaPlaybackId'] = str( stream['mediaPlaybackId']) for playback_item in stream['playbacks']: if playback_item[ 'name'] == config.CONFIG.playback_scenario: game_rec['feed'][feedtype][ 'playback_url'] = playback_item[ 'url'] # elif media['title'] == 'Audio': # for stream in media['items']: # feedtype = 'audio-' + str(stream['mediaFeedType']).lower() # home, away, national, french, ... # game_rec['feed'][feedtype] = dict() # game_rec['feed'][feedtype]['mediaPlaybackId'] = str(stream['mediaId']) # game_rec['feed'][feedtype]['eventId'] = str(stream['id']) # game_rec['feed'][feedtype]['callLetters'] = str(stream['callLetters']) return game_records