def initial_addon_configuration(self): """ Initial addon configuration, helps users to automatically configure addon parameters for proper viewing of videos """ run_initial_config = self.ADDON.getSettingBool('run_init_configuration') if run_initial_config: import resources.lib.common as common import resources.lib.kodi.ui as ui self.settings_monitor_suspended(True) system = common.get_system_platform() common.debug('Running initial addon configuration dialogs on system: {}'.format(system)) if system in ['osx', 'ios', 'xbox']: self.ADDON.setSettingBool('enable_vp9_profiles', False) self.ADDON.setSettingBool('enable_hevc_profiles', True) elif system == 'windows': # Currently inputstream does not support hardware video acceleration on windows, # there is no guarantee that we will get 4K without video hardware acceleration, # so no 4K configuration self.ADDON.setSettingBool('enable_vp9_profiles', True) self.ADDON.setSettingBool('enable_hevc_profiles', False) elif system == 'android': ultrahd_capable_device = False premium_account = ui.ask_for_confirmation(common.get_local_string(30154), common.get_local_string(30155)) if premium_account: ultrahd_capable_device = ui.ask_for_confirmation(common.get_local_string(30154), common.get_local_string(30156)) if ultrahd_capable_device: ui.show_ok_dialog(common.get_local_string(30154), common.get_local_string(30157)) ia_enabled = xbmc.getCondVisibility('System.HasAddon(inputstream.adaptive)') if ia_enabled: xbmc.executebuiltin('Addon.OpenSettings(inputstream.adaptive)') else: ui.show_ok_dialog(common.get_local_string(30154), common.get_local_string(30046)) self.ADDON.setSettingBool('enable_vp9_profiles', False) self.ADDON.setSettingBool('enable_hevc_profiles', True) else: # VP9 should have better performance since there is no need for 4k self.ADDON.setSettingBool('enable_vp9_profiles', True) self.ADDON.setSettingBool('enable_hevc_profiles', False) self.ADDON.setSettingBool('enable_force_hdcp', ultrahd_capable_device) elif system == 'linux': # Too many different linux systems, we can not predict all the behaviors # Some linux distributions have encountered problems with VP9, # OMSC users complain that hevc creates problems self.ADDON.setSettingBool('enable_vp9_profiles', False) self.ADDON.setSettingBool('enable_hevc_profiles', False) else: self.ADDON.setSettingBool('enable_vp9_profiles', False) self.ADDON.setSettingBool('enable_hevc_profiles', False) self.ADDON.setSettingBool('run_init_configuration', False) self.settings_monitor_suspended(False)
def _reset(self): if not ui.ask_for_confirmation( common.get_local_string(13007), # 13007=Reset common.get_local_string(30609)): return with common.show_busy_dialog(): # Set WV Sec. Lev. to Disabled self._ensure_wv_btn_check( self.WV_SECLEV_MAP_BTN[WidevineForceSecLev.DISABLED]) self.wv_sec_lev_new = WidevineForceSecLev.DISABLED if self.is_android: # Generate the ESN self.esn_new = generate_android_esn( wv_force_sec_lev=self.wv_sec_lev_new) else: # To retrieve the ESN from the website, # to avoid possible problems we refresh the nf session data to get a new ESN set_website_esn('') common.make_call('refresh_session_data', {'update_profiles': False}) self.esn_new = get_website_esn() if not self.esn_new: raise Exception( 'It was not possible to obtain the ESN, try restarting the add-on' ) self._update_esn_label()
def remove(self, videoid): """Remove an item from the Kodi library""" if ui.ask_for_confirmation(common.get_local_string(30030), common.get_local_string(30124)): library.execute_library_tasks(videoid, [library.remove_item], common.get_local_string(30030)) common.container_refresh(use_delay=True)
def initial_mylist_sync(self, pathitems): """Perform an initial sync of My List and the Kodi library""" # pylint: disable=unused-argument from resources.lib.cache import CACHE_COMMON # This is a temporary workaround to prevent sync from mylist of non owner account profiles # TODO: in the future you can also add the possibility to synchronize from a chosen profile is_account_owner = g.LOCAL_DB.get_profile_config( 'isAccountOwner', False) if not is_account_owner: ui.show_ok_dialog('Netflix', common.get_local_string(30223)) return do_it = ui.ask_for_confirmation(common.get_local_string(30122), common.get_local_string(30123)) if not do_it: return common.debug('Performing full sync from My List to Kodi library') library.purge() nfo_settings = nfo.NFOSettings() nfo_settings.show_export_dialog() # Invalidate my-list cached data to force to obtain new data g.CACHE.invalidate_entry(CACHE_COMMON, 'my_list_items') for videoid in api.mylist_items(): library.execute_library_tasks(videoid, [library.export_item], common.get_local_string(30018), sync_mylist=False, nfo_settings=nfo_settings)
def remove(self, videoid): """Remove an item from the Kodi library""" if not ui.ask_for_confirmation(common.get_local_string(30030), common.get_local_string(30124)): return get_library_cls().remove_from_library(videoid) common.container_refresh(use_delay=True)
def search_clear(): """Clear all search items""" if not ui.ask_for_confirmation(common.get_local_string(30404), common.get_local_string(30406)): return False G.LOCAL_DB.clear_search_items() search_list(dir_update_listing=True) return True
def show_export_dialog(self, mediatype=None, dialog_message=common.get_local_string(30183)): """Ask the user if he wants to export NFO for movies and/or tvshows, this override the default settings""" if not self.export_enabled or (not self.movie_prompt_dialog and not self.tvshow_prompt_dialog): return ask_message_typelist = [] if mediatype == common.VideoId.MOVIE and self.movie_prompt_dialog: ask_message_typelist.append(common.get_local_string(30189)) if mediatype in common.VideoId.TV_TYPES and self.tvshow_prompt_dialog: ask_message_typelist.append(common.get_local_string(30190)) if not mediatype: # If 'None' a massive export has been requested (i.e. first library sync, manual sync, my list auto-sync...) if self.movie_prompt_dialog: ask_message_typelist.append(common.get_local_string(30189)) if self.tvshow_prompt_dialog: ask_message_typelist.append(common.get_local_string(30190)) if ask_message_typelist: message = ' {} '.format( common.get_local_string(1397)).join(ask_message_typelist) message = dialog_message.format(message) + common.get_local_string( 30192) user_choice = ui.ask_for_confirmation( common.get_local_string(30182), message) if len(ask_message_typelist) == 2 and not user_choice: self._export_movie_id = 0 self._export_tvshow_id = 0 elif common.get_local_string( 30189) in ask_message_typelist and not user_choice: self._export_movie_id = 0 elif common.get_local_string( 30190) in ask_message_typelist and not user_choice: self._export_tvshow_id = 0
def remove_watched_status(self, videoid): """Remove the watched status from the Netflix service""" if not ui.ask_for_confirmation( common.get_local_string(30168), common.get_local_string(30300).format( xbmc.getInfoLabel('ListItem.Label'))): return if not api.remove_watched_status(videoid): ui.show_notification( 'The operation was cancelled due to an unexpected error') return # Check if item is in the cache videoid_exists, list_id = common.make_http_call( 'get_continuewatching_videoid_exists', {'video_id': str(videoid.value)}) if videoid_exists: # Try to remove the videoid from the list in the cache try: video_list_sorted_data = G.CACHE.get(cache_utils.CACHE_COMMON, list_id) del video_list_sorted_data.videos[videoid.value] G.CACHE.add(cache_utils.CACHE_COMMON, list_id, video_list_sorted_data) common.json_rpc( 'Input.Down') # Avoids selection back to the top except CacheMiss: pass common.container_refresh()
def sync_mylist(self, pathitems): # pylint: disable=unused-argument """ Perform a full sync of Netflix "My List" with the Kodi library """ if not ui.ask_for_confirmation(common.get_local_string(30122), common.get_local_string(30123)): return library.sync_mylist_to_library()
def search_clear(): """Clear all search items""" if not ui.ask_for_confirmation(common.get_local_string(30404), common.get_local_string(30406)): return False G.LOCAL_DB.clear_search_items() common.container_refresh() return True
def import_library(self, pathitems): # pylint: disable=unused-argument """Import previous exported STRM files to add-on and/or convert them to the current STRM format type""" if _check_auto_update_running(): return if not ui.ask_for_confirmation(common.get_local_string(30140), common.get_local_string(20135)): return get_library_cls().import_library()
def purge(self, pathitems): # pylint: disable=unused-argument """Delete all previously exported items from the Kodi library""" if _check_auto_update_running(): return if not ui.ask_for_confirmation(common.get_local_string(30125), common.get_local_string(30126)): return get_library_cls().clear_library()
def auto_upd_run_now(self, pathitems): # pylint: disable=unused-argument """ Perform an auto update of Kodi library to add new seasons/episodes of tv shows """ if not ui.ask_for_confirmation(common.get_local_string(30065), common.get_local_string(30231)): return library.auto_update_library(False, False)
def lib_remove(self, pathitems, videoid=None): # pylint: disable=unused-argument """Remove an item to the Kodi library""" if videoid.mediatype in [common.VideoId.SUPPLEMENTAL, common.VideoId.EPISODE]: return if not ui.ask_for_confirmation(common.get_local_string(30030), common.get_local_string(30124)): return get_library_cls().remove_from_library(videoid) common.container_refresh(use_delay=True)
def import_library(self, pathitems): # pylint: disable=unused-argument """Import previous exported STRM files to add-on and/or convert them to the current STRM format type""" if _check_auto_update_running(): return path = ui.show_browse_dialog(common.get_local_string(651), default_path=G.DATA_PATH) if path: if not ui.ask_for_confirmation(common.get_local_string(30140), common.get_local_string(20135)): return get_library_cls().import_library(path)
def initial_mylist_sync(self, pathitems): """Perform an initial sync of My List and the Kodi library""" # pylint: disable=unused-argument do_it = ui.ask_for_confirmation(common.get_local_string(30122), common.get_local_string(30123)) if not do_it or not g.ADDON.getSettingBool('mylist_library_sync'): return common.debug('Performing full sync from My List to Kodi library') library.purge() for videoid in api.video_list( api.list_id_for_type('queue')).videoids: library.execute_library_tasks(videoid, library.export_item, common.get_local_string(30018), sync_mylist=False)
def reset_esn(self, pathitems=None): # pylint: disable=unused-argument """Reset the ESN stored (retrieved from website and manual)""" from resources.lib.database.db_utils import (TABLE_SESSION, TABLE_SETTINGS_MONITOR) if not ui.ask_for_confirmation(common.get_local_string(30217), common.get_local_string(30218)): return # Reset the ESN obtained from website/generated g.LOCAL_DB.set_value('esn', '', TABLE_SESSION) # Reset the custom ESN (manual ESN from settings) g.settings_monitor_suspend(at_first_change=True) g.ADDON.setSetting('esn', '') # Reset the custom ESN (backup of manual ESN from settings, used in settings_monitor.py) g.LOCAL_DB.set_value('custom_esn', '', TABLE_SETTINGS_MONITOR) # Perform a new login to get/generate a new ESN api.login(ask_credentials=False) # Warning after login netflix switch to the main profile! so return to the main screen # Open root page common.container_update(g.BASE_URL, True)
def initial_mylist_sync(self, pathitems): """Perform an initial sync of My List and the Kodi library""" # pylint: disable=unused-argument from resources.lib.cache import CACHE_COMMON do_it = ui.ask_for_confirmation(common.get_local_string(30122), common.get_local_string(30123)) if not do_it: return common.debug('Performing full sync from My List to Kodi library') library.purge() nfo_settings = nfo.NFOSettings() nfo_settings.show_export_dialog() # Invalidate my-list cached data to force to obtain new data g.CACHE.invalidate_entry(CACHE_COMMON, 'my_list_items') for videoid in api.mylist_items(): library.execute_library_tasks(videoid, [library.export_item], common.get_local_string(30018), sync_mylist=False, nfo_settings=nfo_settings)
def _import_library_remove(self, remove_titles, remove_folders): if not remove_folders: return False # If there are STRM files that it was not possible to import them, # we will ask to user if you want to delete them tot_folders = len(remove_folders) if tot_folders > 50: remove_titles = remove_titles[:50] + ['...'] message = common.get_local_string(30246).format(tot_folders) + '[CR][CR]' + ', '.join(remove_titles) if not ui.ask_for_confirmation(common.get_local_string(30140), message): return False # Delete all folders LOG.info('Start deleting folders') with ui.ProgressDialog(True, max_value=tot_folders) as progress_bar: for file_path in remove_folders: progress_bar.set_message('{}/{}'.format(progress_bar.value, tot_folders)) LOG.debug('Deleting folder: {}', file_path) common.delete_folder(file_path) progress_bar.perform_step() return True
def reset_esn(self, pathitems=None): # pylint: disable=unused-argument """Reset the ESN stored (retrieved from website and manual)""" if not ui.ask_for_confirmation(common.get_local_string(30217), common.get_local_string(30218)): return # Generate a new ESN generated_esn = self._get_new_esn() # Reset the ESN obtained from website/generated G.LOCAL_DB.set_value('esn', '', TABLE_SESSION) # Reset the custom ESN (manual ESN from settings) G.settings_monitor_suspend(at_first_change=True) G.ADDON.setSetting('esn', '') # Reset the custom ESN (backup of manual ESN from settings, used in settings_monitor.py) G.LOCAL_DB.set_value('custom_esn', '', TABLE_SETTINGS_MONITOR) # Save the new ESN G.LOCAL_DB.set_value('esn', generated_esn, TABLE_SESSION) # Reinitialize the MSL handler (delete msl data file, then reset everything) common.send_signal(signal=common.Signals.REINITIALIZE_MSL_HANDLER, data=True) # Show login notification ui.show_notification(common.get_local_string(30109)) # Open root page common.container_update(G.BASE_URL, True)
def reset_esn(self, pathitems=None): # pylint: disable=unused-argument """Reset the ESN stored (retrieved from website and manual)""" from resources.lib.database.db_utils import (TABLE_SESSION, TABLE_SETTINGS_MONITOR) if not ui.ask_for_confirmation(common.get_local_string(30217), common.get_local_string(30218)): return # Reset the ESN obtained from website/generated g.LOCAL_DB.set_value('esn', '', TABLE_SESSION) # Reset the custom ESN (manual ESN from settings) g.settings_monitor_suspend(at_first_change=True) g.ADDON.setSetting('esn', '') # Reset the custom ESN (backup of manual ESN from settings, used in settings_monitor.py) g.LOCAL_DB.set_value('custom_esn', '', TABLE_SETTINGS_MONITOR) # Perform a new login to get/generate a new ESN api.login(ask_credentials=False) # Warning after login netflix switch to the main profile! so return to the main screen url = 'plugin://plugin.video.netflix/directory/root' xbmc.executebuiltin( 'XBMC.Container.Update(path,replace)') # Clean path history xbmc.executebuiltin( 'Container.Update({})'.format(url)) # Open root page
def auto_update_library(self, sync_with_mylist, show_prg_dialog=True, show_nfo_dialog=False, clear_on_cancel=False, update_profiles=False): """ Perform an auto update of the exported items in to Kodi library. - The main purpose is check if there are new seasons/episodes. - In the case "Sync Kodi library with My list" feature is enabled, will be also synchronized with My List. :param sync_with_mylist: if True, sync the Kodi library with Netflix My List :param show_prg_dialog: if True, will be show a progress dialog window and the errors will be notified to user :param show_nfo_dialog: if True, ask to user if want export NFO files (override custom NFO actions for videoid) :param clear_on_cancel: if True, when the user cancel the operations will be cleared the entire library :param update_profiles: if True, before perform sync_with_mylist will be updated the profiles """ if is_auto_update_library_running(show_prg_dialog): return LOG.info('Start auto-updating of Kodi library {}', '(with sync of My List)' if sync_with_mylist else '') G.SHARED_DB.set_value('library_auto_update_is_running', True) G.SHARED_DB.set_value('library_auto_update_start_time', datetime.now()) try: # Get the full list of the exported tvshows/movies as id (VideoId.value) exp_tvshows_videoids_values = G.SHARED_DB.get_tvshows_id_list() exp_movies_videoids_values = G.SHARED_DB.get_movies_id_list() # Get the exported tv shows (to be updated) as dict (key=videoid, value=type of task) videoids_tasks = { common.VideoId.from_path([common.VideoId.SHOW, videoid_value]): self.export_new_item for videoid_value in G.SHARED_DB.get_tvshows_id_list(VidLibProp['exclude_update'], False) } if sync_with_mylist and update_profiles: # Before do the sync with My list try to update the profiles in the database, # to do a sanity check of the features that are linked to the profiles self.ext_func_req_profiles_info(update_database=True) # pylint: disable=not-callable sync_with_mylist = G.ADDON.getSettingBool('lib_sync_mylist') # If enabled sync the Kodi library with Netflix My List if sync_with_mylist: self._sync_my_list_ops(videoids_tasks, exp_tvshows_videoids_values, exp_movies_videoids_values) # Show a warning message when there are more than 100 titles to be updated, making too many metadata # requests may cause blocking of http communication from the server or temporary ban of the account if show_prg_dialog: total_titles_upd = sum(task != self.remove_item for task in videoids_tasks.values()) if total_titles_upd >= 100 and not ui.ask_for_confirmation( common.get_local_string(30122), common.get_local_string(30059).format(total_titles_upd)): return # Start the update operations ret = self._update_library(videoids_tasks, exp_tvshows_videoids_values, show_prg_dialog, show_nfo_dialog, clear_on_cancel) if not ret: return request_kodi_library_update(scan=True, clean=True) # Save date for completed operation to compute next update schedule (used in library_updater.py) G.SHARED_DB.set_value('library_auto_update_last_start', datetime.now()) LOG.info('Auto update of the Kodi library completed') if not G.ADDON.getSettingBool('lib_auto_upd_disable_notification'): ui.show_notification(common.get_local_string(30220), time=5000) except Exception as exc: # pylint: disable=broad-except import traceback LOG.error('An error has occurred in the library auto update: {}', exc) LOG.error(G.py2_decode(traceback.format_exc(), 'latin-1')) finally: G.SHARED_DB.set_value('library_auto_update_is_running', False)
def purge(self, pathitems): """Delete all previously exported items from the Kodi library""" # pylint: disable=unused-argument if ui.ask_for_confirmation(common.get_local_string(30125), common.get_local_string(30126)): library.purge()