mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 02:06:09 +00:00
Fix episodes for series pooling
This commit is contained in:
parent
8915773706
commit
d54aad726e
9 changed files with 120 additions and 24 deletions
|
@ -140,6 +140,9 @@ class EmbyDatabase():
|
||||||
|
|
||||||
return self.cursor.fetchall()
|
return self.cursor.fetchall()
|
||||||
|
|
||||||
|
def remove_media_by_parent_id(self, *args):
|
||||||
|
self.cursor.execute(QU.delete_media_by_parent_id, args)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ get_media_by_id = """ SELECT emby_type
|
||||||
FROM emby
|
FROM emby
|
||||||
WHERE emby_id = ?
|
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
|
FROM emby
|
||||||
WHERE emby_parent_id = ?
|
WHERE emby_parent_id = ?
|
||||||
"""
|
"""
|
||||||
|
@ -165,3 +165,6 @@ delete_view = """ DELETE FROM view
|
||||||
"""
|
"""
|
||||||
delete_parent_boxset_obj = [ None, "{Movie}"
|
delete_parent_boxset_obj = [ None, "{Movie}"
|
||||||
]
|
]
|
||||||
|
delete_media_by_parent_id = """ DELETE FROM emby
|
||||||
|
WHERE emby_parent_id = ?
|
||||||
|
"""
|
||||||
|
|
|
@ -122,7 +122,31 @@ def get_movies_by_boxset(boxset_id):
|
||||||
|
|
||||||
def get_episode_by_show(show_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
|
yield items
|
||||||
|
|
||||||
def get_items(parent_id, item_type=None, basic=False, params=None):
|
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,
|
'IncludeItemTypes': item_type,
|
||||||
'SortBy': "SortName",
|
'SortBy': "SortName",
|
||||||
'SortOrder': "Ascending",
|
'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:
|
if params:
|
||||||
|
@ -152,7 +182,13 @@ def get_artists(parent_id=None, basic=False, params=None, server_id=None):
|
||||||
'ParentId': parent_id,
|
'ParentId': parent_id,
|
||||||
'SortBy': "SortName",
|
'SortBy': "SortName",
|
||||||
'SortOrder': "Ascending",
|
'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']
|
url = query['url']
|
||||||
params = query.get('params', {})
|
params = query.get('params', {})
|
||||||
params.update({
|
|
||||||
'CollapseBoxSetItems': False,
|
|
||||||
'IsVirtualUnaired': False,
|
|
||||||
'EnableTotalRecordCount': False,
|
|
||||||
'LocationTypes': "FileSystem,Remote,Offline",
|
|
||||||
'IsMissing': False,
|
|
||||||
'Recursive': True
|
|
||||||
})
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
test_params = dict(params)
|
test_params = dict(params)
|
||||||
|
|
|
@ -104,8 +104,9 @@ class FullSync(object):
|
||||||
|
|
||||||
''' Select all or whitelist libraries. Provides a new list.
|
''' 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.")
|
LOG.info("Selected sync later.")
|
||||||
|
|
||||||
raise LibraryException('SyncLibraryLater')
|
raise LibraryException('SyncLibraryLater')
|
||||||
|
|
||||||
choices = [x['Name'] for x in libraries]
|
choices = [x['Name'] for x in libraries]
|
||||||
|
@ -116,6 +117,7 @@ class FullSync(object):
|
||||||
raise LibraryException('LibrarySelection')
|
raise LibraryException('LibrarySelection')
|
||||||
elif not selection:
|
elif not selection:
|
||||||
LOG.info("Nothing was selected.")
|
LOG.info("Nothing was selected.")
|
||||||
|
|
||||||
raise LibraryException('SyncLibraryLater')
|
raise LibraryException('SyncLibraryLater')
|
||||||
|
|
||||||
if 0 in selection:
|
if 0 in selection:
|
||||||
|
@ -140,6 +142,7 @@ class FullSync(object):
|
||||||
''' Main sync process.
|
''' Main sync process.
|
||||||
'''
|
'''
|
||||||
LOG.info("starting sync with %s", self.sync['Libraries'])
|
LOG.info("starting sync with %s", self.sync['Libraries'])
|
||||||
|
save_sync(self.sync)
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
||||||
for library in list(self.sync['Libraries']):
|
for library in list(self.sync['Libraries']):
|
||||||
|
@ -254,7 +257,7 @@ class FullSync(object):
|
||||||
|
|
||||||
if obj.tvshow(show, library=library) != False:
|
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']:
|
for episode in episodes['Items']:
|
||||||
|
|
||||||
dialog.update(percent, message="%s/%s" % (message, episode['Name'][:10]))
|
dialog.update(percent, message="%s/%s" % (message, episode['Name'][:10]))
|
||||||
|
|
|
@ -105,9 +105,8 @@ def library_check():
|
||||||
def wrapper(self, item, *args, **kwargs):
|
def wrapper(self, item, *args, **kwargs):
|
||||||
from database import get_sync
|
from database import get_sync
|
||||||
|
|
||||||
sync = get_sync()
|
|
||||||
|
|
||||||
if kwargs.get('library') is None:
|
if kwargs.get('library') is None:
|
||||||
|
sync = get_sync()
|
||||||
|
|
||||||
if 'e_item' in kwargs:
|
if 'e_item' in kwargs:
|
||||||
try:
|
try:
|
||||||
|
@ -131,7 +130,7 @@ def library_check():
|
||||||
|
|
||||||
break
|
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'])
|
LOG.info("Library %s is not synced. Skip update.", view['Id'])
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
|
@ -54,7 +54,7 @@ def sources():
|
||||||
try:
|
try:
|
||||||
files = xml.find('files')
|
files = xml.find('files')
|
||||||
|
|
||||||
if not files:
|
if files is None:
|
||||||
files = etree.SubElement(xml, 'files')
|
files = etree.SubElement(xml, 'files')
|
||||||
|
|
||||||
for source in xml.findall('.//path'):
|
for source in xml.findall('.//path'):
|
||||||
|
|
|
@ -230,6 +230,12 @@ class Actions(object):
|
||||||
obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
|
obj['Artwork'] = API.get_all_artwork(objects.map(item, 'Artwork'))
|
||||||
self.listitem_photo(obj, listitem, item)
|
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:
|
else:
|
||||||
obj = objects.map(item, 'BrowseVideo')
|
obj = objects.map(item, 'BrowseVideo')
|
||||||
obj['DbId'] = db_id
|
obj['DbId'] = db_id
|
||||||
|
@ -428,6 +434,45 @@ class Actions(object):
|
||||||
listitem.setInfo('video', metadata)
|
listitem.setInfo('video', metadata)
|
||||||
listitem.setContentLookup(False)
|
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):
|
def listitem_music(self, obj, listitem, item):
|
||||||
API = api.API(item, self.server)
|
API = api.API(item, self.server)
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@
|
||||||
"Video": "MediaSources/0/MediaStreams:?Type=Video",
|
"Video": "MediaSources/0/MediaStreams:?Type=Video",
|
||||||
"Container": "MediaSources/0/Container",
|
"Container": "MediaSources/0/Container",
|
||||||
"Location": "LocationType",
|
"Location": "LocationType",
|
||||||
"EmbyParentId": "ParentId"
|
"EmbyParentId": "SeriesId,ParentId"
|
||||||
},
|
},
|
||||||
"EpisodeUserData": {
|
"EpisodeUserData": {
|
||||||
"Id": "Id",
|
"Id": "Id",
|
||||||
|
@ -333,5 +333,15 @@
|
||||||
"CameraModel": "CameraModel",
|
"CameraModel": "CameraModel",
|
||||||
"ExposureTime": "ExposureTime",
|
"ExposureTime": "ExposureTime",
|
||||||
"FocalLength": "FocalLength"
|
"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"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -127,7 +127,7 @@ class TVShows(KodiDb):
|
||||||
self.add_studios(*values(obj, QU.add_studios_tvshow_obj))
|
self.add_studios(*values(obj, QU.add_studios_tvshow_obj))
|
||||||
self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow")
|
self.artwork.add(obj['Artwork'], obj['ShowId'], "tvshow")
|
||||||
|
|
||||||
season_episodes = []
|
season_episodes = {}
|
||||||
|
|
||||||
for season in self.server['api'].get_seasons(obj['Id'])['Items']:
|
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))
|
self.emby_db.add_reference(*values(obj, QUEM.add_reference_pool_obj))
|
||||||
LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId'])
|
LOG.info("POOL %s [%s/%s]", obj['Title'], obj['Id'], obj['SeriesId'])
|
||||||
|
season_episodes[season['Id']] = season['SeriesId']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.emby_db.get_item_by_id(season['Id'])[0]
|
self.emby_db.get_item_by_id(season['Id'])[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
||||||
self.season(season, obj['ShowId'])
|
self.season(season, obj['ShowId'])
|
||||||
season_episodes.append(season['Id'])
|
|
||||||
else:
|
else:
|
||||||
season_id = self.get_season(*values(obj, QU.get_season_special_obj))
|
season_id = self.get_season(*values(obj, QU.get_season_special_obj))
|
||||||
self.artwork.add(obj['Artwork'], season_id, "season")
|
self.artwork.add(obj['Artwork'], season_id, "season")
|
||||||
|
|
||||||
for season in season_episodes:
|
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']:
|
for episode in episodes['Items']:
|
||||||
self.episode(episode)
|
self.episode(episode)
|
||||||
|
@ -562,6 +561,12 @@ class TVShows(KodiDb):
|
||||||
self.remove_show(obj['ParentId'], obj['Id'])
|
self.remove_show(obj['ParentId'], obj['Id'])
|
||||||
self.emby_db.remove_item_by_kodi_id(*values(obj, QUEM.delete_item_by_parent_tvshow_obj))
|
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))
|
self.emby_db.remove_item(*values(obj, QUEM.delete_item_obj))
|
||||||
|
|
||||||
def remove_tvshow(self, kodi_id, item_id):
|
def remove_tvshow(self, kodi_id, item_id):
|
||||||
|
|
Loading…
Reference in a new issue