def __check_subtitles(self): """ Check subtitles """ # Check if subtitles are enabled before making any changes response = kodiutils.jsonrpc(method='Player.GetProperties', params=dict(playerid=1, properties=['currentsubtitle', 'subtitleenabled', 'subtitles'])) subtitle_enabled = response.get('result').get('subtitleenabled') # Make sure an internal InputStream Adaptive subtitle is selected, if available available_subtitles = self.getAvailableSubtitleStreams() if available_subtitles: for i, subtitle in enumerate(available_subtitles): if '(External)' not in subtitle and '(External)' in self.getSubtitles(): self.setSubtitleStream(i) break elif self.__av_started: _LOGGER.debug('Player: No internal subtitles found') # Add external subtitles if self.__subtitle_paths: for subtitle in self.__subtitle_paths: _LOGGER.debug('Player: Adding external subtitles %s', subtitle) self.setSubtitles(subtitle) # Enable subtitles if needed show_subtitles = kodiutils.get_setting_bool('showsubtitles') if show_subtitles and not subtitle_enabled: _LOGGER.debug('Player: Enabling subtitles') self.showSubtitles(True) elif not subtitle_enabled: _LOGGER.debug('Player: Disabling subtitles') self.showSubtitles(False)
def show_recommendations_category(self, storefront, category): """ Show the items in a recommendations category. :type storefront: str :type category: str """ result = self._api.get_storefront_category(storefront, category) show_unavailable = kodiutils.get_setting_bool( 'interface_show_unavailable') listing = [] for item in result.content: if show_unavailable or item.available: listing.append(Menu.generate_titleitem(item)) if storefront == STOREFRONT_SERIES: content = 'tvshows' elif storefront == STOREFRONT_MOVIES: content = 'movies' else: content = 'tvshows' # Fallback to a list of tvshows kodiutils.show_listing(listing, result.title, content=content, sort=['unsorted', 'label', 'year', 'duration'])
def show_search(self, query=None): """ Shows the search dialog. :type query: str """ if not query: # Ask for query query = kodiutils.get_search_string( heading=kodiutils.localize(30009)) # Search Streamz if not query: kodiutils.end_of_directory() return # Do search try: items = self._api.do_search(query) except Exception as ex: # pylint: disable=broad-except kodiutils.notification(message=str(ex)) kodiutils.end_of_directory() return # Display results show_unavailable = kodiutils.get_setting_bool( 'interface_show_unavailable') listing = [] for item in items: if show_unavailable or item.available: listing.append(Menu.generate_titleitem(item)) # Sort like we get our results back. kodiutils.show_listing(listing, 30009, content='tvshows')
def show_recommendations(self, storefront): """ Show the recommendations. :type storefront: str """ results = self._api.get_storefront(storefront) show_unavailable = kodiutils.get_setting_bool( 'interface_show_unavailable') listing = [] for item in results: if isinstance(item, Category): listing.append( TitleItem( title=item.title, path=kodiutils.url_for('show_recommendations_category', storefront=storefront, category=item.category_id), info_dict=dict(plot='[B]{category}[/B]'.format( category=item.title), ), )) else: if show_unavailable or item.available: listing.append(Menu.generate_titleitem(item)) if storefront == STOREFRONT_SERIES: label = 30005 # Series elif storefront == STOREFRONT_MOVIES: label = 30003 # Movies else: label = 30015 # Recommendations kodiutils.show_listing(listing, label, content='files')
def refresh(cls, show_progress=False): """ Update channels and EPG data """ channels = [] epg = dict() if show_progress: progress = kodiutils.progress( message=kodiutils.localize(30703)) # Detecting IPTV add-ons... else: progress = None addons = cls.get_iptv_addons() for index, addon in enumerate(addons): _LOGGER.info('Updating IPTV data for %s...', addon.addon_id) if progress: progress.update(int(100 * index / len(addons)), kodiutils.localize(30704).format( addon=kodiutils.addon_name(addon.addon_obj) )) # Fetching channels and guide of {addon}... # Fetch channels channels.extend(addon.get_channels()) if progress and progress.iscanceled(): progress.close() return # Fetch EPG data epg.update(addon.get_epg()) if progress and progress.iscanceled(): progress.close() return # Write files if show_progress: progress.update( 100, kodiutils.localize(30705)) # Updating channels and guide... IptvSimple.write_playlist(channels) IptvSimple.write_epg(epg) if kodiutils.get_setting_bool('iptv_simple_restart'): if show_progress: # Try to restart now. We will schedule it if the user is watching TV. IptvSimple.restart(True) else: # Schedule a restart IptvSimple.restart(False) # Update last_refreshed kodiutils.set_setting_int('last_refreshed', int(time.time())) if show_progress: progress.close() kodiutils.ok_dialog(message=kodiutils.localize( 30706)) # The channels and guide are updated successfully!
def index(): """ Show the profile selection, or go to the main menu. """ # Verify credentials from resources.lib.modules.authentication import Authentication if not Authentication.verify_credentials(): kodiutils.end_of_directory() kodiutils.execute_builtin('ActivateWindow(Home)') return if kodiutils.get_setting_bool('auto_login') and kodiutils.get_setting('profile'): show_main_menu() else: select_profile()
def run(self): """ Background loop for maintenance tasks """ _LOGGER.debug('Service started') while not self.abortRequested(): # Update every `update_interval` after the last update if kodiutils.get_setting_bool('metadata_update') and int(kodiutils.get_setting('metadata_last_updated', 0)) + self.update_interval < time(): self._update_metadata() # Stop when abort requested if self.waitForAbort(10): break _LOGGER.debug('Service stopped')
def run(self): """ Background loop for maintenance tasks """ _LOGGER.debug('Service started') kodiutils.set_setting('manifest_proxy_port', None) if kodiutils.get_setting_bool('manifest_proxy'): _LOGGER.debug('Starting Manifest Proxy...') self._proxy_thread = Proxy.start() while not self.abortRequested(): # Update every `update_interval` after the last update if kodiutils.get_setting_bool('metadata_update') and int(kodiutils.get_setting('metadata_last_updated', 0)) + self.update_interval < time(): self._update_metadata() # Stop when abort requested if self.waitForAbort(10): break # Wait for the proxy thread to stop if self._proxy_thread and self._proxy_thread.is_alive(): _LOGGER.debug('Stopping Manifest Proxy...') Proxy.stop() _LOGGER.debug('Service stopped')
def run(self): """ Background loop for maintenance tasks """ _LOGGER.debug('Service started') kodiutils.set_setting('manifest_proxy_port', None) if kodiutils.get_setting_bool('manifest_proxy'): _LOGGER.debug('Starting Manifest Proxy...') self._proxy_thread = Proxy.start() while not self.abortRequested(): # Stop when abort requested if self.waitForAbort(60): break # Wait for the proxy thread to stop if self._proxy_thread and self._proxy_thread.is_alive(): _LOGGER.debug('Stopping Manifest Proxy...') Proxy.stop() _LOGGER.debug('Service stopped')
def index(): """ Show the profile selection, or go to the main menu. """ try: if (kodiutils.get_setting_bool('auto_login') and kodiutils.get_setting('username') and kodiutils.get_setting('password') and kodiutils.get_setting('profile')): # We have credentials show_main_menu() else: # Ask the user for the profile to use select_profile() except NoLoginException: kodiutils.ok_dialog(message=kodiutils.localize( 30701)) # You need to configure your credentials... kodiutils.open_settings() kodiutils.container_refresh() except InvalidLoginException: kodiutils.ok_dialog(message=kodiutils.localize( 30203)) # Your credentials are not valid! kodiutils.open_settings() kodiutils.end_of_directory() except NoStreamzSubscriptionException: kodiutils.ok_dialog(message=kodiutils.localize( 30201)) # Your Streamz account has no valid subscription! kodiutils.end_of_directory() except NoTelenetSubscriptionException: kodiutils.ok_dialog(message=kodiutils.localize( 30202)) # Your Telenet account has no valid subscription! kodiutils.end_of_directory() except LoginErrorException as exc: kodiutils.ok_dialog(message=kodiutils.localize( 30702, code=exc.code)) # Unknown error while logging in: {code} kodiutils.open_settings() kodiutils.end_of_directory()
def index(): """ Show the profile selection, or go to the main menu. """ while True: if not kodiutils.has_credentials(): if not kodiutils.yesno_dialog(message=kodiutils.localize( 30701)): # You need to configure your credentials... # We have no credentials kodiutils.end_of_directory() kodiutils.execute_builtin('ActivateWindow(Home)') return kodiutils.open_settings() else: break try: if kodiutils.get_setting_bool('auto_login') and kodiutils.get_setting( 'profile'): # We have a profile show_main_menu() else: # Ask the user for the profile to use select_profile() except InvalidLoginException: kodiutils.ok_dialog(message=kodiutils.localize( 30203)) # Your credentials are not valid! kodiutils.open_settings() kodiutils.end_of_directory() except LoginErrorException as exc: kodiutils.ok_dialog(message=kodiutils.localize( 30702, code=exc.code)) # Unknown error while logging in: {code} kodiutils.end_of_directory() except HTTPError as exc: kodiutils.ok_dialog(message=kodiutils.localize( 30702, code='HTTP %d' % exc.response.status_code) ) # Unknown error while logging in: {code} kodiutils.end_of_directory()
def show_mainmenu(self): """ Show the main menu. """ listing = [] account = self._auth.get_tokens() if account.product == PRODUCT_STREAMZ: listing.append(TitleItem( title=kodiutils.localize(30015), # Recommendations path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MAIN), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30016), ), )) listing.append(TitleItem( title=kodiutils.localize(30003), # Movies path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MOVIES), art_dict=dict( icon='DefaultMovies.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30004), ), )) listing.append(TitleItem( title=kodiutils.localize(30005), # Series path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_SERIES), art_dict=dict( icon='DefaultTVShows.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30006), ), )) listing.append(TitleItem( title=kodiutils.localize(30021), # Kids path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_KIDS), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30022), ), )) elif account.product == PRODUCT_STREAMZ_KIDS: listing.append(TitleItem( title=kodiutils.localize(30015), # Recommendations path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MAIN_KIDS), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30016), ), )) if kodiutils.get_setting_bool('interface_show_mylist'): listing.append(TitleItem( title=kodiutils.localize(30017), # My List path=kodiutils.url_for('show_mylist'), art_dict=dict( icon='DefaultPlaylist.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30018), ), )) if kodiutils.get_setting_bool('interface_show_continuewatching'): listing.append(TitleItem( title=kodiutils.localize(30019), # Continue watching path=kodiutils.url_for('show_continuewatching'), art_dict=dict( icon='DefaultInProgressShows.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30020), ), )) listing.append(TitleItem( title=kodiutils.localize(30009), # Search path=kodiutils.url_for('show_search'), art_dict=dict( icon='DefaultAddonsSearch.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict( plot=kodiutils.localize(30010), ), )) kodiutils.show_listing(listing, sort=['unsorted'])
def refresh(cls, show_progress=False, force=False): """Update channels and EPG data""" channels = [] epg = [] if show_progress: progress = kodiutils.progress( message=kodiutils.localize(30703)) # Detecting IPTV add-ons... else: progress = None addons = cls.detect_iptv_addons() for index, addon in enumerate(addons): """Check if addon requires update""" if not force and not cls.is_refresh_required(addon.addon_id): addon_epg = cls.cache.get('iptvmanager.epg.%s' % (addon.addon_id)) addon_channel = cls.cache.get('iptvmanager.channel.%s' % (addon.addon_id)) if addon_epg and addon_channel: _LOGGER.info('Update not needed for %s...', addon.addon_id) channels.append(addon_channel) epg.append(addon_epg) continue if progress: # Fetching channels and guide of {addon}... progress.update( int(100 * index / len(addons)), kodiutils.localize(30704).format( addon=kodiutils.addon_name(addon.addon_obj))) _LOGGER.info('Updating IPTV data for %s...', addon.addon_id) # Fetch channels addon_channel = dict( addon_id=addon.addon_id, addon_name=kodiutils.addon_name(addon.addon_obj), channels=addon.get_channels(), ) channels.append(addon_channel) if progress and progress.iscanceled(): progress.close() return # Fetch EPG addon_epg = addon.get_epg() cls.set_cache_n_update(cls, addon.addon_id, addon_epg, addon_channel) epg.append(addon_epg) if progress and progress.iscanceled(): progress.close() return # Write files if show_progress: progress.update( 100, kodiutils.localize(30705)) # Updating channels and guide... IptvSimple.write_playlist(channels) IptvSimple.write_epg(epg, channels) if kodiutils.get_setting_bool('iptv_simple_restart'): if show_progress: # Restart now. IptvSimple.restart(True) else: # Try to restart now. We will schedule it if the user is watching TV. IptvSimple.restart(False) # Update last_refreshed kodiutils.set_property('last_refreshed', int(time.time())) if show_progress: progress.close()
def play(self, category, item): """ Play the requested item. :type category: string :type item: string """ if not self._check_credentials(): kodiutils.end_of_directory() return # Check if inputstreamhelper is correctly installed if not self._check_inputstream(): kodiutils.end_of_directory() return try: # Get stream information resolved_stream = self._vtm_go_stream.get_stream(category, item) except StreamGeoblockedException: kodiutils.ok_dialog(heading=kodiutils.localize(30709), message=kodiutils.localize(30710)) # This video is geo-blocked... kodiutils.end_of_directory() return except StreamUnavailableException: kodiutils.ok_dialog(heading=kodiutils.localize(30711), message=kodiutils.localize(30712)) # The video is unavailable... kodiutils.end_of_directory() return info_dict = { 'tvshowtitle': resolved_stream.program, 'title': resolved_stream.title, 'duration': resolved_stream.duration, } prop_dict = {} stream_dict = { 'duration': resolved_stream.duration, } upnext_data = None # Lookup metadata try: if category in ['movies', 'oneoffs']: info_dict.update({'mediatype': 'movie'}) # Get details movie_details = self._vtm_go.get_movie(item) if movie_details: info_dict.update({ 'plot': movie_details.description, 'year': movie_details.year, 'aired': movie_details.aired, }) elif category == 'episodes': info_dict.update({'mediatype': 'episode'}) # There is no direct API to get episode details, so we go trough the cached program details program = self._vtm_go.get_program(resolved_stream.program_id) if program: episode_details = self._vtm_go.get_episode_from_program(program, item) if episode_details: info_dict.update({ 'plot': episode_details.description, 'season': episode_details.season, 'episode': episode_details.number, }) # Lookup the next episode next_episode_details = self._vtm_go.get_next_episode_from_program(program, episode_details.season, episode_details.number) # Create the data for Up Next if next_episode_details: upnext_data = self.generate_upnext(episode_details, next_episode_details) elif category == 'channels': info_dict.update({'mediatype': 'episode'}) # For live channels, we need to keep on updating the manifest # This might not be needed, and could be done with the Location-tag updates if inputstream.adaptive supports it # See https://github.com/peak3d/inputstream.adaptive/pull/298#issuecomment-524206935 prop_dict.update({ 'inputstream.adaptive.manifest_update_parameter': 'full', }) else: _LOGGER.warning('Unknown category %s', category) except UnavailableException: # We continue without details. # This allows to play some programs that don't have metadata (yet). pass # If we have enabled the Manifest proxy, route the call trough that. if category in ['movies', 'oneoffs', 'episodes'] and kodiutils.get_setting_bool('manifest_proxy'): try: # Python 3 from urllib.parse import urlencode except ImportError: # Python 2 from urllib import urlencode port = kodiutils.get_setting_int('manifest_proxy_port') if not port: kodiutils.notification(message=kodiutils.localize(30718), icon='error') kodiutils.end_of_directory() return url = 'http://127.0.0.1:{port}/manifest?{path}'.format(port=port, path=urlencode({'path': resolved_stream.url})) else: url = resolved_stream.url license_key = self._vtm_go_stream.create_license_key(resolved_stream.license_url) # Play this item kodiutils.play(url, license_key, resolved_stream.title, {}, info_dict, prop_dict, stream_dict) # Wait for playback to start kodi_player = KodiPlayer() if not kodi_player.waitForPlayBack(url=url): # Playback didn't start kodiutils.end_of_directory() return # Send Up Next data if upnext_data and kodiutils.get_setting_bool('useupnext'): _LOGGER.debug("Sending Up Next data: %s", upnext_data) self.send_upnext(upnext_data)
def show_mainmenu(self): """ Show the main menu. """ listing = [] account = self._auth.login() if account.product == 'STREAMZ': listing.append( TitleItem( title=kodiutils.localize(30015), # Recommendations path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MAIN), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30016), ), )) listing.append( TitleItem( title=kodiutils.localize(30003), # Movies path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MOVIES), art_dict=dict( icon='DefaultMovies.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30004), ), )) listing.append( TitleItem( title=kodiutils.localize(30005), # Series path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_SERIES), art_dict=dict( icon='DefaultTVShows.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30006), ), )) listing.append( TitleItem( title=kodiutils.localize(30021), # Kids path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_KIDS), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30022), ), )) elif account.product == 'STREAMZ_KIDS': listing.append( TitleItem( title=kodiutils.localize(30015), # Recommendations path=kodiutils.url_for('show_recommendations', storefront=STOREFRONT_MAIN_KIDS), art_dict=dict( icon='DefaultFavourites.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30016), ), )) if kodiutils.get_setting_bool('interface_show_az'): listing.append( TitleItem( title=kodiutils.localize(30001), # A-Z path=kodiutils.url_for('show_catalog_all'), art_dict=dict( icon='DefaultMovieTitle.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30002), ), )) # listing.append(TitleItem( # title=kodiutils.localize(30003), # Catalogue # path=kodiutils.url_for('show_catalog'), # art_dict=dict( # icon='DefaultGenre.png', # fanart=kodiutils.get_addon_info('fanart'), # ), # info_dict=dict( # plot=kodiutils.localize(30004), # ), # )) if kodiutils.get_setting_bool('interface_show_mylist'): listing.append( TitleItem( title=kodiutils.localize(30017), # My List path=kodiutils.url_for('show_mylist'), art_dict=dict( icon='DefaultPlaylist.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30018), ), )) # if kodiutils.get_setting_as_bool('interface_show_continuewatching') and kodiutils.has_credentials(): # listing.append(TitleItem( # title=kodiutils.localize(30019), # Continue watching # path=kodiutils.url_for('show_continuewatching'), # art_dict=dict( # icon='DefaultInProgressShows.png', # fanart=kodiutils.get_addon_info('fanart'), # ), # info_dict=dict( # plot=kodiutils.localize(30020), # ), # )) listing.append( TitleItem( title=kodiutils.localize(30009), # Search path=kodiutils.url_for('show_search'), art_dict=dict( icon='DefaultAddonsSearch.png', fanart=kodiutils.get_addon_info('fanart'), ), info_dict=dict(plot=kodiutils.localize(30010), ), )) kodiutils.show_listing(listing, sort=['unsorted'])
def generate_titleitem(item): """ Generate a TitleItem based on a Program or Episode. :type item: Union[Program, Episode] :rtype TitleItem """ info_dict = { 'title': item.title, 'plot': item.description, 'aired': item.aired.strftime('%Y-%m-%d') if item.aired else None, } prop_dict = {} # # Program # if isinstance(item, Program): info_dict.update({ 'mediatype': None, 'season': len(item.seasons) if item.seasons else None, }) art_dict = { 'poster': item.poster, 'landscape': item.thumb, 'thumb': item.thumb, 'fanart': item.fanart, } visible = True if isinstance(item.episodes, list) and not item.episodes: # We know that we don't have episodes title = '[COLOR gray]' + item.title + '[/COLOR]' visible = kodiutils.get_setting_bool( 'interface_show_unavailable') else: # We have episodes, or we don't know it title = item.title context_menu = [] if item.uuid: if item.my_list: context_menu.append(( kodiutils.localize(30101), # Remove from My List 'Container.Update(%s)' % kodiutils.url_for('mylist_del', uuid=item.uuid))) else: context_menu.append(( kodiutils.localize(30100), # Add to My List 'Container.Update(%s)' % kodiutils.url_for('mylist_add', uuid=item.uuid))) context_menu.append(( kodiutils.localize(30102), # Go to Program 'Container.Update(%s)' % kodiutils.url_for('show_catalog_program', program=item.path))) return TitleItem(title=title, path=kodiutils.url_for('show_catalog_program', program=item.path), context_menu=context_menu, art_dict=art_dict, info_dict=info_dict, visible=visible) # # Episode # if isinstance(item, Episode): info_dict.update({ 'mediatype': 'episode', 'tvshowtitle': item.program_title, 'duration': item.duration, 'season': item.season, 'episode': item.number, }) art_dict = { 'landscape': item.thumb, 'thumb': item.thumb, 'fanart': item.thumb, } stream_dict = STREAM_DICT.copy() stream_dict.update({ 'duration': item.duration, }) if item.uuid: # We have an UUID and can play this item directly path = kodiutils.url_for('play_catalog', uuid=item.uuid) else: # We don't have an UUID, and first need to fetch the video information from the page path = kodiutils.url_for('play_from_page', page=quote(item.path, safe='')) return TitleItem(title=info_dict['title'], path=path, art_dict=art_dict, info_dict=info_dict, stream_dict=stream_dict, prop_dict=prop_dict, is_playable=True) raise Exception('Unknown video_type')
def update_status(_i, _total): """ Allow to cancel the background job """ return self.abortRequested() or not kodiutils.get_setting_bool('metadata_update')
def play(self, category, item): """ Play the requested item. :type category: string :type item: string """ # Check if inputstreamhelper is correctly installed if not self._check_inputstream(): kodiutils.end_of_directory() return try: # Get stream information resolved_stream = self._stream.get_stream(category, item) except UnavailableException: kodiutils.ok_dialog(message=kodiutils.localize( 30712)) # The video is unavailable... kodiutils.end_of_directory() return except LimitReachedException: kodiutils.ok_dialog( message=kodiutils.localize(30713) ) # You have reached the maximum amount of concurrent streams... kodiutils.end_of_directory() return info_dict = { 'tvshowtitle': resolved_stream.program, 'title': resolved_stream.title, 'duration': resolved_stream.duration, } prop_dict = {} stream_dict = { 'duration': resolved_stream.duration, } upnext_data = None # Lookup metadata try: if category in ['movies', 'oneoffs']: info_dict.update({'mediatype': 'movie'}) # Get details movie_details = self._api.get_movie(item) if movie_details: info_dict.update({ 'plot': movie_details.description, 'year': movie_details.year, 'aired': movie_details.aired, }) elif category == 'episodes': info_dict.update({'mediatype': 'episode'}) # There is no direct API to get episode details, so we go trough the cached program details program = self._api.get_program(resolved_stream.program_id) if program: episode_details = self._api.get_episode_from_program( program, item) if episode_details: info_dict.update({ 'plot': episode_details.description, 'season': episode_details.season, 'episode': episode_details.number, }) # Lookup the next episode next_episode_details = self._api.get_next_episode_from_program( program, episode_details.season, episode_details.number) # Create the data for Up Next if next_episode_details: upnext_data = self.generate_upnext( episode_details, next_episode_details) else: _LOGGER.warning('Unknown category %s', category) except UnavailableException: # We continue without details. # This allows to play some programs that don't have metadata (yet). pass # If we have enabled the Manifest proxy, route the call trough that. if kodiutils.get_setting_bool('manifest_proxy'): try: # Python 3 from urllib.parse import urlencode except ImportError: # Python 2 from urllib import urlencode port = kodiutils.get_setting_int('manifest_proxy_port') if not port: kodiutils.notification(message=kodiutils.localize(30718), icon='error') kodiutils.end_of_directory() return url = 'http://127.0.0.1:{port}/manifest?{path}'.format( port=port, path=urlencode({'path': resolved_stream.url})) else: url = resolved_stream.url license_key = self._stream.create_license_key( resolved_stream.license_url) # Play this item kodiutils.play(url, license_key, resolved_stream.title, {}, info_dict, prop_dict, stream_dict, subtitles=resolved_stream.subtitles) # Wait for playback to start kodi_player = KodiPlayer() if not kodi_player.waitForPlayBack(url=url): # Playback didn't start return # Send Up Next data if upnext_data and kodiutils.get_setting_bool('useupnext'): _LOGGER.debug("Sending Up Next data: %s", upnext_data) self.send_upnext(upnext_data)