def select_libraries(self, mode=None): ''' Select from libraries synced. Either update or repair libraries. Send event back to service.py ''' modes = { 'SyncLibrarySelection': 'SyncLibrary', 'RepairLibrarySelection': 'RepairLibrary', 'AddLibrarySelection': 'SyncLibrary', 'RemoveLibrarySelection': 'RemoveLibrary' } sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] libraries = [] with Database('jellyfin') as jellyfindb: db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) if mode in ('SyncLibrarySelection', 'RepairLibrarySelection', 'RemoveLibrarySelection'): for library in sync['Whitelist']: name = db.get_view_name(library.replace('Mixed:', "")) libraries.append({'Id': library, 'Name': name}) else: available = [ x for x in sync['SortedViews'] if x not in whitelist ] for library in available: name, media = db.get_view(library) if media in ('movies', 'tvshows', 'musicvideos', 'mixed', 'music'): libraries.append({'Id': library, 'Name': name}) choices = [x['Name'] for x in libraries] choices.insert(0, translate(33121)) titles = { "RepairLibrarySelection": 33199, "SyncLibrarySelection": 33198, "RemoveLibrarySelection": 33200, "AddLibrarySelection": 33120 } title = titles.get(mode, "Failed to get title {}".format(mode)) selection = dialog("multi", translate(title), choices) if selection is None: return if 0 in selection: selection = list(range(1, len(libraries) + 1)) selected_libraries = [] for x in selection: library = libraries[x - 1] selected_libraries.append(library['Id']) event( modes[mode], { 'Id': ','.join([libraries[x - 1]['Id'] for x in selection]), 'Update': mode == 'SyncLibrarySelection' })
def startup(self): ''' Run at startup. Check databases. Check for the server plugin. ''' self.test_databases() Views().get_views() Views().get_nodes() try: if get_sync()['Libraries']: try: with FullSync(self, self.server) as sync: sync.libraries() Views().get_nodes() except Exception as error: LOG.error(error) elif not settings('SyncInstallRunDone.bool'): with FullSync(self, self.server) as sync: sync.libraries() Views().get_nodes() return True if settings('SyncInstallRunDone.bool'): if settings('kodiCompanion.bool'): for plugin in self.server['api'].get_plugins(): if plugin['Name'] in ("Emby.Kodi Sync Queue", "Kodi companion"): if not self.fast_sync(): dialog("ok", heading="{emby}", line1=_(33128)) raise Exception( "Failed to retrieve latest updates") LOG.info("--<[ retrieve changes ]") break else: raise LibraryException('CompanionMissing') return True except LibraryException as error: LOG.error(error.status) if error.status in 'SyncLibraryLater': dialog("ok", heading="{emby}", line1=_(33129)) settings('SyncInstallRunDone.bool', True) sync = get_sync() sync['Libraries'] = [] save_sync(sync) return True elif error.status == 'CompanionMissing': dialog("ok", heading="{emby}", line1=_(33099)) settings('kodiCompanion.bool', False) return True except Exception as error: LOG.exception(error) return False
def startup(self): ''' Run at startup. Check databases. Check for the server plugin. ''' self.test_databases() Views().get_views() Views().get_nodes() try: if get_sync()['Libraries']: try: with FullSync(self, self.server) as sync: sync.libraries() Views().get_nodes() except Exception as error: LOG.exception(error) elif not settings('SyncInstallRunDone.bool'): with FullSync(self, self.server) as sync: sync.libraries() Views().get_nodes() return True if settings('SyncInstallRunDone.bool'): if settings('kodiCompanion.bool'): if self.server.jellyfin.check_companion_installed(): if not self.fast_sync(): dialog("ok", "{jellyfin}", translate(33128)) raise Exception( "Failed to retrieve latest updates") LOG.info("--<[ retrieve changes ]") else: raise LibraryException('CompanionMissing') return True except LibraryException as error: LOG.error(error.status) if error.status in 'SyncLibraryLater': dialog("ok", "{jellyfin}", translate(33129)) settings('SyncInstallRunDone.bool', True) sync = get_sync() sync['Libraries'] = [] save_sync(sync) return True elif error.status == 'CompanionMissing': dialog("ok", "{jellyfin}", translate(33099)) settings('kodiCompanion.bool', False) return True except Exception as error: LOG.exception(error) return False
def fast_sync(self): ''' Movie and userdata not provided by server yet. ''' last_sync = settings('LastIncrementalSync') include = [] filters = ["tvshows", "boxsets", "musicvideos", "music", "movies"] sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] LOG.info("--[ retrieve changes ] %s", last_sync) # Get the item type of each synced library and build list of types to request for item_id in whitelist: library = self.server.jellyfin.get_item(item_id) library_type = library.get('CollectionType') if library_type in filters: include.append(library_type) # Include boxsets if movies are synced if 'movies' in include: include.append('boxsets') # Filter down to the list of library types we want to exclude query_filter = list(set(filters) - set(include)) try: # Get list of updates from server for synced library types and populate work queues result = self.server.jellyfin.get_sync_queue( last_sync, ",".join([x for x in query_filter])) if result is None: return True updated = [] userdata = [] removed = [] updated.extend(result['ItemsAdded']) updated.extend(result['ItemsUpdated']) userdata.extend(result['UserDataChanged']) removed.extend(result['ItemsRemoved']) total = len(updated) + len(userdata) if total > int(settings('syncIndicator') or 99): ''' Inverse yes no, in case the dialog is forced closed by Kodi. ''' if dialog("yesno", "{jellyfin}", translate(33172).replace('{number}', str(total)), nolabel=translate(107), yeslabel=translate(106)): LOG.warning("Large updates skipped.") return True self.updated(updated) self.userdata(userdata) self.removed(removed) except Exception as error: LOG.exception(error) return False return True
def fast_sync(self): ''' Movie and userdata not provided by server yet. ''' last_sync = settings('LastIncrementalSync') filters = ["tvshows", "boxsets", "musicvideos", "music", "movies"] sync = get_sync() LOG.info("--[ retrieve changes ] %s", last_sync) try: updated = [] userdata = [] removed = [] for media in filters: result = self.server.jellyfin.get_sync_queue( last_sync, ",".join([x for x in filters if x != media])) updated.extend(result['ItemsAdded']) updated.extend(result['ItemsUpdated']) userdata.extend(result['UserDataChanged']) removed.extend(result['ItemsRemoved']) total = len(updated) + len(userdata) if total > int(settings('syncIndicator') or 99): ''' Inverse yes no, in case the dialog is forced closed by Kodi. ''' if dialog("yesno", heading="{jellyfin}", line1=translate(33172).replace( '{number}', str(total)), nolabel=translate(107), yeslabel=translate(106)): LOG.warning("Large updates skipped.") return True self.updated(updated) self.userdata(userdata) self.removed(removed) """ result = self.server.jellyfin.get_sync_queue(last_sync) self.userdata(result['UserDataChanged']) self.removed(result['ItemsRemoved']) filters.extend(["tvshows", "boxsets", "musicvideos", "music"]) # Get only movies. result = self.server.jellyfin.get_sync_queue(last_sync, ",".join(filters)) self.updated(result['ItemsAdded']) self.updated(result['ItemsUpdated']) self.userdata(result['UserDataChanged']) self.removed(result['ItemsRemoved']) """ except Exception as error: LOG.exception(error) return False return True
def remove_library(self, library_id, dialog): ''' Remove library by their id from the Kodi database. ''' direct_path = self.library.direct_path with Database('jellyfin') as jellyfindb: db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) library = db.get_view(library_id.replace('Mixed:', "")) items = db.get_item_by_media_folder( library_id.replace('Mixed:', "")) media = 'music' if library[1] == 'music' else 'video' if media == 'music': settings('MusicRescan.bool', False) if items: count = 0 with self.library.music_database_lock if media == 'music' else self.library.database_lock: with Database(media) as kodidb: if library[1] == 'mixed': movies = [x for x in items if x[1] == 'Movie'] tvshows = [x for x in items if x[1] == 'Series'] obj = Movies(self.server, jellyfindb, kodidb, direct_path).remove for item in movies: obj(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library[0])) count += 1 obj = TVShows(self.server, jellyfindb, kodidb, direct_path).remove for item in tvshows: obj(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library[0])) count += 1 else: default_args = (self.server, jellyfindb, kodidb, direct_path) for item in items: if item[1] in ('Series', 'Season', 'Episode'): TVShows(*default_args).remove(item[0]) elif item[1] in ('Movie', 'BoxSet'): Movies(*default_args).remove(item[0]) elif item[1] in ('MusicAlbum', 'MusicArtist', 'AlbumArtist', 'Audio'): Music(*default_args).remove(item[0]) elif item[1] == 'MusicVideo': MusicVideos(*default_args).remove(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (translate('addon_name'), library[0])) count += 1 self.sync = get_sync() if library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove(library_id) elif 'Mixed:%s' % library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove('Mixed:%s' % library_id) save_sync(self.sync)
def listing(): ''' Display all emby nodes and dynamic entries when appropriate. ''' total = int(window('Emby.nodes.total') or 0) sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] servers = get_credentials()['Servers'][1:] for i in range(total): window_prop = "Emby.nodes.%s" % i path = window('%s.index' % window_prop) if not path: path = window('%s.content' % window_prop) or window('%s.path' % window_prop) label = window('%s.title' % window_prop) node = window('%s.type' % window_prop) artwork = window('%s.artwork' % window_prop) view_id = window('%s.id' % window_prop) context = [] if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed') and view_id not in whitelist: label = "%s %s" % (label.decode('utf-8'), _(33166)) context.append((_(33123), "RunPlugin(plugin://plugin.video.emby/?mode=synclib&id=%s)" % view_id)) if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist: context.append((_(33136), "RunPlugin(plugin://plugin.video.emby/?mode=updatelib&id=%s)" % view_id)) context.append((_(33132), "RunPlugin(plugin://plugin.video.emby/?mode=repairlib&id=%s)" % view_id)) context.append((_(33133), "RunPlugin(plugin://plugin.video.emby/?mode=removelib&id=%s)" % view_id)) LOG.debug("--[ listing/%s/%s ] %s", node, label, path) if path: if xbmc.getCondVisibility('Window.IsActive(Pictures)') and node in ('photos', 'homevideos'): directory(label, path, artwork=artwork) elif xbmc.getCondVisibility('Window.IsActive(Videos)') and node not in ('photos', 'music', 'audiobooks'): directory(label, path, artwork=artwork, context=context) elif xbmc.getCondVisibility('Window.IsActive(Music)') and node in ('music'): directory(label, path, artwork=artwork, context=context) elif not xbmc.getCondVisibility('Window.IsActive(Videos) | Window.IsActive(Pictures) | Window.IsActive(Music)'): directory(label, path, artwork=artwork) for server in servers: context = [] if server.get('ManualAddress'): context.append((_(30500), "RunPlugin(plugin://plugin.video.emby/?mode=setssl&server=%s)" % server['Id'])) context.append((_(33141), "RunPlugin(plugin://plugin.video.emby/?mode=removeserver&server=%s)" % server['Id'])) if 'AccessToken' not in server: directory("%s (%s)" % (server['Name'], _(30539)), "plugin://plugin.video.emby/?mode=login&server=%s" % server['Id'], False, context=context) else: directory(server['Name'], "plugin://plugin.video.emby/?mode=browse&server=%s" % server['Id'], context=context) directory(_(33194), "plugin://plugin.video.emby/?mode=managelibs", True) directory(_(33134), "plugin://plugin.video.emby/?mode=addserver", False) directory(_(33054), "plugin://plugin.video.emby/?mode=adduser", False) directory(_(5), "plugin://plugin.video.emby/?mode=settings", False) directory(_(33059), "plugin://plugin.video.emby/?mode=texturecache", False) directory(_(33058), "plugin://plugin.video.emby/?mode=reset", False) directory(_(33192), "plugin://plugin.video.emby/?mode=restartservice", False) if settings('backupPath'): directory(_(33092), "plugin://plugin.video.emby/?mode=backup", False) directory("Changelog", "plugin://plugin.video.emby/?mode=changelog", False) directory(_(33163), None, False, artwork="special://home/addons/plugin.video.emby/donations.png") xbmcplugin.setContent(int(sys.argv[1]), 'files') xbmcplugin.endOfDirectory(int(sys.argv[1]))
def __init__(self): self.sync = get_sync() self.server = Jellyfin()
def fast_sync(self): ''' Movie and userdata not provided by server yet. ''' last_sync = settings('LastIncrementalSync') filters = ["tvshows", "boxsets", "musicvideos", "music", "movies"] sync = get_sync() LOG.info("--[ retrieve changes ] %s", last_sync) """ for library in sync['Whitelist']: data = self.server.jellyfin.get_date_modified(last_sync, library.replace('Mixed:', ""), "Series,Episode,BoxSet,Movie,MusicVideo,MusicArtist,MusicAlbum,Audio") [self.updated_output[query['Type']].put(query) for query in data['Items']] """ try: updated = [] userdata = [] removed = [] for media in filters: result = self.server.jellyfin.get_sync_queue( last_sync, ",".join([x for x in filters if x != media])) updated.extend(result['ItemsAdded']) updated.extend(result['ItemsUpdated']) userdata.extend(result['UserDataChanged']) removed.extend(result['ItemsRemoved']) total = len(updated) + len(userdata) if total > int(settings('syncIndicator') or 99): ''' Inverse yes no, in case the dialog is forced closed by Kodi. ''' if dialog("yesno", heading="{jellyfin}", line1=_(33172).replace('{number}', str(total)), nolabel=_(107), yeslabel=_(106)): LOG.warning("Large updates skipped.") return True self.updated(updated) self.userdata(userdata) self.removed(removed) """ result = self.server.jellyfin.get_sync_queue(last_sync) self.userdata(result['UserDataChanged']) self.removed(result['ItemsRemoved']) filters.extend(["tvshows", "boxsets", "musicvideos", "music"]) # Get only movies. result = self.server.jellyfin.get_sync_queue(last_sync, ",".join(filters)) self.updated(result['ItemsAdded']) self.updated(result['ItemsUpdated']) self.userdata(result['UserDataChanged']) self.removed(result['ItemsRemoved']) """ except Exception as error: LOG.exception(error) return False return True
def remove_library(self, library_id, dialog): ''' Remove library by their id from the Kodi database. ''' MEDIA = self.library.MEDIA direct_path = self.library.direct_path with Database('jellyfin') as jellyfindb: db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) library = db.get_view(library_id.replace('Mixed:', "")) items = db.get_item_by_media_folder( library_id.replace('Mixed:', "")) media = 'music' if library[1] == 'music' else 'video' if media == 'music': settings('MusicRescan.bool', False) if items: count = 0 with self.library.music_database_lock if media == 'music' else self.library.database_lock: with Database(media) as kodidb: if library[1] == 'mixed': movies = [x for x in items if x[1] == 'Movie'] tvshows = [x for x in items if x[1] == 'Series'] obj = MEDIA['Movie'](self.server, jellyfindb, kodidb, direct_path)['Remove'] for item in movies: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 obj = MEDIA['Series'](self.server, jellyfindb, kodidb, direct_path)['Remove'] for item in tvshows: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 else: obj = MEDIA[items[0][1]](self.server, jellyfindb, kodidb, direct_path)['Remove'] for item in items: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 self.sync = get_sync() if library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove(library_id) elif 'Mixed:%s' % library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove('Mixed:%s' % library_id) save_sync(self.sync)
def remove_library(self, library_id, dialog): ''' Remove library by their id from the Kodi database. ''' MEDIA = self.library.MEDIA direct_path = self.library.direct_path with Database('jellyfin') as jellyfindb: db = jellyfin_db.JellyfinDatabase(jellyfindb.cursor) library = db.get_view(library_id.replace('Mixed:', "")) items = db.get_item_by_media_folder( library_id.replace('Mixed:', "")) media = 'music' if library[1] == 'music' else 'video' if media == 'music': settings('MusicRescan.bool', False) if items: count = 0 with self.library.music_database_lock if media == 'music' else self.library.database_lock: with Database(media) as kodidb: if library[1] == 'mixed': movies = [x for x in items if x[1] == 'Movie'] tvshows = [x for x in items if x[1] == 'Series'] obj = Movies(self.server, jellyfindb, kodidb, direct_path).remove for item in movies: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 obj = TVShows(self.server, jellyfindb, kodidb, direct_path).remove for item in tvshows: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 else: # from mcarlton: I'm not sure what triggers this. # I've added and removed every media type except # for music videos (because i don't have any) and # can't find it, but I'm not comfortable # removing it right now LOG.info('Triggered the mystery function') LOG.debug('Mystery function item type: {}'.format( items[0][1])) obj = MEDIA[items[0][1]](self.server, jellyfindb, kodidb, direct_path).remove for item in items: obj(item[0]) dialog.update(int( (float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 self.sync = get_sync() if library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove(library_id) elif 'Mixed:%s' % library_id in self.sync['Whitelist']: self.sync['Whitelist'].remove('Mixed:%s' % library_id) save_sync(self.sync)
def __init__(self): self.sync = get_sync() self.server = Emby()
def listing(): ''' Display all jellyfin nodes and dynamic entries when appropriate. ''' total = int(window('Jellyfin.nodes.total') or 0) sync = get_sync() whitelist = [x.replace('Mixed:', "") for x in sync['Whitelist']] servers = get_credentials()['Servers'][1:] for i in range(total): window_prop = "Jellyfin.nodes.%s" % i path = window('%s.index' % window_prop) if not path: path = window('%s.content' % window_prop) or window('%s.path' % window_prop) label = window('%s.title' % window_prop) node = window('%s.type' % window_prop) artwork = window('%s.artwork' % window_prop) view_id = window('%s.id' % window_prop) context = [] if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music', 'mixed') and view_id not in whitelist: label = "%s %s" % (label, translate(33166)) context.append((translate(33123), "RunPlugin(plugin://plugin.video.jellyfin/?mode=synclib&id=%s)" % view_id)) if view_id and node in ('movies', 'tvshows', 'musicvideos', 'music') and view_id in whitelist: context.append((translate(33136), "RunPlugin(plugin://plugin.video.jellyfin/?mode=updatelib&id=%s)" % view_id)) context.append((translate(33132), "RunPlugin(plugin://plugin.video.jellyfin/?mode=repairlib&id=%s)" % view_id)) context.append((translate(33133), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removelib&id=%s)" % view_id)) LOG.debug("--[ listing/%s/%s ] %s", node, label, path) if path: directory(label, path, artwork=artwork, context=context) for server in servers: context = [] if server.get('ManualAddress'): context.append((translate(33141), "RunPlugin(plugin://plugin.video.jellyfin/?mode=removeserver&server=%s)" % server['Id'])) if 'AccessToken' not in server: directory("%s (%s)" % (server['Name'], translate(30539)), "plugin://plugin.video.jellyfin/?mode=login&server=%s" % server['Id'], False, context=context) else: directory(server['Name'], "plugin://plugin.video.jellyfin/?mode=browse&server=%s" % server['Id'], context=context) directory(translate(33194), "plugin://plugin.video.jellyfin/?mode=managelibs", True) directory(translate(33134), "plugin://plugin.video.jellyfin/?mode=addserver", False) directory(translate(33054), "plugin://plugin.video.jellyfin/?mode=adduser", False) directory(translate(5), "plugin://plugin.video.jellyfin/?mode=settings", False) directory(translate(33161), "plugin://plugin.video.jellyfin/?mode=updatepassword", False) directory(translate(33058), "plugin://plugin.video.jellyfin/?mode=reset", False) directory(translate(33180), "plugin://plugin.video.jellyfin/?mode=restartservice", False) if settings('backupPath'): directory(translate(33092), "plugin://plugin.video.jellyfin/?mode=backup", False) xbmcplugin.setContent(PROCESS_HANDLE, 'files') xbmcplugin.endOfDirectory(PROCESS_HANDLE)
def service(self): ''' If error is encountered, it will rerun this function. Start new "daemon threads" to process library updates. (actual daemon thread is not supported in Kodi) ''' for thread in self.download_threads: if thread.is_done: self.removed(thread.removed) self.download_threads.remove(thread) for threads in (self.emby_threads, self.writer_threads['updated'], self.writer_threads['userdata'], self.writer_threads['removed']): for thread in threads: if thread.is_done: threads.remove(thread) if not self.player.isPlayingVideo() or settings( 'syncDuringPlay.bool') or xbmc.getCondVisibility( 'VideoPlayer.Content(livetv)'): if not self.player.isPlayingVideo() or xbmc.getCondVisibility( 'VideoPlayer.Content(livetv)'): if self.verify_libs: self.verify_libs = False if get_sync()['Libraries']: self.sync_libraries(True) self.worker_remove_lib() self.worker_add_lib() self.worker_verify() self.worker_downloads() self.worker_sort() self.worker_updates() self.worker_userdata() self.worker_remove() self.worker_notify() if self.pending_refresh: window('emby_sync.bool', True) self.set_progress_dialog() if not settings( 'dbSyncScreensaver.bool') and self.screensaver is None: xbmc.executebuiltin('InhibitIdleShutdown(true)') self.screensaver = get_screensaver() set_screensaver(value="") if (self.pending_refresh and not self.download_threads and not self.writer_threads['updated'] and not self.writer_threads['userdata'] and not self.writer_threads['removed']): self.pending_refresh = False self.save_last_sync() self.total_updates = 0 window('emby_sync', clear=True) if self.progress_updates: LOG.info("--<[ pdialog ]") self.progress_updates.close() self.progress_updates = None if not settings( 'dbSyncScreensaver.bool') and self.screensaver is not None: xbmc.executebuiltin('InhibitIdleShutdown(false)') set_screensaver(value=self.screensaver) self.screensaver = None if not xbmc.getCondVisibility('Window.IsMedia'): xbmc.executebuiltin('UpdateLibrary(video)') else: # Prevent cursor from moving xbmc.executebuiltin('Container.Refresh') window('emby.updatewidgets.bool', True) elif window('emby.updatewidgets.bool' ) and not xbmc.getCondVisibility('Window.IsMedia'): ''' In case an update happened but we were not on the homescreen and now we are, force widget to update. ''' window('emby.updatewidgets', clear=True) xbmc.executebuiltin('UpdateLibrary(video)')
def remove_library(self, library_id, dialog): try: with Database('emby') as embydb: db = emby_db.EmbyDatabase(embydb.cursor) library = db.get_view(library_id.replace('Mixed:', "")) items = db.get_item_by_media_folder( library_id.replace('Mixed:', "")) media = 'music' if library[1] == 'music' else 'video' if media == 'music': settings('MusicRescan.bool', False) if items: count = 0 with self.music_database_lock if media == 'music' else self.database_lock: with Database(media) as kodidb: if library[1] == 'mixed': movies = [x for x in items if x[1] == 'Movie'] tvshows = [ x for x in items if x[1] == 'Series' ] obj = MEDIA['Movie']( self.server, embydb, kodidb, self.direct_path)['Remove'] for item in movies: obj(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 obj = MEDIA['Series']( self.server, embydb, kodidb, self.direct_path)['Remove'] for item in tvshows: obj(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 else: obj = MEDIA[items[0][1]]( self.server, embydb, kodidb, self.direct_path)['Remove'] for item in items: obj(item[0]) dialog.update( int((float(count) / float(len(items)) * 100)), heading="%s: %s" % (_('addon_name'), library[0])) count += 1 sync = get_sync() if library_id in sync['Whitelist']: sync['Whitelist'].remove(library_id) elif 'Mixed:%s' % library_id in sync['Whitelist']: sync['Whitelist'].remove('Mixed:%s' % library_id) save_sync(sync) Views().remove_library(library_id) except Exception as error: LOG.exception(error) dialog.close() return False Views().get_views() Views().get_nodes() return True