def season_Menu(): xbmcplugin.setContent(int(sys.argv[1]), 'seasons') slug = vars.params.get("slug") serie_title = vars.params.get("serie_title") page = int(vars.params.get("page", 1)) per_page = 20 utils.log("seasonListMenu: tag is %s, page is %d" % (slug, page), xbmc.LOGDEBUG) base_url = "https://content-api-prod.nba.com/public/1/endeavor/video-list/nba-tv-series/%s?" params = urlencode({ "sort": "releaseDate desc", "page": page, "count": per_page }) url = base_url % slug + params response = utils.stringify(urllib2.urlopen(url).read()) utils.log("seasonListMenu: response: %s" % response, xbmc.LOGDEBUG) jsonresponse = json.loads(response) seasonicon = jsonresponse['results']['series']['coverImage']['portrait'] # idx is the index of the season in the json data # to do: avoid fetching the same page for season and episodes idx = 0 for season in jsonresponse['results']['seasons']: name = 'Season %s' % season['season'] common.addListItem(name, '', 'nba_tv_episode', seasonicon, isfolder=True, customparams={'url':url, 'seasonidx': idx, 'serie_title': serie_title}) idx = idx +1
def episode_menu(): et_tz = pytz.timezone('US/Eastern') date_et = common.get_date() if vars.params.get('custom_date', False) else utils.tznow(et_tz).date() # Avoid possible caching by using query string epg_url = 'https://nlnbamdnyc-a.akamaihd.net/fs/nba/feeds/epg/%d/%d_%d.js?t=%d' % ( date_et.year, date_et.month, date_et.day, time.time()) response = utils.fetch(epg_url) g_epg = json.loads(response[response.find('['):]) for epg_item in g_epg: entry = epg_item['entry'] start_et_hours, start_et_minutes = map(int, entry['start'].split(':')) duration_hours, duration_minutes = map(int, entry['duration'].split(':')) dt_et = et_tz.localize(datetime.datetime(date_et.year, date_et.month, date_et.day, start_et_hours, start_et_minutes)) dt_utc = dt_et.astimezone(pytz.utc) start_timestamp = int((dt_utc - datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()) * 1000 # in milliseconds duration = (duration_hours * 60 + duration_minutes) * 60 * 1000 # in milliseconds params = { 'start_timestamp': start_timestamp, 'duration': duration, } utils.log(params, xbmc.LOGDEBUG) name = '%s %s: %s' % ( entry['start'], dt_et.tzname(), entry['showTitle'] if entry['showTitle'] else entry['title']) common.addListItem(name, '', 'nba_tv_play_episode', iconimage=entry['image'], customparams=params)
def episodes_list_Menu(): xbmcplugin.setContent(int(sys.argv[1]), 'episodes') url = vars.params.get("url") serie_title = vars.params.get("serie_title") seasonidx = int(vars.params.get("seasonidx")) response = utils.stringify(urllib2.urlopen(url).read()) utils.log("episodeListMenu: response: %s" % response, xbmc.LOGDEBUG) jsonresponse = json.loads(response) episodes = jsonresponse['results']['seasons'][seasonidx]['episodes'] for episode in episodes: name = episode['title'] release_date = episode['releaseDate'].split('T')[0] plot = episode['description'] runtime = episode['program']['runtimeHours'].split(':') seconds = int(runtime[-1]) minutes = int(runtime[-2]) duration = minutes * 60 + seconds if len(runtime) == 3: hours = int(runtime[0]) duration = duration + hours * 3600 thumb = episode['image'] infoList = { "mediatype": "episode", "title": name, "TVShowTitle": serie_title, "duration": duration, "plot": plot, "aired":str(release_date) } common.addListItem(url=str(episode['program']['id']), name=name, mode='nba_tv_play_serieepisode', iconimage=thumb, infoList=infoList) xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
def nba_tv_videoMenu(): xbmcplugin.setContent(int(sys.argv[1]), 'videos') url = "https://content-api-prod.nba.com/public/1/endeavor/layout/watch/nbatv" json_parser = json.loads(utils.stringify(urllib2.urlopen(url).read())) for category in json_parser['results']['carousels']: if category['type'] == "video_carousel": common.addListItem(category['title'], '', 'nba_tv_videoplay', category['value']['videos'][0]['image'], True, customparams={'slug':category['value']['slug'], 'pagination': True}) elif category['type'] == "collection_cards": for collection in category['value']['items']: common.addListItem(collection['name'], '', 'nba_tv_videoplay', collection['image'], True, customparams={'slug':collection['slug'], 'pagination': True})
def episode_menu(): if vars.params.get("custom_date", False): date = datetime.datetime.combine( common.getDate(), datetime.time(hour=4, minute=0, second=0)) else: date = utils.nowEST().replace(hour=4, minute=0, second=0) utils.log("date for episodes: %s (from %s)" % (date, utils.nowEST()), xbmc.LOGDEBUG) schedule = 'https://nlnbamdnyc-a.akamaihd.net/fs/nba/feeds/epg/2019/%s_%s.js?t=%d' % ( date.month, date.day, time.time()) utils.log('Requesting %s' % schedule, xbmc.LOGDEBUG) now_timestamp = int(calendar.timegm(date.timetuple())) now_timestamp_milliseconds = now_timestamp * 1000 req = urllib2.Request(schedule, None) response = str(urllib2.urlopen(req).read()) json_response = json.loads(response[response.find("["):]) for entry in json_response: entry = entry['entry'] start_hours, start_minutes = entry['start'].split(':') start_timestamp_milliseconds = now_timestamp_milliseconds + ( int(start_hours) * 60 * 60 + int(start_minutes) * 60) * 1000 utils.log( "date for episode %s: %d (from %d)" % (entry['title'], start_timestamp_milliseconds, now_timestamp_milliseconds), xbmc.LOGDEBUG) duration_hours, duration_minutes = entry['duration'].split(":") duration_milliseconds = (int(duration_hours) * 60 * 60 + int(duration_minutes) * 60) * 1000 params = { 'duration': duration_milliseconds, 'start_timestamp': start_timestamp_milliseconds } name = "%s - %s (%s)" % (entry['start'], entry['title'], entry['duration']) common.addListItem(name, '', 'nbatvliveepisode', iconimage=entry['image'], customparams=params)
def series_Menu(): xbmcplugin.setContent(int(sys.argv[1]), 'tvshows') url = "https://content-api-prod.nba.com/public/1/endeavor/video-list/nba-tv-series" json_parser = json.loads(utils.stringify(urllib2.urlopen(url).read())) for serie in json_parser['results']: name = serie['series']['name'] plot = serie['series']['description'] slug = serie['series']['slug'] thumb = serie['series']['coverImage']['portrait'] infoList = { "mediatype": "tvshow", "title": name, "TVShowTitle": name, "plot": plot } common.addListItem( name, '', 'nba_tv_seasons', thumb, isfolder=True, customparams={'slug': slug, 'video_type': 'nba-tv-series', 'serie_title': name, 'pagination': True}, infoList=infoList)
def nba_tv_videoPlay(): xbmcplugin.setContent(int(sys.argv[1]), 'videos') slug = vars.params.get("slug") page = int(vars.params.get("page", 1)) per_page = 22 utils.log("nba_tv_videoPlay: collection is %s, page is %d" % (slug, page), xbmc.LOGDEBUG) base_url = "https://content-api-prod.nba.com/public/1/endeavor/video-list/collection/%s?" params = urlencode({ "sort": "releaseDate desc", "page": page, "count": per_page }) url = base_url % slug + params utils.log("nba_tv_videoPlay: %s: url of collection is %s" % (slug, url), xbmc.LOGDEBUG) response = utils.stringify(urllib2.urlopen(url).read()) utils.log("nba_tv_videoPlay: response: %s" % response, xbmc.LOGDEBUG) jsonresponse = json.loads(response) for video in jsonresponse['results']['videos']: name = video['title'] entitlement = video['entitlements'] release_date = video['releaseDate'].split('T')[0] plot = video['description'] thumb = video['image'] runtime = video['program']['runtimeHours'].split(':') seconds = int(runtime[-1]) minutes = int(runtime[-2]) duration = minutes * 60 + seconds if len(runtime) == 3: hours = int(runtime[0]) duration = duration + hours * 3600 infoList = { "mediatype": "video", "title": name, "duration": duration, "plot": plot, "aired":str(release_date) } if entitlement == 'free': common.addListItem(url=str(video['program']['id']), name=name, mode='videoplay', iconimage=thumb, infoList=infoList) else: common.addListItem(url=str(video['program']['id']), name=name, mode='nba_tv_play_serieepisode', iconimage=thumb, infoList=infoList) if vars.params.get("pagination") and page+1 <= jsonresponse['results']['pages']: next_page_name = xbmcaddon.Addon().getLocalizedString(50008) # Add "next page" link custom_params = { 'slug': slug, 'page': page + 1, 'pagination': True } common.addListItem(next_page_name, '', 'nba_tv_videolist', '', True, customparams=custom_params) xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
def menu(): common.addListItem('Live', '', 'nba_tv_play_live', '') common.addListItem('Today\'s programming', '', 'nba_tv_episode_menu', '', isfolder=True) common.addListItem('Select date', '', 'nba_tv_episode_menu', '', isfolder=True, customparams={'custom_date': True})
def chooseGameVideoMenu(): video_id = vars.params.get("video_id") video_type = vars.params.get("video_type") seo_name = vars.params.get("seo_name") has_away_feed = vars.params.get("has_away_feed", "0") == "1" has_condensed_game = vars.params.get("has_condensed_game", "0") == "1" start_time = vars.params.get("start_time") duration = vars.params.get("duration") game_data_json = utils.fetch_json(vars.config['game_data_endpoint'] % seo_name) game_state = game_data_json['gameState'] game_home_team = vars.params.get("home_team") game_visitor_team = vars.params.get("visitor_team") game_cameras = [] if 'multiCameras' in game_data_json: game_cameras = game_data_json['multiCameras'].split(",") nba_config = utils.fetch_json(vars.config['config_endpoint']) nba_cameras = {} for camera in nba_config['content']['cameras']: nba_cameras[ camera['number'] ] = camera['name'] if has_away_feed: # Create the "Home" and "Away" list items for ishomefeed in [True, False]: listitemname = "Full game, " + ("away feed" if not ishomefeed else "home feed") # Show actual team names instead of 'home feed' and 'away feed' if game_home_team and game_visitor_team: if ishomefeed: listitemname += " (" + game_home_team + ")" else: listitemname += " (" + game_visitor_team + ")" params = { 'video_id': video_id, 'video_type': video_type, 'video_ishomefeed': 1 if ishomefeed else 0, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } common.addListItem(listitemname, url="", mode="playgame", iconimage="", customparams=params) else: #Add a "Home" list item params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } common.addListItem("Full game", url="", mode="playgame", iconimage="", customparams=params) if vars.show_cameras: utils.log(nba_cameras, xbmc.LOGDEBUG) utils.log(game_cameras, xbmc.LOGDEBUG) # Add all the cameras available for camera_number in game_cameras: camera_number = int(camera_number) # Skip camera number 0 (broadcast?) - the full game links are the same if camera_number == 0: continue params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'camera_number': camera_number, 'start_time': start_time, 'duration': duration, } name = "Camera %d: %s" % (camera_number, nba_cameras.get(camera_number, 'Unknown')) common.addListItem(name, url="", mode="playgame", iconimage="", customparams=params) # Live games have no condensed or highlight link if video_type != "live": # Create the "Condensed" list item if has_condensed_game: params = { 'video_id': video_id, 'video_type': 'condensed', 'game_state': game_state } common.addListItem("Condensed game", url="", mode="playgame", iconimage="", customparams=params) # Get the highlights video if available highlights_url = getHighlightGameUrl(video_id) if highlights_url: common.addVideoListItem("Highlights", highlights_url, iconimage="") xbmcplugin.endOfDirectory(handle=int(sys.argv[1]))
def addGamesLinks(date = '', video_type = "archive"): try: now_datetime_est = utils.nowEST() schedule = 'https://nlnbamdnyc-a.akamaihd.net/fs/nba/feeds_s2019/schedule/%04d/%d_%d.js?t=%d' % \ (date.year, date.month, date.day, time.time()) utils.log('Requesting %s' % schedule, xbmc.LOGDEBUG) schedule_request = urllib2.Request(schedule, None) schedule_response = str(urllib2.urlopen(schedule_request).read()) schedule_json = json.loads(schedule_response[schedule_response.find("{"):]) unknown_teams = {} for index, daily_games in enumerate(schedule_json['games']): utils.log("daily games for day %d are %s" % (index, daily_games), xbmc.LOGDEBUG) for game in daily_games: h = game.get('h', '') v = game.get('v', '') game_id = game.get('id', '') game_start_date_est = game.get('d', '') vs = game.get('vs', '') hs = game.get('hs', '') name = game.get('name', '') image = game.get('image', '') seo_name = game.get("seoName", "") has_condensed_video = game.get("video", {}).get("c", False) has_away_feed = False video_details = game.get('video', {}) has_away_feed = bool(video_details.get("af", {})) # Try to convert start date to datetime try: game_start_datetime_est = datetime.datetime.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f" ) except: game_start_datetime_est = datetime.datetime.fromtimestamp(time.mktime(time.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f"))) #Set game start date in the past if python can't parse the date #so it doesn't get flagged as live or future game and you can still play it #if a video is available if type(game_start_datetime_est) is not datetime.datetime: game_start_datetime_est = now_datetime_est + timedelta(-30) #guess end date by adding 4 hours to start date game_end_datetime_est = game_start_datetime_est + timedelta(hours=4) # Get playoff game number, if available playoff_game_number = 0 playoff_status = "" if 'playoff' in game: playoff_home_wins = int(game['playoff']['hr'].split("-")[0]) playoff_visitor_wins = int(game['playoff']['vr'].split("-")[0]) playoff_status = "%d-%d" % (playoff_visitor_wins, playoff_home_wins) playoff_game_number = playoff_home_wins + playoff_visitor_wins if game_id != '': # Get pretty names for the team names [visitor_name, host_name] = [vars.config['teams'].get(t.lower(), t) for t in [v, h]] [unknown_teams.setdefault(t, []).append(game_start_datetime_est.strftime("%Y-%m-%d")) for t in [v, h] if t.lower() not in vars.config['teams']] has_video = "video" in game future_video = game_start_datetime_est > now_datetime_est and \ game_start_datetime_est.date() == now_datetime_est.date() live_video = game_start_datetime_est < now_datetime_est < game_end_datetime_est # Create the title if host_name and visitor_name: name = game_start_datetime_est.strftime("%Y-%m-%d") if video_type == "live": name = utils.toLocalTimezone(game_start_datetime_est).strftime("%Y-%m-%d (at %I:%M %p)") # Add the teams' names and the scores if needed name += ' %s vs %s' % (visitor_name, host_name) if playoff_game_number != 0: name += ' (game %d)' % (playoff_game_number) if vars.show_scores and not future_video: name += ' %s:%s' % (str(vs), str(hs)) if playoff_status: name += " (series: %s)" % playoff_status thumbnail_url = utils.generateCombinedThumbnail(v, h) elif image: thumbnail_url = "https://nbadsdmt.akamaized.net/media/nba/nba/thumbs/%s" % image if video_type == "live": if future_video: name = "UPCOMING: " + name elif live_video: name = "LIVE: " + name add_link = True if video_type == "live" and not (live_video or future_video): add_link = False elif video_type != "live" and (live_video or future_video): add_link = False elif not future_video and not has_video: add_link = False if add_link == True: params = { 'video_id': game_id, 'video_type': video_type, 'seo_name': seo_name, 'visitor_team': visitor_name, 'home_team': host_name, 'has_away_feed': 1 if has_away_feed else 0, 'has_condensed_game': 1 if has_condensed_video else 0, } if 'st' in game: start_time = calendar.timegm(time.strptime(game['st'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['start_time'] = start_time if 'et' in game: end_time = calendar.timegm(time.strptime(game['et'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time else: # create my own et for game (now) end_time = str(datetime.datetime.now()).replace(' ', 'T') end_time = calendar.timegm(time.strptime(end_time, '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time # Add a directory item that contains home/away/condensed items common.addListItem(name, url="", mode="gamechoosevideo", iconimage=thumbnail_url, isfolder=True, customparams=params) if unknown_teams: utils.log("Unknown teams: %s" % str(unknown_teams), xbmc.LOGWARNING) except Exception, e: utils.littleErrorPopup("Error: %s" % str(e)) utils.log(traceback.format_exc(), xbmc.LOGDEBUG) pass
def menu(): common.addListItem('Live', '', 'nba_tv_play_live', '') common.addListItem('Today\'s programming', '', 'nba_tv_episode_menu', '', isfolder=True) common.addListItem('Select date', '', 'nba_tv_episode_menu', '', isfolder=True, customparams={ 'custom_date': True }) common.addListItem('NBA TV Series', '', 'nba_tv_series', '', isfolder=True) common.addListItem('Video Collections', '', 'nba_tv_videolist', '', isfolder=True, customparams={ 'url': 'https://content-api-prod.nba.com/public/1/endeavor/layout/watch/nbatv' }) common.addListItem('NBA TV Clips', '', 'videolist', '', True, customparams={ 'video_tag':'nba-tv-clips', 'pagination': True })
def chooseGameVideoMenu(): video_id = vars.params.get("video_id") video_type = vars.params.get("video_type") seo_name = vars.params.get("seo_name") has_away_feed = vars.params.get("has_away_feed", "0") == "1" has_condensed_game = vars.params.get("has_condensed_game", "0") == "1" start_time = vars.params.get("start_time") duration = vars.params.get("duration") game_data_json = Request.getJson(vars.config['game_data_endpoint'] % seo_name) game_state = game_data_json['gameState'] game_home_team = vars.params.get("home_team") game_visitor_team = vars.params.get("visitor_team") game_cameras = [] if 'multiCameras' in game_data_json: game_cameras = game_data_json['multiCameras'].split(",") nba_config = Request.getJson(vars.config['config_endpoint']) nba_cameras = {} for camera in nba_config['content']['cameras']: nba_cameras[ camera['number'] ] = camera['name'] if has_away_feed: # Create the "Home" and "Away" list items for ishomefeed in [True, False]: listitemname = "Full game, " + ("away feed" if not ishomefeed else "home feed") # Show actual team names instead of 'home feed' and 'away feed' if game_home_team and game_visitor_team: if ishomefeed: listitemname += " (" + game_home_team + ")" else: listitemname += " (" + game_visitor_team + ")" params = { 'video_id': video_id, 'video_type': video_type, 'video_ishomefeed': 1 if ishomefeed else 0, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } common.addListItem(listitemname, url="", mode="playgame", iconimage="", customparams=params) else: #Add a "Home" list item params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } common.addListItem("Full game", url="", mode="playgame", iconimage="", customparams=params) if vars.show_cameras: #Add all the cameras available for camera_number in game_cameras: #Skip camera number 0 (broadcast?) - the full game links are the same camera_number = int(camera_number) if camera_number == 0: continue params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'camera_number': camera_number, 'start_time': start_time, 'duration': duration, } name = "Camera %d: %s" % (camera_number, nba_cameras[camera_number]) common.addListItem(name , url="", mode="playgame", iconimage="", customparams=params) #Live games have no condensed or highlight link if video_type != "live": # Create the "Condensed" list item if has_condensed_game: params = { 'video_id': video_id, 'video_type': 'condensed', 'game_state': game_state } common.addListItem("Condensed game", url="", mode="playgame", iconimage="", customparams=params) # Get the highlights video if available highlights_url = getHighlightGameUrl(video_id) if highlights_url: common.addVideoListItem("Highlights", highlights_url, iconimage="") xbmcplugin.endOfDirectory(handle = int(sys.argv[1]) )
def addGamesLinks(date = '', video_type = "archive"): try: now_datetime_est = utils.nowEST() #example: http://smb.cdnak.neulion.com/fs/nba/feeds_s2012/schedule/2013/10_7.js?t=1381054350000 schedule = 'http://smb.cdnak.neulion.com/fs/nba/feeds_s2012/schedule/%04d/%d_%d.js?t=%d' % \ (date.year, date.month, date.day, time.time()) utils.log('Requesting %s' % schedule, xbmc.LOGDEBUG) schedule_request = urllib2.Request(schedule, None) schedule_response = str(urllib2.urlopen(schedule_request).read()) schedule_json = json.loads(schedule_response[schedule_response.find("{"):]) unknown_teams = {} for index, daily_games in enumerate(schedule_json['games']): utils.log("daily games for day %d are %s" % (index, daily_games), xbmc.LOGDEBUG) for game in daily_games: h = game.get('h', '') v = game.get('v', '') game_id = game.get('id', '') game_start_date_est = game.get('d', '') vs = game.get('vs', '') hs = game.get('hs', '') name = game.get('name', '') image = game.get('image', '') seo_name = game.get("seoName", "") has_condensed_video = game.get("video", {}).get("c", False) has_away_feed = False video_details = game.get('video', {}) has_away_feed = bool(video_details.get("af", {})) # Try to convert start date to datetime try: game_start_datetime_est = datetime.datetime.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f" ) except: game_start_datetime_est = datetime.datetime.fromtimestamp(time.mktime(time.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f"))) #Set game start date in the past if python can't parse the date #so it doesn't get flagged as live or future game and you can still play it #if a video is available if type(game_start_datetime_est) is not datetime.datetime: game_start_datetime_est = now_datetime_est + timedelta(-30) #guess end date by adding 4 hours to start date game_end_datetime_est = game_start_datetime_est + timedelta(hours=4) # Get playoff game number, if available playoff_game_number = 0 playoff_status = "" if 'playoff' in game: playoff_home_wins = int(game['playoff']['hr'].split("-")[0]) playoff_visitor_wins = int(game['playoff']['vr'].split("-")[0]) playoff_status = "%d-%d" % (playoff_visitor_wins, playoff_home_wins) playoff_game_number = playoff_home_wins + playoff_visitor_wins if game_id != '': # Get pretty names for the team names [visitor_name, host_name] = [vars.config['teams'].get(t.lower(), t) for t in [v, h]] [unknown_teams.setdefault(t, []).append(game_start_datetime_est.strftime("%Y-%m-%d")) for t in [v, h] if t.lower() not in vars.config['teams']] has_video = "video" in game future_video = game_start_datetime_est > now_datetime_est and \ game_start_datetime_est.date() == now_datetime_est.date() live_video = game_start_datetime_est < now_datetime_est < game_end_datetime_est # Create the title if host_name and visitor_name: name = game_start_datetime_est.strftime("%Y-%m-%d") if video_type == "live": name = utils.toLocalTimezone(game_start_datetime_est).strftime("%Y-%m-%d (at %I:%M %p)") # Add the teams' names and the scores if needed name += ' %s vs %s' % (visitor_name, host_name) if playoff_game_number != 0: name += ' (game %d)' % (playoff_game_number) if vars.show_scores and not future_video: name += ' %s:%s' % (str(vs), str(hs)) if playoff_status: name += " (series: %s)" % playoff_status thumbnail_url = utils.generateCombinedThumbnail(v, h) elif image: thumbnail_url = "https://neulionmdnyc-a.akamaihd.net/u/nba/nba/thumbs/%s" % image if video_type == "live": if future_video: name = "UPCOMING: " + name elif live_video: name = "LIVE: " + name add_link = True if video_type == "live" and not (live_video or future_video): add_link = False elif video_type != "live" and (live_video or future_video): add_link = False elif not future_video and not has_video: add_link = False if add_link == True: params = { 'video_id': game_id, 'video_type': video_type, 'seo_name': seo_name, 'visitor_team': visitor_name, 'home_team': host_name, 'has_away_feed': 1 if has_away_feed else 0, 'has_condensed_game': 1 if has_condensed_video else 0, } if 'st' in game: start_time = calendar.timegm(time.strptime(game['st'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['start_time'] = start_time if 'et' in game: end_time = calendar.timegm(time.strptime(game['et'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time else: # create my own et for game (now) end_time = str(datetime.datetime.now()).replace(' ', 'T') end_time = calendar.timegm(time.strptime(end_time, '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time # Add a directory item that contains home/away/condensed items common.addListItem(name, url="", mode="gamechoosevideo", iconimage=thumbnail_url, isfolder=True, customparams=params) if unknown_teams: utils.log("Unknown teams: %s" % str(unknown_teams), xbmc.LOGWARNING) except Exception, e: utils.littleErrorPopup("Error: %s" % str(e)) utils.log(traceback.format_exc(), xbmc.LOGDEBUG) pass
def chooseGameVideoMenu(playlist=None, paramsX=None, in_a_hurry=False): if paramsX is None: paramsX = vars.params video_id = paramsX.get("video_id") video_type = paramsX.get("video_type") seo_name = paramsX.get("seo_name") has_away_feed = paramsX.get("has_away_feed", "0") == "1" has_condensed_game = paramsX.get("has_condensed_game", "0") == "1" start_time = paramsX.get("start_time") duration = paramsX.get("duration") game_data_json = json.loads(utils.fetch(vars.config['game_data_endpoint'] % seo_name)) game_state = game_data_json['gameState'] game_home_team = paramsX.get("home_team") game_visitor_team = paramsX.get("visitor_team") game_cameras = [] foldername = paramsX.get("foldername") iconimage = paramsX.get('iconimage', "") if 'multiCameras' in game_data_json: game_cameras = game_data_json['multiCameras'].split(",") nba_config = json.loads(utils.fetch(vars.config['config_endpoint'])) nba_cameras = {} for camera in nba_config['content']['cameras']: nba_cameras[camera['number']] = camera['name'] streams = [] if has_away_feed: # Create the "Home" and "Away" list items for ishomefeed in [True, False]: listitemname = "Full game, " + ("away feed" if not ishomefeed else "home feed") # Show actual team names instead of 'home feed' and 'away feed' if game_home_team and game_visitor_team: if ishomefeed: listitemname += " (" + game_home_team + ")" else: listitemname += " (" + game_visitor_team + ")" params = { 'video_id': video_id, 'video_type': video_type, 'video_ishomefeed': 1 if ishomefeed else 0, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } if playlist is None: common.addListItem(listitemname, url="", mode="playgame", iconimage=iconimage, customparams=params) else: streams.append([True, foldername + ' - ' + listitemname, get_link(url="", mode="playgame", customparams=params)]) else: # Add a "Home" list item params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'start_time': start_time, 'duration': duration, } if playlist is None: common.addListItem("Full game", url="", mode="playgame", iconimage=iconimage, customparams=params) else: streams.append([True, foldername + ' - Full game', get_link(url="", mode="playgame", customparams=params)]) if vars.show_cameras: utils.log(nba_cameras, xbmc.LOGDEBUG) utils.log(game_cameras, xbmc.LOGDEBUG) # Add all the cameras available for camera_number in game_cameras: camera_number = int(camera_number) # Skip camera number 0 (broadcast?) - the full game links are the same if camera_number == 0: continue params = { 'video_id': video_id, 'video_type': video_type, 'game_state': game_state, 'camera_number': camera_number, 'start_time': start_time, 'duration': duration, } name = "Camera %d: %s" % (camera_number, nba_cameras.get(camera_number, 'Unknown')) if playlist is None: common.addListItem(name, url="", mode="playgame", iconimage=iconimage, customparams=params) elif " ESPN" in name or " ABC" in name or " TNT" in name: #only interesting additional streams (also or "NBA TV" in name?), but not e.g. Spanish (ESPN) streams.append([True, foldername + ' - ' + name, get_link(url="", mode="playgame", customparams=params)]) # Live games have no condensed or highlight link if video_type != "live": # Create the "Condensed" list item params = { 'video_id': video_id, 'video_type': 'condensed', 'game_state': game_state, } if has_condensed_game: if playlist is None: common.addListItem("Condensed game", url="", mode="playgame", iconimage=iconimage, customparams=params) if playlist is not None: #manually add to playlist anyways, maybe will come online later... streams.append([False, foldername + ' - Condensed game', get_link(url="", mode="playgame", customparams=params)]) # Get the highlights video if available highlights_url = getHighlightGameUrl(video_id) if highlights_url: if playlist is None: common.addVideoListItem("Highlights", highlights_url, iconimage=iconimage) else: streams.append([False, foldername + ' - Highlights', get_link(url=highlights_url)]) if playlist is None: xbmcplugin.endOfDirectory(handle=int(sys.argv[1])) else: #reorder playlist items before adding reorder_streams(streams, game_home_team, game_visitor_team, in_a_hurry) for s in streams: #trying to add thumbs to playlist item... (can't seem to get it as icon, but it is shown on the right and on the background. However, lost again when saving the playlist.) item = xbmcgui.ListItem(s[1], iconImage=iconimage, thumbnailImage=iconimage) try: art_keys = ['thumb', 'poster', 'banner', 'fanart', 'clearart', 'clearlogo', 'landscape', 'icon'] art = dict(zip(art_keys, [iconimage for x in art_keys])) item.setArt(art) item.setInfo(type="video", infoLabels={"title": s[1]}) item.setThumbnailImage(iconimage) item.setProperty('fanart_image', iconimage) except: pass playlist.add(s[2], item)
def addGamesLinks(date='', video_type="archive", playlist=None, in_a_hurry=False): try: now_datetime_est = utils.nowEST() schedule = 'https://nlnbamdnyc-a.akamaihd.net/fs/nba/feeds_s2019/schedule/%04d/%d_%d.js?t=%d' % \ (date.year, date.month, date.day, time.time()) utils.log('Requesting %s' % schedule, xbmc.LOGDEBUG) schedule_request = urllib2.Request(schedule, None) schedule_response = str(urllib2.urlopen(schedule_request).read()) schedule_json = json.loads(schedule_response[schedule_response.find("{"):]) unknown_teams = {} for index, daily_games in enumerate(schedule_json['games']): utils.log("daily games for day %d are %s" % (index, daily_games), xbmc.LOGDEBUG) for game in daily_games: processed_keys = set() v = process_key(game, 'v', processed_keys) h = process_key(game, 'h', processed_keys) vr = process_key(game, 'vr', processed_keys) hr = process_key(game, 'hr', processed_keys) vs = process_key(game, 'vs', processed_keys) hs = process_key(game, 'hs', processed_keys) if v is None or h is None: # TODO utils.log(json.dumps(game), xbmc.LOGDEBUG) continue game_id = process_key(game, 'id', processed_keys) game_start_date_est = process_key(game, 'd', processed_keys) name = process_key(game, 'name', processed_keys) image = process_key(game, 'image', processed_keys) seo_name = process_key(game, 'seoName', processed_keys) video = process_key(game, 'video', processed_keys) has_video = video is not None has_condensed_video = has_video and bool(video.get('c')) has_away_feed = has_video and bool(video.get('af')) # Try to convert start date to datetime try: game_start_datetime_est = datetime.datetime.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f") except: game_start_datetime_est = datetime.datetime.fromtimestamp(time.mktime(time.strptime(game_start_date_est, "%Y-%m-%dT%H:%M:%S.%f"))) #Set game start date in the past if python can't parse the date #so it doesn't get flagged as live or future game and you can still play it #if a video is available if type(game_start_datetime_est) is not datetime.datetime: game_start_datetime_est = now_datetime_est + timedelta(-30) # Guess end date by adding 4 hours to start date game_end_datetime_est = game_start_datetime_est + timedelta(hours=4) # Get playoff game number, if available playoff_game_number = 0 playoff_status = "" if 'playoff' in game: playoff_home_wins = int(game['playoff']['hr'].split("-")[0]) playoff_visitor_wins = int(game['playoff']['vr'].split("-")[0]) playoff_status = "%d-%d" % (playoff_visitor_wins, playoff_home_wins) playoff_game_number = playoff_home_wins + playoff_visitor_wins if game_id is not None: # Get pretty names for the team names [visitor_name, host_name] = [vars.config['teams'].get(t.lower(), t) for t in [v, h]] [unknown_teams.setdefault(t, []).append(game_start_datetime_est.strftime("%Y-%m-%d")) for t in [v, h] if t.lower() not in vars.config['teams']] future_video = game_start_datetime_est > now_datetime_est and \ game_start_datetime_est.date() == now_datetime_est.date() live_video = game_start_datetime_est < now_datetime_est < game_end_datetime_est name = game_start_datetime_est.strftime("%Y-%m-%d") if video_type == "live": name = utils.toLocalTimezone(game_start_datetime_est).strftime("%Y-%m-%d (at %I:%M %p)") name += " %s%s vs %s%s" % (visitor_name, " (%s)" % vr if vars.show_records_and_scores else '', host_name, " (%s)" % hr if vars.show_records_and_scores else '') if playoff_game_number != 0: name += ' (game %d)' % (playoff_game_number) if vars.show_records_and_scores and not future_video: name += ' %s:%s' % (vs, hs) if playoff_status: name += " (series: %s)" % playoff_status thumbnail_url = utils.generateCombinedThumbnail(v, h) if video_type == "live": if future_video: name = "UPCOMING: " + name elif live_video: name = "LIVE: " + name add_link = True if video_type == "live" and not (live_video or future_video): add_link = False elif video_type != "live" and (live_video or future_video): add_link = False elif not future_video and not has_video: add_link = False if add_link: params = { 'video_id': game_id, 'video_type': video_type, 'seo_name': seo_name, 'visitor_team': visitor_name, 'home_team': host_name, 'has_away_feed': "1" if has_away_feed else "0", 'has_condensed_game': "1" if has_condensed_video else "0", 'foldername': name, 'iconimage': thumbnail_url, } if 'st' in game: start_time = calendar.timegm(time.strptime(game['st'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['start_time'] = start_time if 'et' in game: end_time = calendar.timegm(time.strptime(game['et'], '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time else: # create my own et for game (now) end_time = str(datetime.datetime.now()).replace(' ', 'T') end_time = calendar.timegm(time.strptime(end_time, '%Y-%m-%dT%H:%M:%S.%f')) * 1000 params['end_time'] = end_time params['duration'] = end_time - start_time # Add a directory item that contains home/away/condensed items if playlist is None: common.addListItem(name, url="", mode="gamechoosevideo", iconimage=thumbnail_url, isfolder=True, customparams=params) else: chooseGameVideoMenu(playlist, params, in_a_hurry) remaining_keys = set(game.keys()).difference(processed_keys) utils.log('Remaining keys: {}'.format(remaining_keys), xbmc.LOGDEBUG) if unknown_teams: utils.log("Unknown teams: %s" % str(unknown_teams), xbmc.LOGWARNING) except Exception, e: utils.littleErrorPopup("Error: %s" % str(e)) utils.log(traceback.format_exc(), xbmc.LOGDEBUG) pass