diff --git a/resources/lib/database/emby_db.py b/resources/lib/database/emby_db.py index 101bf1bd..2f756800 100644 --- a/resources/lib/database/emby_db.py +++ b/resources/lib/database/emby_db.py @@ -140,6 +140,9 @@ class EmbyDatabase(): return self.cursor.fetchall() + def remove_media_by_parent_id(self, *args): + self.cursor.execute(QU.delete_media_by_parent_id, args) + diff --git a/resources/lib/database/queries.py b/resources/lib/database/queries.py index 24e7aab4..e2af7445 100644 --- a/resources/lib/database/queries.py +++ b/resources/lib/database/queries.py @@ -61,7 +61,7 @@ get_media_by_id = """ SELECT emby_type FROM emby WHERE emby_id = ? """ -get_media_by_parent_id = """ SELECT emby_id, emby_type +get_media_by_parent_id = """ SELECT emby_id, emby_type, kodi_id, kodi_fileid FROM emby WHERE emby_parent_id = ? """ @@ -165,3 +165,6 @@ delete_view = """ DELETE FROM view """ delete_parent_boxset_obj = [ None, "{Movie}" ] +delete_media_by_parent_id = """ DELETE FROM emby + WHERE emby_parent_id = ? + """ diff --git a/resources/lib/downloader.py b/resources/lib/downloader.py index 59d8fb56..b9776c3b 100644 --- a/resources/lib/downloader.py +++ b/resources/lib/downloader.py @@ -122,7 +122,31 @@ def get_movies_by_boxset(boxset_id): def get_episode_by_show(show_id): - for items in get_items(show_id, "Episode"): + query = { + 'url': "Shows/%s/Episodes" % show_id, + 'params': { + 'EnableUserData': True, + 'EnableImages': True, + 'UserId': "{UserId}", + 'Fields': api.info() + } + } + for items in _get_items(query): + yield items + +def get_episode_by_season(show_id, season_id): + + query = { + 'url': "Shows/%s/Episodes" % show_id, + 'params': { + 'SeasonId': season_id, + 'EnableUserData': True, + 'EnableImages': True, + 'UserId': "{UserId}", + 'Fields': api.info() + } + } + for items in _get_items(query): yield items def get_items(parent_id, item_type=None, basic=False, params=None): @@ -134,7 +158,13 @@ def get_items(parent_id, item_type=None, basic=False, params=None): 'IncludeItemTypes': item_type, 'SortBy': "SortName", 'SortOrder': "Ascending", - 'Fields': api.basic_info() if basic else api.info() + 'Fields': api.basic_info() if basic else api.info(), + 'CollapseBoxSetItems': False, + 'IsVirtualUnaired': False, + 'EnableTotalRecordCount': False, + 'LocationTypes': "FileSystem,Remote,Offline", + 'IsMissing': False, + 'Recursive': True } } if params: @@ -152,7 +182,13 @@ def get_artists(parent_id=None, basic=False, params=None, server_id=None): 'ParentId': parent_id, 'SortBy': "SortName", 'SortOrder': "Ascending", - 'Fields': api.basic_info() if basic else api.music_info() + 'Fields': api.basic_info() if basic else api.music_info(), + 'CollapseBoxSetItems': False, + 'IsVirtualUnaired': False, + 'EnableTotalRecordCount': False, + 'LocationTypes': "FileSystem,Remote,Offline", + 'IsMissing': False, + 'Recursive': True } } @@ -187,14 +223,6 @@ def _get_items(query, server_id=None): url = query['url'] params = query.get('params', {}) - params.update({ - 'CollapseBoxSetItems': False, - 'IsVirtualUnaired': False, - 'EnableTotalRecordCount': False, - 'LocationTypes': "FileSystem,Remote,Offline", - 'IsMissing': False, - 'Recursive': True - }) try: test_params = dict(params) diff --git a/resources/lib/full_sync.py b/resources/lib/full_sync.py index fc07cc48..64214db2 100644 --- a/resources/lib/full_sync.py +++ b/resources/lib/full_sync.py @@ -104,8 +104,9 @@ class FullSync(object): ''' Select all or whitelist libraries. Provides a new list. ''' - if not dialog("yesno", heading="{emby}", line1=_(33125), nolabel=_(33126), yeslabel=_(33127)): + if dialog("yesno", heading="{emby}", line1=_(33125), nolabel=_(33127), yeslabel=_(33126)): LOG.info("Selected sync later.") + raise LibraryException('SyncLibraryLater') choices = [x['Name'] for x in libraries] @@ -116,6 +117,7 @@ class FullSync(object): raise LibraryException('LibrarySelection') elif not selection: LOG.info("Nothing was selected.") + raise LibraryException('SyncLibraryLater') if 0 in selection: @@ -140,6 +142,7 @@ class FullSync(object): ''' Main sync process. ''' LOG.info("starting sync with %s", self.sync['Libraries']) + save_sync(self.sync) start_time = datetime.datetime.now() for library in list(self.sync['Libraries']): @@ -254,7 +257,7 @@ class FullSync(object): if obj.tvshow(show, library=library) != False: - for episodes in server.get_items(show['Id'], "Episode"): + for episodes in server.get_episode_by_show(show['Id']): for episode in episodes['Items']: dialog.update(percent, message="%s/%s" % (message, episode['Name'][:10])) diff --git a/resources/lib/helper/wrapper.py b/resources/lib/helper/wrapper.py index 1cab2bc5..5859cea5 100644 --- a/resources/lib/helper/wrapper.py +++ b/resources/lib/helper/wrapper.py @@ -105,9 +105,8 @@ def library_check(): def wrapper(self, item, *args, **kwargs): from database import get_sync - sync = get_sync() - if kwargs.get('library') is None: + sync = get_sync() if 'e_item' in kwargs: try: @@ -131,7 +130,7 @@ def library_check(): break - if view['Id'] not in sync['Whitelist']: + if view['Id'] not in [x.replace('Mixed:', "") for x in sync['Whitelist'] + sync['Libraries']]: LOG.info("Library %s is not synced. Skip update.", view['Id']) return diff --git a/resources/lib/helper/xmls.py b/resources/lib/helper/xmls.py index 18d4367c..a1e98a7b 100644 --- a/resources/lib/helper/xmls.py +++ b/resources/lib/helper/xmls.py @@ -54,7 +54,7 @@ def sources(): try: files = xml.find('files') - if not files: + if files is None: files = etree.SubElement(xml, 'files') for source in xml.findall('.//path'): diff --git a/resources/lib/objects/actions.py b/resources/lib/objects/actions.py index 732c92ff..59f1480f 100644 --- a/resources/lib/objects/actions.py +++ b/resources/lib/objects/actions.py @@ -230,6 +230,12 @@ class Actions(object): obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork')) self.listitem_photo(obj, listitem, item) + elif item['Type'] in ('TvChannel'): + + obj = objects.map(item, 'BrowseChannel') + obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork')) + self.listitem_channel(obj, listitem, item) + else: obj = objects.map(item, 'BrowseVideo') obj['DbId'] = db_id @@ -428,6 +434,45 @@ class Actions(object): listitem.setInfo('video', metadata) listitem.setContentLookup(False) + def listitem_channel(self, obj, listitem, item): + + ''' Set listitem for channel content. + ''' + API = api.API(item, self.server) + + obj['Title'] = "%s - %s" % (obj['Title'], obj['ProgramName']) + obj['Runtime'] = round(float((obj['Runtime'] or 0) / 10000000.0), 6) + obj['PlayCount'] = API.get_playcount(obj['Played'], obj['PlayCount']) or 0 + obj['Overlay'] = 7 if obj['Played'] else 6 + obj['Artwork']['Primary'] = obj['Artwork']['Primary'] or "special://home/addons/plugin.video.emby/icon.png" + obj['Artwork']['Thumb'] = obj['Artwork']['Thumb'] or "special://home/addons/plugin.video.emby/fanart.jpg" + obj['Artwork']['Backdrop'] = obj['Artwork']['Backdrop'] or ["special://home/addons/plugin.video.emby/fanart.jpg"] + + + metadata = { + 'title': obj['Title'], + 'originaltitle': obj['Title'], + 'playcount': obj['PlayCount'], + 'overlay': obj['Overlay'] + } + listitem.setIconImage(obj['Artwork']['Thumb']) + listitem.setThumbnailImage(obj['Artwork']['Primary']) + self.set_artwork(obj['Artwork'], listitem, obj['Type']) + + if obj['Artwork']['Primary']: + listitem.setThumbnailImage(obj['Artwork']['Primary']) + + if not obj['Artwork']['Backdrop']: + listitem.setArt({'fanart': obj['Artwork']['Primary']}) + + listitem.setProperty('totaltime', str(obj['Runtime'])) + listitem.setProperty('IsPlayable', 'true') + listitem.setProperty('IsFolder', 'false') + + listitem.setLabel(obj['Title']) + listitem.setInfo('video', metadata) + listitem.setContentLookup(False) + def listitem_music(self, obj, listitem, item): API = api.API(item, self.server) diff --git a/resources/lib/objects/obj_map.json b/resources/lib/objects/obj_map.json index 02fec2e0..d98dc20c 100644 --- a/resources/lib/objects/obj_map.json +++ b/resources/lib/objects/obj_map.json @@ -117,7 +117,7 @@ "Video": "MediaSources/0/MediaStreams:?Type=Video", "Container": "MediaSources/0/Container", "Location": "LocationType", - "EmbyParentId": "ParentId" + "EmbyParentId": "SeriesId,ParentId" }, "EpisodeUserData": { "Id": "Id", @@ -333,5 +333,15 @@ "CameraModel": "CameraModel", "ExposureTime": "ExposureTime", "FocalLength": "FocalLength" + }, + "BrowseChannel": { + "Id": "Id", + "Title": "Name", + "Type": "Type", + "ProgramName": "CurrentProgram/Name", + "Played": "CurrentProgram/UserData/Played", + "PlayCount": "CurrentProgram/UserData/PlayCount", + "Runtime": "CurrentProgram/RunTimeTicks", + "MediaType": "MediaType" } } \ No newline at end of file diff --git a/resources/lib/objects/tvshows.py b/resources/lib/objects/tvshows.py index 79ae1291..9a2a8b9c 100644 --- a/resources/lib/objects/tvshows.py +++ b/resources/lib/objects/tvshows.py @@ -127,7 +127,7 @@ class TVShows(KodiDb): self.add_studios(*values(obj, QU.add_studios_tvshow_obj)) self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow") - season_episodes = [] + season_episodes = {} for season in self.server['api'].get_seasons(obj['Id'])['Items']: @@ -140,19 +140,18 @@ class TVShows(KodiDb): self.emby_db.add_reference(*values(obj, QUEM.add_reference_pool_obj)) LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId']) - + season_episodes[season['Id']] = season['SeriesId'] + try: self.emby_db.get_item_by_id(season['Id'])[0] except TypeError: - self.season(season, obj['ShowId']) - season_episodes.append(season['Id']) else: season_id = self.get_season(*values(obj, QU.get_season_special_obj)) self.artwork.add(obj['Artwork'], season_id, "season") for season in season_episodes: - for episodes in server.get_items(season, "Episode"): + for episodes in server.get_episode_by_season(season_episodes[season], season): for episode in episodes['Items']: self.episode(episode) @@ -562,6 +561,12 @@ class TVShows(KodiDb): self.remove_show(obj['ParentId'], obj['Id']) self.emby_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj)) + # Remove any series pooling episodes + for episode in self.emby_db.get_media_by_parent_id(obj['Id']): + self.remove_episode(episode[2], episode[3], obj['Id']) + else: + self.emby_db.remove_media_by_parent_id(obj['Id']) + self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj)) def remove_tvshow(self, kodi_id, item_id):