def get_libraries(self, library_id=None): with Database('emby') as embydb: if library_id is None: return emby_db.EmbyDatabase(embydb.cursor).get_views() else: return emby_db.EmbyDatabase(embydb.cursor).get_view(library_id)
def remove_library(self, view_id): ''' Remove entry from view table in emby database. ''' with Database('emby') as embydb: emby_db.EmbyDatabase(embydb.cursor).remove_view(view_id) self.delete_playlist_by_id(view_id) self.delete_node_by_id(view_id)
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('emby') as embydb: db = emby_db.EmbyDatabase(embydb.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, _(33121)) selection = dialog("multi", _(33120), 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 musicvideos_compare(self, library, obj, embydb): ''' Compare entries from library to what's in the embydb. Remove surplus ''' db = emby_db.EmbyDatabase(embydb.cursor) items = db.get_item_by_media_folder(library['Id']) current = obj.item_ids for x in items: if x[0] not in current and x[1] == 'MusicVideo': obj.remove(x[0])
def __init__(self, server, embydb, musicdb, direct_path): self.server = server self.emby = embydb self.music = musicdb self.direct_path = direct_path self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.objects = Objects() self.item_ids = [] KodiDb.__init__(self, musicdb.cursor)
def __init__(self, server, embydb, videodb, direct_path, *args, **kwargs): self.server = server self.emby = embydb self.video = videodb self.direct_path = direct_path self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.objects = Objects() self.item_ids = [] KodiDb.__init__(self, videodb.cursor)
def get_views(self): ''' Get the media folders. Add or remove them. Do not proceed if issue getting libraries. ''' media = { 'movies': "Movie", 'tvshows': "Series", 'musicvideos': "MusicVideo" } try: libraries = self.get_libraries() except IndexError as error: LOG.error(error) return self.sync['SortedViews'] = [x['Id'] for x in libraries] for library in libraries: if library['Type'] == 'Channel': library['Media'] = "channels" else: library['Media'] = library.get( 'OriginalCollectionType', library.get('CollectionType', "mixed")) self.add_library(library) with Database('emby') as embydb: views = emby_db.EmbyDatabase(embydb.cursor).get_views() sorted_views = self.sync['SortedViews'] whitelist = self.sync['Whitelist'] removed = [] for view in views: if view[0] not in sorted_views: removed.append(view[0]) if removed: event('RemoveLibrary', {'Id': ','.join(removed)}) for library_id in removed: if library_id in sorted_views: sorted_views.remove(library_id) if library_id in whitelist: whitelist.remove(library_id) save_sync(self.sync)
def __init__(self, server, embydb, videodb, direct_path, update_library=False): self.server = server self.emby = embydb self.video = videodb self.direct_path = direct_path self.update_library = update_library self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.objects = Objects() self.item_ids = [] KodiDb.__init__(self, videodb.cursor)
def music_compare(self, library, obj, embydb): ''' Compare entries from library to what's in the embydb. Remove surplus ''' db = emby_db.EmbyDatabase(embydb.cursor) items = db.get_item_by_media_folder(library['Id']) for x in list(items): items.extend(obj.get_child(x[0])) current = obj.item_ids for x in items: if x[0] not in current and x[1] == 'MusicArtist': obj.remove(x[0])
def __init__(self, server, embydb, videodb, direct_path, update_library=False, verify=False, *args, **kwargs): self.server = server self.emby = embydb self.video = videodb self.direct_path = direct_path self.update_library = update_library self.verify = verify self.emby_db = emby_db.EmbyDatabase(embydb.cursor) self.objects = Objects() self.item_ids = [] self.display_specials = settings('SeasonSpecials.bool') KodiDb.__init__(self, videodb.cursor)
def check_version(self): ''' Check the database version to ensure we do not need to do a reset. ''' with Database('emby') as embydb: version = emby_db.EmbyDatabase(embydb.cursor).get_version() LOG.info("---[ db/%s ]", version) if version and compare_version(version, "3.1.0") < 0: resp = dialog("yesno", heading=_('addon_name'), line1=_(33022)) if not resp: LOG.warn("Database version is out of date! USER IGNORED!") dialog("ok", heading=_('addon_name'), line1=_(33023)) raise Exception("User backed out of a required database reset") else: reset() raise Exception("Completed database reset")
def get_views(self): ''' Get the media folders. Add or remove them. ''' media = { 'movies': "Movie", 'tvshows': "Series", 'musicvideos': "MusicVideo" } libraries = self.get_libraries() self.sync['SortedViews'] = [x['Id'] for x in libraries] for library in libraries: if library['Type'] == 'Channel': library['Media'] = "channels" else: library['Media'] = library.get( 'OriginalCollectionType', library.get('CollectionType', "mixed")) self.add_library(library) with Database('emby') as embydb: views = emby_db.EmbyDatabase(embydb.cursor).get_views() removed = [] for view in views: if view[0] not in self.sync['SortedViews']: removed.append(view[0]) if removed: event('RemoveLibrary', {'Id': ','.join(removed)}) save_sync(self.sync)
def run(self): with Database('emby') as embydb: database = emby_db.EmbyDatabase(embydb.cursor) while True: try: item_id = self.queue.get(timeout=1) except Queue.Empty: break try: media = database.get_media_by_id(item_id) self.output[media].put({'Id': item_id, 'Type': media}) except Exception: items = database.get_media_by_parent_id(item_id) if not items: LOG.info( "Could not find media %s in the emby database.", item_id) else: for item in items: self.output[item[1]].put({ 'Id': item[0], 'Type': item[1] }) self.queue.task_done() if window('emby_should_stop.bool'): break LOG.info("--<[ q:sort/%s ]", id(self)) self.is_done = True
def get_themes(): ''' Add theme media locally, via strm. This is only for tv tunes. If another script is used, adjust this code. ''' from helper.utils import normalize_string from helper.playutils import PlayUtils from helper.xmls import tvtunes_nfo library = xbmc.translatePath("special://profile/addon_data/plugin.video.emby/library").decode('utf-8') play = settings('useDirectPaths') == "1" if not xbmcvfs.exists(library + '/'): xbmcvfs.mkdir(library) if xbmc.getCondVisibility('System.HasAddon(script.tvtunes)'): tvtunes = xbmcaddon.Addon(id="script.tvtunes") tvtunes.setSetting('custom_path_enable', "true") tvtunes.setSetting('custom_path', library) LOG.info("TV Tunes custom path is enabled and set.") else: dialog("ok", heading="{emby}", line1=_(33152)) return with Database('emby') as embydb: all_views = emby_db.EmbyDatabase(embydb.cursor).get_views() views = [x[0] for x in all_views if x[2] in ('movies', 'tvshows', 'mixed')] items = {} server = TheVoid('GetServerAddress', {'ServerId': None}).get() token = TheVoid('GetToken', {'ServerId': None}).get() for view in views: result = TheVoid('GetThemes', {'Type': "Video", 'Id': view}).get() for item in result['Items']: folder = normalize_string(item['Name'].encode('utf-8')) items[item['Id']] = folder result = TheVoid('GetThemes', {'Type': "Song", 'Id': view}).get() for item in result['Items']: folder = normalize_string(item['Name'].encode('utf-8')) items[item['Id']] = folder for item in items: nfo_path = os.path.join(library, items[item]) nfo_file = os.path.join(nfo_path, "tvtunes.nfo") if not xbmcvfs.exists(nfo_path): xbmcvfs.mkdir(nfo_path) themes = TheVoid('GetTheme', {'Id': item}).get() paths = [] for theme in themes['ThemeVideosResult']['Items'] + themes['ThemeSongsResult']['Items']: putils = PlayUtils(theme, False, None, server, token) if play: paths.append(putils.direct_play(theme['MediaSources'][0]).encode('utf-8')) else: paths.append(putils.direct_url(theme['MediaSources'][0]).encode('utf-8')) tvtunes_nfo(nfo_file, paths) dialog("notification", heading="{emby}", message=_(33153), icon="{emby}", time=1000, sound=False)
def get_next_episodes(item_id, limit): ''' Only for synced content. ''' with Database('emby') as embydb: db = emby_db.EmbyDatabase(embydb.cursor) library = db.get_view_name(item_id) if not library: return result = JSONRPC('VideoLibrary.GetTVShows').execute({ 'sort': {'order': "descending", 'method': "lastplayed"}, 'filter': { 'and': [ {'operator': "true", 'field': "inprogress", 'value': ""}, {'operator': "is", 'field': "tag", 'value': "%s" % library} ]}, 'properties': ['title', 'studio', 'mpaa', 'file', 'art'] }) try: items = result['result']['tvshows'] except (KeyError, TypeError): return list_li = [] for item in items: if settings('ignoreSpecialsNextEpisodes.bool'): params = { 'tvshowid': item['tvshowid'], 'sort': {'method': "episode"}, 'filter': { 'and': [ {'operator': "lessthan", 'field': "playcount", 'value': "1"}, {'operator': "greaterthan", 'field': "season", 'value': "0"} ]}, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", "streamdetails", "firstaired", "runtime", "writer", "dateadded", "lastplayed" ], 'limits': {"end": 1} } else: params = { 'tvshowid': item['tvshowid'], 'sort': {'method': "episode"}, 'filter': {'operator': "lessthan", 'field': "playcount", 'value': "1"}, 'properties': [ "title", "playcount", "season", "episode", "showtitle", "plot", "file", "rating", "resume", "tvshowid", "art", "streamdetails", "firstaired", "runtime", "writer", "dateadded", "lastplayed" ], 'limits': {"end": 1} } result = JSONRPC('VideoLibrary.GetEpisodes').execute(params) try: episodes = result['result']['episodes'] except (KeyError, TypeError): pass else: for episode in episodes: li = create_listitem(episode) list_li.append((episode['file'], li)) if len(list_li) == limit: break xbmcplugin.addDirectoryItems(int(sys.argv[1]), list_li, len(list_li)) xbmcplugin.setContent(int(sys.argv[1]), 'episodes') xbmcplugin.endOfDirectory(int(sys.argv[1]))
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('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 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, embydb, 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, embydb, 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, embydb, 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): 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
def add_library(self, view): ''' Add entry to view table in emby database. ''' with Database('emby') as embydb: emby_db.EmbyDatabase(embydb.cursor).add_view( view['Id'], view['Name'], view['Media'])
def get_nodes(self): ''' Set up playlists, video nodes, window prop. ''' node_path = xbmc.translatePath( "special://profile/library/video").decode('utf-8') playlist_path = xbmc.translatePath( "special://profile/playlists/video").decode('utf-8') index = 0 with Database('emby') as embydb: db = emby_db.EmbyDatabase(embydb.cursor) for library in self.sync['Whitelist']: library = library.replace('Mixed:', "") view = db.get_view(library) if view: view = { 'Id': library, 'Name': view[0], 'Tag': view[0], 'Media': view[1] } if view['Media'] == 'mixed': for media in ('movies', 'tvshows'): temp_view = dict(view) temp_view['Media'] = media self.add_playlist(playlist_path, temp_view, True) self.add_nodes(node_path, temp_view, True) else: # Compensate for the duplicate. index += 1 else: if view['Media'] in ('movies', 'tvshows', 'musicvideos'): self.add_playlist(playlist_path, view) if view['Media'] not in ('music'): self.add_nodes(node_path, view) index += 1 for single in [{ 'Name': _('fav_movies'), 'Tag': "Favorite movies", 'Media': "movies" }, { 'Name': _('fav_tvshows'), 'Tag': "Favorite tvshows", 'Media': "tvshows" }, { 'Name': _('fav_episodes'), 'Tag': "Favorite episodes", 'Media': "episodes" }]: self.add_single_node(node_path, index, "favorites", single) index += 1 self.window_nodes()
def window_nodes(self): ''' Just read from the database and populate based on SortedViews Setup the window properties that reflect the emby server views and more. ''' self.window_clear() self.window_clear('Emby.wnodes') with Database('emby') as embydb: libraries = emby_db.EmbyDatabase(embydb.cursor).get_views() libraries = self.order_media_folders(libraries or []) index = 0 windex = 0 try: self.media_folders = self.get_libraries() except IndexError as error: LOG.error(error) for library in (libraries or []): view = { 'Id': library[0], 'Name': library[1], 'Tag': library[1], 'Media': library[2] } if library[0] in [ x.replace('Mixed:', "") for x in self.sync['Whitelist'] ]: # Synced libraries if view['Media'] in ('movies', 'tvshows', 'musicvideos', 'mixed'): if view['Media'] == 'mixed': for media in ('movies', 'tvshows'): for node in NODES[media]: temp_view = dict(view) temp_view['Media'] = media temp_view['Name'] = "%s (%s)" % (view['Name'], _(media)) self.window_node(index, temp_view, *node) self.window_wnode(windex, temp_view, *node) else: # Add one to compensate for the duplicate. index += 1 windex += 1 else: for node in NODES[view['Media']]: self.window_node(index, view, *node) if view['Media'] in ('movies', 'tvshows'): self.window_wnode(windex, view, *node) if view['Media'] in ('movies', 'tvshows'): windex += 1 elif view['Media'] == 'music': self.window_node(index, view, 'music') else: # Dynamic entry if view['Media'] in ('homevideos', 'books', 'audiobooks'): self.window_wnode(windex, view, 'browse') windex += 1 self.window_node(index, view, 'browse') index += 1 for single in [{ 'Name': _('fav_movies'), 'Tag': "Favorite movies", 'Media': "movies" }, { 'Name': _('fav_tvshows'), 'Tag': "Favorite tvshows", 'Media': "tvshows" }, { 'Name': _('fav_episodes'), 'Tag': "Favorite episodes", 'Media': "episodes" }]: self.window_single_node(index, "favorites", single) index += 1 window('Emby.nodes.total', str(index)) window('Emby.wnodes.total', str(windex))