def _fetch_json_from_url(url, overwrite_json=True, suffix=''): if suffix: suffix = '-' + suffix if config.SAVE_JSON_FILE_BY_TIMESTAMP: json_file = os.path.join( config.CONFIG.dir, 'mlbgamedata{}-{}.json'.format(suffix, time.strftime("%Y-%m-%d-%H%M"))) else: json_file = os.path.join(config.CONFIG.dir, 'mlbgamedata{}.json'.format(suffix)) if overwrite_json or not os.path.exists(json_file): LOG.debug('Getting url={} ...'.format(url)) # query nhl.com for today's schedule headers = { 'User-Agent': config.CONFIG.ua_iphone, 'Connection': 'close' } util.log_http(url, 'get', headers, sys._getframe().f_code.co_name) r = requests.get(url, headers=headers, cookies=auth.load_cookies(), verify=config.VERIFY_SSL) with open(json_file, 'w') as f: # write date to json_file f.write(r.text) with open(json_file) as games_file: json_data = json.load(games_file) return json_data
def login(): """ taken from plugin.video.mlbtv """ url = 'https://secure.mlb.com/pubajaxws/services/IdentityPointService' headers = { "SOAPAction": "http://services.bamnetworks.com/registration/identityPoint/identify", "Content-type": "text/xml; charset=utf-8", "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 6.0.1; Hub Build/MHC19J)", "Connection": "Keep-Alive" } payload = "<?xml version='1.0' encoding='UTF-8'?" payload += '<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">' payload += '<SOAP-ENV:Body><tns:identityPoint_identify_request xmlns:tns="http://services.bamnetworks.com/registration/types/1.4">' payload += '<tns:identification type="email-password"><tns:id xsi:nil="true"/>' payload += '<tns:fingerprint xsi:nil="true"/>' payload += '<tns:email>' payload += '<tns:id xsi:nil="true"/>' payload += '<tns:address>{}</tns:address>'.format( config.CONFIG.parser['username']) payload += '</tns:email>' payload += '<tns:password>{}</tns:password>'.format( config.CONFIG.parser['password']) payload += '<tns:mobilePhone xsi:nil="true"/>' payload += '<tns:profileProperty xsi:nil="true"/>' payload += '</tns:identification>' payload += '</tns:identityPoint_identify_request>' payload += '</SOAP-ENV:Body>' payload += '</SOAP-ENV:Envelope>' util.log_http(url, 'post', headers, sys._getframe().f_code.co_name) req = requests.post(url, headers=headers, data=payload, verify=config.VERIFY_SSL) """ Bad username => <status><code>-1000</code><message> [Invalid credentials for identification] [com.bamnetworks.registration.types.exception.IdentificationException: Account doesn't exits]</message><exceptionClass>com.bamnetworks.registration.types.exception.IdentificationException</exceptionClass><detail type="identityPoint" field="exists" message="false" messageKey="identityPoint.exists" /><detail type="identityPoint" field="email-password" message="identification error on identity point of type email-password" messageKey="identityPoint.email-password" /></status> Bad password => <status><code>-1000</code><message> [Invalid credentials for identification] [com.bamnetworks.registration.types.exception.IdentificationException: Invalid Password]</message><exceptionClass>com.bamnetworks.registration.types.exception.IdentificationException</exceptionClass><detail type="identityPoint" field="exists" message="true" messageKey="identityPoint.exists" /><detail type="identityPoint" field="email-password" message="identification error on identity point of type email-password" messageKey="identityPoint.email-password" /></status> Good => <status><code>1</code><message>OK</message></status> """ if find_text_in_str(req.text, '<code>', '</code>') != '1': LOG.debug('Login Error: r.text: %s', req.text) msg = find_text_in_str( req.text, 'com.bamnetworks.registration.types.exception.IdentificationException: ', ']</message>') util.die('Login Error: {}'.format(msg)) LOG.debug('Login successful') save_cookies(req.cookies)
def save_playlist_to_file(stream_url, media_auth): headers = { "Accept": "*/*", "Accept-Encoding": "identity", "Accept-Language": "en-US,en;q=0.8", "Connection": "keep-alive", "User-Agent": config.CONFIG.svc_user_agent, "Cookie": media_auth } util.log_http(stream_url, 'get', headers, sys._getframe().f_code.co_name) r = requests.get(stream_url, headers=headers, cookies=auth.load_cookies(), verify=config.VERIFY_SSL) playlist = r.text playlist_file = os.path.join( config.CONFIG.dir, 'playlist-{}.m3u8'.format(time.strftime("%Y-%m-%d"))) LOG.debug('writing playlist to: {}'.format(playlist_file)) with open(playlist_file, 'w') as f: f.write(playlist) LOG.debug('save_playlist_to_file: {}'.format(playlist))
def get_session_key(game_pk, event_id, content_id, auth_cookie): """ game_pk: game_pk event_id: eventId content_id: mediaPlaybackId """ raise Exception("Not implemented") session_key_file = os.path.join(config.CONFIG.dir, 'sessionkey') if os.path.exists(session_key_file): if datetime.today() - datetime.fromtimestamp( os.path.getmtime(session_key_file)) < timedelta(days=1): with open(session_key_file, 'r') as f: for line in f: session_key = line.strip() LOG.debug( 'Using cached session key: {}'.format(session_key)) return session_key LOG.debug("Requesting session key") epoch_time_now = str(int(round(time.time() * 1000))) url = 'https://mf.svc.nhl.com/ws/media/mf/v2.4/stream?eventId={}&format=json&platform={}&subject=NHLTV&_={}' url = url.format(event_id, config.CONFIG.platform, epoch_time_now) headers = { "Accept": "application/json", "Accept-Encoding": "identity", "Accept-Language": "en-US,en;q=0.8", "Connection": "keep-alive", "Authorization": auth_cookie, "User-Agent": config.CONFIG.ua_pc, "Origin": "https://www.nhl.com", "Referer": "https://www.nhl.com/tv/{}/{}/{}".format(game_pk, event_id, content_id) } util.log_http(url, 'get', headers, sys._getframe().f_code.co_name) r = requests.get(url, headers=headers, cookies=load_cookies(), verify=config.VERIFY_SSL) json_source = r.json() LOG.debug('Session key json: {}'.format(json_source)) if json_source['status_code'] == 1: if json_source['user_verified_event'][0]['user_verified_content'][0][ 'user_verified_media_item'][0]['blackout_status'][ 'status'] == 'BlackedOutStatus': session_key = 'blackout' LOG.debug('Event blacked out: {}'.format( json_source['user_verified_event'][0]['user_verified_content'] [0]['user_verified_media_item'][0])) else: session_key = str(json_source['session_key']) else: msg = json_source['status_message'] util.die('Could not get session key: {}'.format(msg)) LOG.debug('Retrieved session key: {}'.format(session_key)) update_session_key(session_key) return session_key
def nhl_login(): """Authenticates user to nhl site.""" url = 'https://user.svc.nhl.com/oauth/token?grant_type=client_credentials' headers = { "Accept": "application/json", "Accept-Encoding": "identity", "Accept-Language": "en-US,en;q=0.8", "User-Agent": config.CONFIG.ua_pc, "Origin": "https://www.nhl.com", "Authorization": "Basic d2ViX25obC12MS4wLjA6MmQxZDg0NmVhM2IxOTRhMThlZjQwYWM5ZmJjZTk3ZTM=", } userid = config.CONFIG.parser['username'] passwd = config.CONFIG.parser['password'] use_rogers = config.CONFIG.parser.getboolean('use_rogers', False) util.log_http(url, 'post', headers, sys._getframe().f_code.co_name) r = requests.post(url, headers=headers, data='', cookies=load_cookies(), verify=config.VERIFY_SSL) if r.status_code >= 400: util.die("Authorization cookie couldn't be downloaded.") json_source = r.json() if get_auth_cookie() is not None: LOG.debug('login: already logged in (we have a valid cookie)') return auth_cookie = json_source['access_token'] if use_rogers: LOG.info("Logging in via Rogers") url = 'https://activation-rogers.svc.nhl.com/ws/subscription/flow/rogers.login' login_data = '{"rogerCredentials":{"email":%s,"password":%s}}' % ( userid, passwd) # referer = "https://www.nhl.com/login/rogers" else: LOG.info("Logging in via NHL") url = 'https://user.svc.nhl.com/v2/user/identity' login_data = '{"email":{"address":%s},"type":"email-password","password":{"value":%s}}' % ( userid, passwd) headers = { "Accept": "*/*", "Accept-Encoding": "identity", "Accept-Language": "en-US,en;q=0.8", "Content-Type": "application/json", "Authorization": auth_cookie, "Connection": "keep-alive", "User-Agent": config.CONFIG.ua_pc } util.log_http(url, 'post', headers, sys._getframe().f_code.co_name) r = requests.post(url, headers=headers, data=login_data, cookies=load_cookies(), verify=config.VERIFY_SSL) if r.status_code >= 400: try: json_source = r.json() msg = json_source['message'] except Exception as e: msg = "Please check that your username and password are correct" LOG.debug('Login Error: json_source: {}'.format(json_source)) util.die('Login Error: {}'.format(msg)) LOG.debug('Login successful') save_cookies(r.cookies)
def fetch_stream(game_pk, content_id, event_id): """ game_pk: game_pk event_id: eventId content_id: mediaPlaybackId """ stream_url = None media_auth = None auth_cookie = auth.get_auth_cookie() if auth_cookie is None: LOG.error("fetch_stream: not logged in") return stream_url, media_auth session_key = auth.get_session_key(game_pk, event_id, content_id, auth_cookie) if session_key is None: return stream_url, media_auth elif session_key == 'blackout': msg = ( 'The game you are trying to access is not currently available due to local ' 'or national blackout restrictions.\n' ' Full game archives will be available 48 hours after completion of this game.' ) LOG.info('Game Blacked Out: {}'.format(msg)) return stream_url, media_auth url = config.CONFIG.mf_svc_url url += '?contentId=' + content_id url += '&playbackScenario=' + config.CONFIG.playback_scenario url += '&platform=' + config.CONFIG.platform url += '&sessionKey=' + urllib.parse.quote_plus(session_key) # Get user set CDN if config.CONFIG.parser['cdn'] == 'akamai': url += '&cdnName=MED2_AKAMAI_SECURE' elif config.CONFIG.parser['cdn'] == 'level3': url += '&cdnName=MED2_LEVEL3_SECURE' headers = { "Accept": "*/*", "Accept-Encoding": "identity", "Accept-Language": "en-US,en;q=0.8", "Connection": "keep-alive", "Authorization": auth_cookie, "User-Agent": config.CONFIG.svc_user_agent, "Proxy-Connection": "keep-alive" } util.log_http(url, 'get', headers, sys._getframe().f_code.co_name) r = requests.get(url, headers=headers, cookies=auth.load_cookies(), verify=config.VERIFY_SSL) json_source = r.json() if json_source['status_code'] == 1: media_item = json_source['user_verified_event'][0][ 'user_verified_content'][0]['user_verified_media_item'][0] if media_item['blackout_status']['status'] == 'BlackedOutStatus': msg = ( 'The game you are trying to access is not currently available due to local ' 'or national blackout restrictions.\n' 'Full game archives will be available 48 hours after completion of this game.' ) util.die('Game Blacked Out: {}'.format(msg)) elif media_item['auth_status'] == 'NotAuthorizedStatus': msg = 'You do not have an active subscription. To access this content please purchase a subscription.' util.die('Account Not Authorized: {}'.format(msg)) else: stream_url = media_item['url'] media_auth = '{}={}'.format( str(json_source['session_info']['sessionAttributes'][0] ['attributeName']), str(json_source['session_info']['sessionAttributes'][0] ['attributeValue'])) session_key = json_source['session_key'] auth.update_session_key(session_key) else: msg = json_source['status_message'] util.die('Error Fetching Stream: {}', msg) LOG.debug('fetch_stream stream_url: ' + stream_url) LOG.debug('fetch_stream media_auth: ' + media_auth) return stream_url, media_auth
def display_standings(standings_type, display_title, date_str, rank_tag='divisionRank', header_tags=('league', 'division')): headers = {'User-Agent': config.CONFIG.ua_iphone, 'Connection': 'close'} season_str = datetime.strftime(datetime.strptime(date_str, "%Y-%m-%d"), "%Y") url = STANDINGS_URL.format(standings_type=standings_type, league_ids='103,104', season=season_str, date=date_str) util.log_http(url, 'get', headers, sys._getframe().f_code.co_name) resp = requests.get(url, headers=headers, verify=config.VERIFY_SSL) json_file = os.path.join(config.CONFIG.dir, 'standings.json') with open(json_file, 'w') as f: # write date to json_file f.write(resp.text) json_data = resp.json() outl = list() if display_title != '': outl.append( '{color_on}{name:22}\t{win:>3} {loss:>3} {pct:<5} {gb:<4} {wgb:<4} {streak}{color_off}' .format(color_on=util.ANSI_CONTROL_CODES['bold'], name=' ====== {} ======'.format(display_title), win='W', loss='L', pct='PCT', gb='GB', wgb='WGB', streak='Streak', color_off=util.ANSI_CONTROL_CODES['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 = '--- ' + header + ' ---' 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 = util.fg_ansi_colour( config.CONFIG.parser['fav_colour']) color_off = util.ANSI_CONTROL_CODES['reset'] outl.append( '{color_on}{rank:2} {clinch}{name:22}\t{win:3} {loss:3} {pct:5} {gb:4} {wgb:4} [{streak}]{color_off}' .format(color_on=color_on, rank=rank, clinch=clinch, name=teamrec['team']['name'], win=teamrec['leagueRecord']['wins'], loss=teamrec['leagueRecord']['losses'], pct=teamrec['leagueRecord']['pct'], gb=teamrec['gamesBack'], wgb=teamrec['wildCardGamesBack'], streak=teamrec['streak']['streakCode'], color_off=color_off)) print('\n'.join(outl))