def _import_videoid_old(self, file_content, folder_name): try: # The STRM file in add-on v13.x is different and can contains two lines, example: # #EXTINF:-1,Tv show title - "meta data ..." # plugin://plugin.video.netflix/?video_id=12345678&action=play_video # Get last line and extract the videoid value match = re.search(r'video_id=(\d+)', file_content.split('\n')[-1]) # Create a videoid of UNSPECIFIED type (we do not know the real type of videoid) videoid = common.VideoId(videoid=match.groups()[0]) # Try to get the videoid metadata: # - To know if the videoid still exists on netflix # - To get the videoid type # - To get the Tv show videoid, in the case of STRM of an episode metadata = self.ext_func_get_metadata(videoid)[0] # pylint: disable=not-callable # Generate the a good videoid if metadata['type'] == 'show': return common.VideoId(tvshowid=metadata['id']) return common.VideoId(movieid=metadata['id']) except MetadataNotAvailable: LOG.warn('Import error: folder {} skipped, metadata not available', folder_name) return None except (AttributeError, IndexError): LOG.warn( 'Import error: folder {} skipped, STRM not conform to v0.13.x format', folder_name) return None
def _get_root_videoid(filename, pattern): match = re.search( pattern, xbmcvfs.File(filename, 'r').read().decode('utf-8').split('\n')[-1]) metadata = api.metadata(common.VideoId(videoid=match.groups()[0]))[0] if metadata['type'] == 'show': return common.VideoId(tvshowid=metadata['id']) return common.VideoId(movieid=metadata['id'])
def _find_next_episode(videoid, metadata): try: # Find next episode in current season episode = common.find(metadata[0]['seq'] + 1, 'seq', metadata[1]['episodes']) return common.VideoId(tvshowid=videoid.tvshowid, seasonid=videoid.seasonid, episodeid=episode['id']) except (IndexError, KeyError): # Find first episode of next season next_season = common.find(metadata[1]['seq'] + 1, 'seq', metadata[2]['seasons']) episode = common.find(1, 'seq', next_season['episodes']) return common.VideoId(tvshowid=videoid.tvshowid, seasonid=next_season['id'], episodeid=episode['id'])
def _sync_my_list_ops(self, videoids_tasks, exp_tvshows_videoids_values, exp_movies_videoids_values): # Get videoids from the My list (of the chosen profile) # pylint: disable=not-callable mylist_video_id_list, mylist_video_id_list_type = self.ext_func_get_mylist_videoids_profile_switch() # Check if tv shows have been removed from the My List for videoid_value in exp_tvshows_videoids_values: if unicode(videoid_value) in mylist_video_id_list: continue # The tv show no more exist in My List so remove it from library videoid = common.VideoId.from_path([common.VideoId.SHOW, videoid_value]) videoids_tasks.update({videoid: self.remove_item}) # Check if movies have been removed from the My List for videoid_value in exp_movies_videoids_values: if unicode(videoid_value) in mylist_video_id_list: continue # The movie no more exist in My List so remove it from library videoid = common.VideoId.from_path([common.VideoId.MOVIE, videoid_value]) videoids_tasks.update({videoid: self.remove_item}) # Add to library the missing tv shows / movies of My List for index, videoid_value in enumerate(mylist_video_id_list): if (int(videoid_value) not in exp_tvshows_videoids_values and int(videoid_value) not in exp_movies_videoids_values): is_movie = mylist_video_id_list_type[index] == 'movie' videoid = common.VideoId(**{('movieid' if is_movie else 'tvshowid'): videoid_value}) videoids_tasks.update({videoid: self.export_item if is_movie else self.export_new_item})
def __init__(self, path_response, list_id=None): # common.debug('VideoList data: {}', path_response) self.perpetual_range_selector = path_response.get( '_perpetual_range_selector') self.data = path_response has_data = bool(path_response.get('lists')) self.videos = OrderedDict() self.artitem = None self.contained_titles = None self.videoids = None if has_data: # Generate one videoid, or from the first id of the list or with specified one self.videoid = common.VideoId(videoid=( list_id if list_id else next(iter(self.data['lists'])))) self.videos = OrderedDict( resolve_refs(self.data['lists'][self.videoid.value], self.data)) if self.videos: # self.artitem = next(itervalues(self.videos)) self.artitem = listvalues(self.videos)[0] self.contained_titles = _get_titles(self.videos) try: self.videoids = _get_videoids(self.videos) except KeyError: self.videoids = None
def __init__(self, path_response, list_id): # common.debug('VideoListLoCo data: {}', path_response) self.perpetual_range_selector = path_response.get( '_perpetual_range_selector') self.data = path_response self.list_id = list_id self.videoids = None # Set a 'UNSPECIFIED' type videoid (special handling for menus see parse_info in infolabels.py) self.videoid = common.VideoId(videoid=list_id) self.contained_titles = None self.artitem = None if 'lists' not in path_response: # No data in path response return # Set videos data for the specified list id self.videos = OrderedDict( resolve_refs(self.data['lists'][list_id], self.data)) if not self.videos: return # Set first videos titles (special handling for menus see parse_info in infolabels.py) self.contained_titles = _get_titles(self.videos) # Set art data of first video (special handling for menus see parse_info in infolabels.py) self.artitem = listvalues(self.videos)[0] try: self.videoids = _get_videoids(self.videos) except KeyError: self.videoids = None
def _create_remove_jobs_from_rows(self, row_results): """Create jobs data to remove episodes, from the rows results of the database""" return [ self._build_remove_job_data( get_episode_title_from_path(row['FilePath']), row['FilePath'], common.VideoId(tvshowid=row['TvShowID'], seasonid=row['SeasonID'], episodeid=row['EpisodeID'])) for row in row_results ]
def _create_supplemental_item(videoid_value, video, video_list, params): """Create a tuple that can be added to a Kodi directory that represents a video as listed in a videolist""" videoid = common.VideoId(**{'supplementalid': videoid_value}) list_item = list_item_skeleton(video['title']) add_info(videoid, list_item, video, video_list.data) add_art(videoid, list_item, video) url = common.build_url(videoid=videoid, mode=g.MODE_PLAY, params=params) list_item.addContextMenuItems(generate_context_menu_items(videoid)) return (url, list_item, False)
def _create_supplemental_item(videoid_value, video, video_list): """Create a tuple that can be added to a Kodi directory that represents a video as listed in a videolist""" videoid = common.VideoId(**{'supplementalid': videoid_value}) list_item = list_item_skeleton(video['title']) add_info(videoid, list_item, video, video_list.data) add_art(videoid, list_item, video) url = common.build_url(videoid=videoid, mode=g.MODE_PLAY) # replaceItems still look broken because it does not remove the default ctx menu, i hope in the future Kodi fix this list_item.addContextMenuItems(generate_context_menu_items(videoid), replaceItems=True) return (url, list_item, False)
def _create_video_item(videoid_value, video, video_list): """Create a tuple that can be added to a Kodi directory that represents a video as listed in a videolist""" is_movie = video['summary']['type'] == 'movie' videoid = common.VideoId( **{('movieid' if is_movie else 'tvshowid'): videoid_value}) list_item = list_item_skeleton(video['title']) add_info(videoid, list_item, video, video_list.data) add_art(videoid, list_item, video) url = common.build_url( videoid=videoid, mode=(g.MODE_PLAY if is_movie else g.MODE_DIRECTORY)) list_item.addContextMenuItems(generate_context_menu_items(videoid)) return (url, list_item, not is_movie)
def __init__(self, path_response, list_id=None): self.data = path_response self.id = common.VideoId( videoid=(list_id if list_id else next(self.data['lists'].iterkeys()))) self.title = self['displayName'] self.videos = OrderedDict( resolve_refs(self.data['lists'][self.id.value], self.data)) self.artitem = next(self.videos.itervalues()) self.contained_titles = _get_titles(self.videos) try: self.videoids = _get_videoids(self.videos) except KeyError: self.videoids = None
def _create_video_item(videoid_value, video, video_list, menu_data, params): """Create a tuple that can be added to a Kodi directory that represents a video as listed in a videolist""" is_movie = video['summary']['type'] == 'movie' videoid = common.VideoId( **{('movieid' if is_movie else 'tvshowid'): videoid_value}) list_item = list_item_skeleton(video['title']) infos = add_info(videoid, list_item, video, video_list.data) if menu_data['path'][1] != 'myList': add_highlighted_title(list_item, videoid, infos) list_item.setInfo('video', infos) add_art(videoid, list_item, video) url = common.build_url( videoid=videoid, mode=(g.MODE_PLAY if is_movie else g.MODE_DIRECTORY), params=params) list_item.addContextMenuItems(generate_context_menu_items(videoid)) return (url, list_item, not is_movie)
def __init__(self, path_response, list_id=None): self.perpetual_range_selector = path_response.get( '_perpetual_range_selector') self.data = path_response self.id = common.VideoId(videoid=( list_id if list_id else next(self.data['lists'].iterkeys()))) #self.title = self['displayName'] Not more used self.videos = OrderedDict( resolve_refs(self.data['lists'][self.id.value], self.data)) if self.videos: self.artitem = next(self.videos.itervalues()) self.contained_titles = _get_titles(self.videos) try: self.videoids = _get_videoids(self.videos) except KeyError: self.videoids = None else: self.artitem = None self.contained_titles = None self.videoids = None
def sync_mylist_to_library(): """ Perform a full sync of Netflix "My List" with the Kodi library by deleting everything that was previously exported """ common.info( 'Performing full sync of Netflix "My List" with the Kodi library') purge() nfo_settings = nfo.NFOSettings() nfo_settings.show_export_dialog() mylist_video_id_list, mylist_video_id_list_type = common.make_call( 'get_mylist_videoids_profile_switch') for index, video_id in enumerate(mylist_video_id_list): videoid = common.VideoId( **{ ('movieid' if (mylist_video_id_list_type[index] == 'movie') else 'tvshowid'): video_id }) execute_library_tasks(videoid, [export_item], common.get_local_string(30018), nfo_settings=nfo_settings)
def auto_update_library(sync_with_mylist, silent): """ Perform an auto update of the exported items to Kodi library, so check if there is new seasons/episodes. If sync_with_mylist is enabled the Kodi library will be also synchronized with the Netflix "My List". :param sync_with_mylist: True to enable sync with My List :param silent: don't display user interface while performing an operation :return: None """ if _is_auto_update_library_running(): return execute_lib_tasks_method = execute_library_tasks_silently if silent else execute_library_tasks common.info( 'Starting auto update library - check updates for tv shows (sync with My List is {})', 'ENABLED' if sync_with_mylist else 'DISABLED') g.SHARED_DB.set_value('library_auto_update_is_running', True) g.SHARED_DB.set_value('library_auto_update_start_time', datetime.now()) try: videoids_to_update = [] # Get the list of the exported items to Kodi library exported_tvshows_videoids_values = g.SHARED_DB.get_tvshows_id_list() exported_movies_videoids_values = g.SHARED_DB.get_movies_id_list() if sync_with_mylist: # Get My List videoids of the chosen profile # Use make_http_call instead make_http because call AddonSignals on same instance makes problems mylist_video_id_list, mylist_video_id_list_type = common.make_http_call( 'get_mylist_videoids_profile_switch', None) # Check if tv shows have been removed from the My List for videoid_value in exported_tvshows_videoids_values: if unicode(videoid_value) in mylist_video_id_list: continue # The tv show no more exist in My List so remove it from library videoid = common.VideoId.from_path( [common.VideoId.SHOW, videoid_value]) execute_lib_tasks_method(videoid, [remove_item]) # Check if movies have been removed from the My List for videoid_value in exported_movies_videoids_values: if unicode(videoid_value) in mylist_video_id_list: continue # The movie no more exist in My List so remove it from library videoid = common.VideoId.from_path( [common.VideoId.MOVIE, videoid_value]) execute_lib_tasks_method(videoid, [remove_item]) # Add missing tv shows / movies of My List to library for index, video_id in enumerate(mylist_video_id_list): if (int(video_id) not in exported_tvshows_videoids_values and int(video_id) not in exported_movies_videoids_values): videoids_to_update.append( common.VideoId( **{ ('movieid' if (mylist_video_id_list_type[index] == 'movie') else 'tvshowid'): video_id })) # Add the exported tv shows to be updated to the list.. tvshows_videoids_to_upd = [ common.VideoId.from_path([common.VideoId.SHOW, videoid_value]) for videoid_value in g.SHARED_DB.get_tvshows_id_list( VidLibProp['exclude_update'], False) ] # ..and avoids any duplication caused by possible unexpected errors videoids_to_update.extend( list(set(tvshows_videoids_to_upd) - set(videoids_to_update))) # Add missing tv shows/movies or update existing tv shows _update_library(videoids_to_update, exported_tvshows_videoids_values, silent) common.debug('Auto update of the library completed') g.SHARED_DB.set_value('library_auto_update_is_running', False) if not g.ADDON.getSettingBool('lib_auto_upd_disable_notification'): ui.show_notification(common.get_local_string(30220), time=5000) common.debug( 'Notify service to communicate to Kodi of update the library') common.send_signal(common.Signals.LIBRARY_UPDATE_REQUESTED) except Exception: # pylint: disable=broad-except import traceback common.error('An error has occurred in the library auto update') common.error(traceback.format_exc()) g.SHARED_DB.set_value('library_auto_update_is_running', False)