diff --git a/resources/lib/database.py b/resources/lib/database.py index b833b313..918d5caf 100644 --- a/resources/lib/database.py +++ b/resources/lib/database.py @@ -149,9 +149,15 @@ def verify_emby_database(cursor): checksum INTEGER)""") cursor.execute( """CREATE TABLE IF NOT EXISTS view( - view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER)""") + view_id TEXT UNIQUE, view_name TEXT, media_type TEXT, kodi_tagid INTEGER, group_series TEXT)""") cursor.execute("CREATE TABLE IF NOT EXISTS version(idVersion TEXT)") + columns = cursor.execute("SELECT * FROM view") + if 'group_series' not in [description[0] for description in columns.description]: + log.info("Add missing column group_series") + cursor.execute("ALTER TABLE view ADD COLUMN group_series 'TEXT'") + + def db_reset(): dialog = xbmcgui.Dialog() diff --git a/resources/lib/embydb_functions.py b/resources/lib/embydb_functions.py index 5ad53dee..63373038 100644 --- a/resources/lib/embydb_functions.py +++ b/resources/lib/embydb_functions.py @@ -144,17 +144,30 @@ class Embydb_Functions(): return view - def addView(self, embyid, name, mediatype, tagid): + def addView(self, embyid, name, mediatype, tagid, group_series): query = ( ''' INSERT INTO view( - view_id, view_name, media_type, kodi_tagid) + view_id, view_name, media_type, kodi_tagid, group_series) - VALUES (?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?) ''' ) - self.embycursor.execute(query, (embyid, name, mediatype, tagid)) + self.embycursor.execute(query, (embyid, name, mediatype, tagid, group_series)) + + def get_view_grouped_series(self, view_id): + + query = ' '.join(( + + "SELECT group_series", + "FROM view", + "WHERE view_id = ?" + )) + try: + self.embycursor.execute(query, (view_id,)) + return self.embycursor.fetchone() + except: return False def updateView(self, name, tagid, mediafolderid): diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py index 57878de7..5166e6a3 100644 --- a/resources/lib/librarysync.py +++ b/resources/lib/librarysync.py @@ -458,6 +458,8 @@ class LibrarySync(threading.Thread): message="%s %s..." % (lang(33020), view['name'])) all_tvshows = self.emby.getShows(view['id'], dialog=pdialog) + #log.info([item['Id'] for item in all_tvshows['Items']]) + #for all_tvshows in self.emby.get_parent_child(view['id'], "Series"): tvshows.add_all("Series", all_tvshows, view) else: diff --git a/resources/lib/objects/_kodi_tvshows.py b/resources/lib/objects/_kodi_tvshows.py index 991c7a0b..59a1e63b 100644 --- a/resources/lib/objects/_kodi_tvshows.py +++ b/resources/lib/objects/_kodi_tvshows.py @@ -119,9 +119,7 @@ class KodiTVShows(KodiItems): def add_uniqueid(self, *args): query = ( ''' - INSERT INTO uniqueid( - uniqueid_id, media_id, media_type, value, type) - + INSERT INTO uniqueid(uniqueid_id, media_id, media_type, value, type) VALUES (?, ?, ?, ?, ?) ''' ) diff --git a/resources/lib/objects/tvshows.py b/resources/lib/objects/tvshows.py index 57fd78d6..826bf806 100644 --- a/resources/lib/objects/tvshows.py +++ b/resources/lib/objects/tvshows.py @@ -245,25 +245,6 @@ class TVShows(Items): force_episodes = False itemid = item['Id'] emby_dbitem = emby_db.getItem_byId(itemid) - try: - showid = emby_dbitem[0] - pathid = emby_dbitem[2] - log.info("showid: %s pathid: %s", showid, pathid) - - except TypeError: - update_item = False - log.debug("showid: %s not found", itemid) - showid = self.kodi_db.create_entry() - - else: - # Verification the item is still in Kodi - if self.kodi_db.get_tvshow(showid) is None: - # item is not found, let's recreate it. - update_item = False - log.info("showid: %s missing from Kodi, repairing the entry", showid) - # Force re-add episodes after the show is re-created. - force_episodes = True - if view is None: # Get view tag from emby @@ -292,28 +273,6 @@ class TVShows(Items): studios = API.get_studios() studio = " / ".join(studios) - # Verify series pooling - if not update_item and tvdb: - query = "SELECT idShow FROM tvshow WHERE C12 = ?" - kodicursor.execute(query, (tvdb,)) - try: - temp_showid = kodicursor.fetchone()[0] - except TypeError: - pass - else: - emby_other = emby_db.getItem_byKodiId(temp_showid, "tvshow") - if emby_other and viewid == emby_other[2]: - log.info("Applying series pooling for %s", title) - emby_other_item = emby_db.getItem_byId(emby_other[0]) - showid = emby_other_item[0] - pathid = emby_other_item[2] - log.info("showid: %s pathid: %s", showid, pathid) - # Create the reference in emby table - emby_db.addReference(itemid, showid, "Series", "tvshow", pathid=pathid, - checksum=checksum, mediafolderid=viewid) - update_item = True - - ##### GET THE FILE AND PATH ##### playurl = API.get_file_path() @@ -338,6 +297,74 @@ class TVShows(Items): path = "%s%s/" % (toplevelpath, itemid) + try: + showid = emby_dbitem[0] + pathid = emby_dbitem[2] + log.info("showid: %s pathid: %s", showid, pathid) + + except TypeError: + update_item = False + showid = None + log.debug("showid: %s not found", itemid) + + if self.emby_db.get_view_grouped_series(viewid) and imdb: + # search kodi db for same provider id + if self.kodi_version > 16: + query = "SELECT idShow FROM tvshow_view WHERE uniqueid_value = ?" + kodicursor.execute(query, (imdb,)) + else: + query = "SELECT idShow FROM tvshow WHERE C12 = ?" + kodicursor.execute(query, (tvdb,)) + + try: + temps_showid = kodicursor.fetchall() + except TypeError: pass + else: + for temp_showid in temps_showid: + emby_other = emby_db.getItem_byKodiId(temp_showid[0], "tvshow") + if emby_other and viewid == emby_other[2]: + log.info("Applying series pooling for: %s %s", itemid, title) + emby_other_item = emby_db.getItem_byId(emby_other[0]) + showid = emby_other_item[0] + pathid = self.kodi_db.add_path(path) + emby_db.addReference(itemid, showid, "Series", "tvshow", pathid=pathid, + checksum=checksum, mediafolderid=viewid) + return + + showid = self.kodi_db.create_entry() + + else: + # Verification the item is still in Kodi + if self.kodi_db.get_tvshow(showid) is None: + # item is not found, let's recreate it. + update_item = False + log.info("showid: %s missing from Kodi, repairing the entry", showid) + # Force re-add episodes after the show is re-created. + force_episodes = True + + + # Verify series pooling + """if not update_item and tvdb: + query = "SELECT idShow FROM tvshow WHERE C12 = ?" + kodicursor.execute(query, (tvdb,)) + try: + temp_showid = kodicursor.fetchone()[0] + except TypeError: + pass + else: + emby_other = emby_db.getItem_byKodiId(temp_showid, "tvshow") + if emby_other and viewid == emby_other[2]: + log.info("Applying series pooling for %s", title) + emby_other_item = emby_db.getItem_byId(emby_other[0]) + showid = emby_other_item[0] + pathid = emby_other_item[2] + log.info("showid: %s pathid: %s", showid, pathid) + # Create the reference in emby table + emby_db.addReference(itemid, showid, "Series", "tvshow", pathid=pathid, + checksum=checksum, mediafolderid=viewid) + update_item = True""" + + ##### UPDATE THE TVSHOW ##### if update_item: log.info("UPDATE tvshow itemid: %s - Title: %s", itemid, title) @@ -390,7 +417,7 @@ class TVShows(Items): # Create the tvshow entry if self.kodi_version > 16: self.kodi_db.add_tvshow(showid, title, plot, uniqueid, premieredate, genre, - title, uniqueid, mpaa, studio, sorttitle) + title, uniqueid, mpaa, studio, sorttitle) else: self.kodi_db.add_tvshow(showid, title, plot, rating, premieredate, genre, title, tvdb, mpaa, studio, sorttitle) @@ -424,6 +451,7 @@ class TVShows(Items): # Process seasons all_seasons = emby.getSeasons(itemid) for season in all_seasons['Items']: + log.info("found season: %s", season) self.add_updateSeason(season, showid=showid) else: # Finally, refresh the all season entry @@ -468,6 +496,7 @@ class TVShows(Items): # Process artwork artwork.add_artwork(artwork.get_all_artwork(item), seasonid, "season", kodicursor) + log.info("Processed seasonid: %s index: %s", item['Id'], seasonnum) return True @catch_except() @@ -886,3 +915,9 @@ class TVShows(Items): self.artwork.delete_artwork(kodiid, "episode", kodicursor) self.kodi_db.remove_episode(kodiid, fileid) log.debug("Removed episode: %s", kodiid) + + def add_tvshow(self, item, view): + # The only way to keep things together is to drill down, like in the webclient. + # If series pooling is true, they will share the showid, extra tvshow entries + # will be added to emby.db due to server events. + pass diff --git a/resources/lib/playbackutils.py b/resources/lib/playbackutils.py index fd927fce..aad56aa4 100644 --- a/resources/lib/playbackutils.py +++ b/resources/lib/playbackutils.py @@ -270,7 +270,7 @@ class PlaybackUtils(): if "Language" in stream: - filename = "Stream.%s.srt" % stream['Language'] + filename = "Stream.%s.%s" % (stream['Language'], stream['Codec']) try: path = self._download_external_subs(url, temp, filename) externalsubs.append(path) diff --git a/resources/lib/read_embyserver.py b/resources/lib/read_embyserver.py index f030311b..22084676 100644 --- a/resources/lib/read_embyserver.py +++ b/resources/lib/read_embyserver.py @@ -600,4 +600,50 @@ class Read_EmbyServer(): 'IncludeItemTypes': media_type } url = self.get_emby_url('Users/{UserId}/Items?format=json') - return self.doUtils.downloadUrl(url, parameters=params) \ No newline at end of file + return self.doUtils.downloadUrl(url, parameters=params) + + # NEW CODE ---------------------------------------------------- + + @classmethod + def _get_full_details(cls, params): + params.update({ + 'Fields': ( + + "Path,Genres,SortName,Studios,Writer,ProductionYear,Taglines," + "CommunityRating,OfficialRating,CumulativeRunTimeTicks," + "Metascore,AirTime,DateCreated,MediaStreams,People,Overview," + "CriticRating,CriticRatingSummary,Etag,ShortOverview,ProductionLocations," + "Tags,ProviderIds,ParentId,RemoteTrailers,SpecialEpisodeNumbers," + "MediaSources,VoteCount" + ) + }) + return params + + def get_parent_child(self, parent_id, media_format=None): + + url = self.get_emby_url('Users/{UserId}/Items') + params = { + 'SortBy': "SortName", + 'SortOrder': "Ascending", + 'IncludeItemTypes': media_format, + 'Recursive': True, + 'Limit': 1, + 'ParentId': parent_id + } + result = self.doUtils.downloadUrl(url, parameters=params) + params['Limit'] = self.limitIndex + params = self._get_full_details(params) + + index = 0 + while index < result['TotalRecordCount']: + params['StartIndex'] = index + yield self.doUtils.downloadUrl(url, parameters=params) + + index += self.limitIndex + + def get_view_options(self, view_id): + + url = self.get_emby_url('Library/VirtualFolders') + for library in self.doUtils.downloadUrl(url): + if library['ItemId'] == view_id: + return library['LibraryOptions'] diff --git a/resources/lib/views.py b/resources/lib/views.py index f807eb69..6e8b0e3d 100644 --- a/resources/lib/views.py +++ b/resources/lib/views.py @@ -147,7 +147,8 @@ class Views(object): self.add_playlist_node(media_type, view_id, view_name, view_type) # Add view to emby database - self.emby_db.addView(view_id, view_name, view_type, tag_id) + group_series = self.emby.get_view_options(view_id)['EnableAutomaticSeriesGrouping'] if view_type == "tvshows" else None + self.emby_db.addView(view_id, view_name, view_type, tag_id, group_series) def compare_view(self, media_type, view_id, view_name, view_type):