mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-24 17:56:11 +00:00
Support series pooling
Still requires a manual sync to apply...
This commit is contained in:
parent
7767f515b9
commit
8d00a9ade2
8 changed files with 154 additions and 53 deletions
|
@ -149,9 +149,15 @@ def verify_emby_database(cursor):
|
||||||
checksum INTEGER)""")
|
checksum INTEGER)""")
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"""CREATE TABLE IF NOT EXISTS view(
|
"""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)")
|
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():
|
def db_reset():
|
||||||
|
|
||||||
dialog = xbmcgui.Dialog()
|
dialog = xbmcgui.Dialog()
|
||||||
|
|
|
@ -144,17 +144,30 @@ class Embydb_Functions():
|
||||||
|
|
||||||
return view
|
return view
|
||||||
|
|
||||||
def addView(self, embyid, name, mediatype, tagid):
|
def addView(self, embyid, name, mediatype, tagid, group_series):
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO view(
|
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):
|
def updateView(self, name, tagid, mediafolderid):
|
||||||
|
|
||||||
|
|
|
@ -458,6 +458,8 @@ class LibrarySync(threading.Thread):
|
||||||
message="%s %s..." % (lang(33020), view['name']))
|
message="%s %s..." % (lang(33020), view['name']))
|
||||||
|
|
||||||
all_tvshows = self.emby.getShows(view['id'], dialog=pdialog)
|
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)
|
tvshows.add_all("Series", all_tvshows, view)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -119,9 +119,7 @@ class KodiTVShows(KodiItems):
|
||||||
def add_uniqueid(self, *args):
|
def add_uniqueid(self, *args):
|
||||||
query = (
|
query = (
|
||||||
'''
|
'''
|
||||||
INSERT INTO uniqueid(
|
INSERT INTO uniqueid(uniqueid_id, media_id, media_type, value, type)
|
||||||
uniqueid_id, media_id, media_type, value, type)
|
|
||||||
|
|
||||||
VALUES (?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?)
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
|
@ -245,25 +245,6 @@ class TVShows(Items):
|
||||||
force_episodes = False
|
force_episodes = False
|
||||||
itemid = item['Id']
|
itemid = item['Id']
|
||||||
emby_dbitem = emby_db.getItem_byId(itemid)
|
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:
|
if view is None:
|
||||||
# Get view tag from emby
|
# Get view tag from emby
|
||||||
|
@ -292,28 +273,6 @@ class TVShows(Items):
|
||||||
studios = API.get_studios()
|
studios = API.get_studios()
|
||||||
studio = " / ".join(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 #####
|
##### GET THE FILE AND PATH #####
|
||||||
playurl = API.get_file_path()
|
playurl = API.get_file_path()
|
||||||
|
|
||||||
|
@ -338,6 +297,74 @@ class TVShows(Items):
|
||||||
path = "%s%s/" % (toplevelpath, itemid)
|
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 #####
|
##### UPDATE THE TVSHOW #####
|
||||||
if update_item:
|
if update_item:
|
||||||
log.info("UPDATE tvshow itemid: %s - Title: %s", itemid, title)
|
log.info("UPDATE tvshow itemid: %s - Title: %s", itemid, title)
|
||||||
|
@ -390,7 +417,7 @@ class TVShows(Items):
|
||||||
# Create the tvshow entry
|
# Create the tvshow entry
|
||||||
if self.kodi_version > 16:
|
if self.kodi_version > 16:
|
||||||
self.kodi_db.add_tvshow(showid, title, plot, uniqueid, premieredate, genre,
|
self.kodi_db.add_tvshow(showid, title, plot, uniqueid, premieredate, genre,
|
||||||
title, uniqueid, mpaa, studio, sorttitle)
|
title, uniqueid, mpaa, studio, sorttitle)
|
||||||
else:
|
else:
|
||||||
self.kodi_db.add_tvshow(showid, title, plot, rating, premieredate, genre,
|
self.kodi_db.add_tvshow(showid, title, plot, rating, premieredate, genre,
|
||||||
title, tvdb, mpaa, studio, sorttitle)
|
title, tvdb, mpaa, studio, sorttitle)
|
||||||
|
@ -424,6 +451,7 @@ class TVShows(Items):
|
||||||
# Process seasons
|
# Process seasons
|
||||||
all_seasons = emby.getSeasons(itemid)
|
all_seasons = emby.getSeasons(itemid)
|
||||||
for season in all_seasons['Items']:
|
for season in all_seasons['Items']:
|
||||||
|
log.info("found season: %s", season)
|
||||||
self.add_updateSeason(season, showid=showid)
|
self.add_updateSeason(season, showid=showid)
|
||||||
else:
|
else:
|
||||||
# Finally, refresh the all season entry
|
# Finally, refresh the all season entry
|
||||||
|
@ -468,6 +496,7 @@ class TVShows(Items):
|
||||||
# Process artwork
|
# Process artwork
|
||||||
artwork.add_artwork(artwork.get_all_artwork(item), seasonid, "season", kodicursor)
|
artwork.add_artwork(artwork.get_all_artwork(item), seasonid, "season", kodicursor)
|
||||||
|
|
||||||
|
log.info("Processed seasonid: %s index: %s", item['Id'], seasonnum)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@catch_except()
|
@catch_except()
|
||||||
|
@ -886,3 +915,9 @@ class TVShows(Items):
|
||||||
self.artwork.delete_artwork(kodiid, "episode", kodicursor)
|
self.artwork.delete_artwork(kodiid, "episode", kodicursor)
|
||||||
self.kodi_db.remove_episode(kodiid, fileid)
|
self.kodi_db.remove_episode(kodiid, fileid)
|
||||||
log.debug("Removed episode: %s", kodiid)
|
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
|
||||||
|
|
|
@ -270,7 +270,7 @@ class PlaybackUtils():
|
||||||
|
|
||||||
if "Language" in stream:
|
if "Language" in stream:
|
||||||
|
|
||||||
filename = "Stream.%s.srt" % stream['Language']
|
filename = "Stream.%s.%s" % (stream['Language'], stream['Codec'])
|
||||||
try:
|
try:
|
||||||
path = self._download_external_subs(url, temp, filename)
|
path = self._download_external_subs(url, temp, filename)
|
||||||
externalsubs.append(path)
|
externalsubs.append(path)
|
||||||
|
|
|
@ -600,4 +600,50 @@ class Read_EmbyServer():
|
||||||
'IncludeItemTypes': media_type
|
'IncludeItemTypes': media_type
|
||||||
}
|
}
|
||||||
url = self.get_emby_url('Users/{UserId}/Items?format=json')
|
url = self.get_emby_url('Users/{UserId}/Items?format=json')
|
||||||
return self.doUtils.downloadUrl(url, parameters=params)
|
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']
|
||||||
|
|
|
@ -147,7 +147,8 @@ class Views(object):
|
||||||
|
|
||||||
self.add_playlist_node(media_type, view_id, view_name, view_type)
|
self.add_playlist_node(media_type, view_id, view_name, view_type)
|
||||||
# Add view to emby database
|
# 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):
|
def compare_view(self, media_type, view_id, view_name, view_type):
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue