TV shows sync v0.1

This commit is contained in:
tomkat83 2016-01-09 16:14:02 +01:00
parent b3f588fd71
commit 5da6b4153e
3 changed files with 271 additions and 466 deletions

View file

@ -1232,16 +1232,46 @@ class PlexAPI():
try:
result = jsondata['_children']
except KeyError:
self.logMsg("Error retrieving all items for Plex section %s" % viewId, 1)
self.logMsg("Error retrieving all items for Plex section %s" % viewId, -1)
pass
return result
def GetPlexSubitems(self, key):
def GetAllPlexLeaves(self, key):
"""
Returns a list (raw JSON API dump) of all Plex subitems for the key.
(e.g. key=/library/metadata/194853/children pointing to a season)
"""
(e.g. /library/metadata/194853/allLeaves pointing to all episodes
of a TV show)
Input:
key Key to a Plex item, e.g. 12345
"""
result = []
url = "{server}/library/metadata/%s/allLeaves" % key
jsondata = self.doUtils.downloadUrl(url)
try:
result = jsondata['_children']
except KeyError:
self.logMsg("Error retrieving all children for Plex item %s" % key, -1)
pass
return result
def GetAllPlexChildren(self, key):
"""
Returns a list (raw JSON API dump) of all Plex children for the key.
(e.g. /library/metadata/194853/children pointing to a season)
Input:
key Key to a Plex item, e.g. 12345
"""
result = []
url = "{server}/library/metadata/%s/children" % key
jsondata = self.doUtils.downloadUrl(url)
try:
result = jsondata['_children']
except KeyError:
self.logMsg("Error retrieving all children for Plex item %s" % key, -1)
pass
return result
def GetPlexMetadata(self, key):
"""
@ -1270,7 +1300,7 @@ class PlexAPI():
headerOptions = {'Accept': 'application/xml'}
xml = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
if not xml:
self.logMsg("Error retrieving metadata for %s" % url, 1)
self.logMsg("Error retrieving metadata for %s" % url, -1)
return xml
@ -1388,17 +1418,23 @@ class API():
Returns the Plex unique movie id as a str, not int
"""
item = self.item
key_regex = re.compile(r'/(\d+)$')
# XML
try:
item = item[self.child].attrib
# JSON
except KeyError:
pass
key = item['key']
key = key_regex.findall(key)[0]
key = item['ratingKey']
return str(key)
def getIndex(self):
"""
Returns the 'index' of an PMS XML reply. Depicts e.g. season number.
"""
item = self.item[self.child].attrib
index = item['index']
return str(index)
def getDateCreated(self):
"""
Returns the date when this library item was created
@ -1550,33 +1586,19 @@ class API():
genre.append(child.attrib['tag'])
return genre
def getProvider(self, providername):
def getProvider(self, providername=None):
"""
providername: imdb, tvdb, musicBrainzArtist, musicBrainzAlbum,
musicBrainzTrackId
providername: depricated
Return IMDB: "tt1234567". Returns None if not found
Return IMDB, e.g. "imdb://tt0903624?lang=en". Returns None if not found
"""
item = self.item
item = item[self.child].attrib
imdb_regex = re.compile(r'''(
imdb:// # imdb tag, which will be followed be tt1234567
(tt\d{7}) # actual IMDB ID, e.g. tt1234567
\?? # zero or one ?
(.*) # rest, e.g. language setting
)''', re.VERBOSE)
regex = re.compile(r'''com.plexapp.agents.(.+)$''')
provider = regex.findall(item['guid'])
try:
if "Imdb" in providername:
provider = imdb_regex.findall(item['guid'])
provider = provider[0][1]
elif "tvdb" in providername:
provider = item['ProviderIds']['Tvdb']
elif "musicBrainzArtist" in providername:
provider = item['ProviderIds']['MusicBrainzArtist']
elif "musicBrainzAlbum" in providername:
provider = item['ProviderIds']['MusicBrainzAlbum']
elif "musicBrainzTrackId" in providername:
provider = item['ProviderIds']['MusicBrainzTrackId']
provider = provider[0]
except:
provider = None
return provider
@ -1752,6 +1774,25 @@ class API():
string = " / ".join(listobject)
return string
def getEpisodeDetails(self):
"""
Call on a single episode.
Output: for the corresponding the TV show and season:
[
TV show key, Plex: 'grandparentRatingKey'
TV show title, Plex: 'grandparentTitle'
TV show season, Plex: 'parentIndex'
Episode number, Plex: 'index'
]
"""
item = self.item[self.child].attrib
key = item['grandparentRatingKey']
title = item['grandparentTitle']
season = item['parentIndex']
episode = item['index']
return key, title, season, episode
def getFilePath(self):
"""
returns the path to the Plex object, e.g. "/library/metadata/221803"

View file

@ -1173,12 +1173,8 @@ class MusicVideos(Items):
self.logMsg("Deleted musicvideo %s from kodi database" % itemid, 1)
class TVShows(Items):
def __init__(self, embycursor, kodicursor):
Items.__init__(self, embycursor, kodicursor)
def added(self, items, pdialog):
total = len(items)
@ -1233,15 +1229,18 @@ class TVShows(Items):
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
API = api.API(item)
API = PlexAPI.API(item)
if utils.settings('syncEmptyShows') == "false" and not item['RecursiveItemCount']:
self.logMsg("Skipping empty show: %s" % item['Name'], 1)
return
# if utils.settings('syncEmptyShows') == "false" and not item['RecursiveItemCount']:
# self.logMsg("Skipping empty show: %s" % item['Name'], 1)
# return
# If the item already exist in the local Kodi DB we'll perform a full item update
# If the item doesn't exist, we'll add it to the database
update_item = True
itemid = item['Id']
itemid = API.getKey()
if not itemid:
self.logMsg("Cannot parse XML data for TV show", -1)
return
emby_dbitem = emby_db.getItem_byId(itemid)
try:
showid = emby_dbitem[0]
@ -1252,31 +1251,28 @@ class TVShows(Items):
update_item = False
self.logMsg("showid: %s not found." % itemid, 2)
if viewtag is None or viewid is None:
# Get view tag from emby
viewtag, viewid, mediatype = emby.getView_embyId(itemid)
self.logMsg("View tag found: %s" % viewtag, 2)
# if viewtag is None or viewid is None:
# # Get view tag from emby
# viewtag, viewid, mediatype = emby.getView_embyId(itemid)
# self.logMsg("View tag found: %s" % viewtag, 2)
# fileId information
checksum = API.getChecksum()
dateadded = API.getDateCreated()
userdata = API.getUserData()
playcount = userdata['PlayCount']
dateplayed = userdata['LastPlayedDate']
# item details
genres = item['Genres']
title = item['Name']
plot = API.getOverview()
rating = item.get('CommunityRating')
genres = API.getGenres()
title, sorttitle = API.getTitle()
plot = API.getPlot()
rating = API.getAudienceRating()
premieredate = API.getPremiereDate()
tvdb = API.getProvider('Tvdb')
sorttitle = item['SortName']
mpaa = API.getMpaa()
genre = " / ".join(genres)
genre = API.joinList(genres)
studios = API.getStudios()
studio = " / ".join(studios)
try:
studio = studios[0]
except IndexError:
studio = None
##### GET THE FILE AND PATH #####
playurl = API.getFilePath()
@ -1380,76 +1376,78 @@ class TVShows(Items):
kodicursor.execute(query, (path, None, None, 1, pathid))
# Process cast
people = artwork.getPeopleArtwork(item['People'])
people = API.getPeopleList()
kodi_db.addPeople(showid, people, "tvshow")
# Process genres
kodi_db.addGenres(showid, genres, "tvshow")
# Process artwork
artwork.addArtwork(artwork.getAllArtwork(item), showid, "tvshow", kodicursor)
allartworks = API.getAllArtwork()
artwork.addArtwork(allartworks, showid, "tvshow", kodicursor)
# Process studios
kodi_db.addStudios(showid, studios, "tvshow")
# Process tags: view, emby tags
tags = [viewtag]
tags.extend(item['Tags'])
if userdata['Favorite']:
tags.append("Favorite tvshows")
kodi_db.addTags(showid, tags, "tvshow")
# tags = [viewtag]
# tags.extend(item['Tags'])
# if userdata['Favorite']:
# tags.append("Favorite tvshows")
# kodi_db.addTags(showid, tags, "tvshow")
# Process seasons
all_seasons = emby.getSeasons(itemid)
for season in all_seasons['Items']:
self.add_updateSeason(season, showid=showid)
else:
# Finally, refresh the all season entry
seasonid = kodi_db.addSeason(showid, -1)
# Process artwork
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
def add_updateSeason(self, item, showid=None):
def refreshSeasonEntry(self, item, showid):
API = PlexAPI.API(item)
kodicursor = self.kodicursor
kodi_db = self.kodi_db
# Finally, refresh the all season entry
seasonid = kodi_db.addSeason(showid, -1)
# Process artwork for season
allartworks = API.getAllArtwork()
artwork.addArtwork(allartworks, seasonid, "season", kodicursor)
def add_updateSeason(self, item, viewid=None, viewtag=None):
self.logMsg("add_updateSeason called with", 1)
self.logMsg("item: %s" % item, 1)
self.logMsg("viewid: %s" % viewid, 1)
self.logMsg("viewName: %s" % viewtag, 1)
showid = viewid
itemid = viewid
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
API = PlexAPI.API(item)
self.logMsg("add_updateSeason initialization done", 1)
if item['LocationType'] == "Virtual":
self.logMsg("Skipping virtual season.")
return
seasonnum = item.get('IndexNumber', 1)
itemid = item['Id']
if showid is None:
try:
seriesId = item['SeriesId']
showid = emby_db.getItem_byId(seriesId)[0]
except KeyError:
return
except TypeError:
# Show is missing, update show instead.
show = self.emby.getItem(seriesId)
self.add_update(show)
return
seasonnum = API.getIndex()
self.logMsg("seasonnum: %s" % seasonnum, 1)
seasonid = kodi_db.addSeason(showid, seasonnum)
self.logMsg("seasonid: %s" % seasonid, 1)
# Create the reference in emby table
emby_db.addReference(itemid, seasonid, "Season", "season", parentid=showid)
self.logMsg("Added db reference", 1)
# Process artwork
artwork.addArtwork(artwork.getAllArtwork(item), seasonid, "season", kodicursor)
allartworks = API.getAllArtwork()
self.logMsg("Gotten allartworks: %s" % allartworks, 1)
artwork.addArtwork(allartworks, seasonid, "season", kodicursor)
self.logMsg("Added Artwork reference", 1)
def add_updateEpisode(self, item):
def add_updateEpisode(self, item, viewtag=None, viewid=None):
"""
viewtag and viewid are irrelevant!
"""
# Process single episode
kodiversion = self.kodiversion
kodicursor = self.kodicursor
emby_db = self.emby_db
kodi_db = self.kodi_db
artwork = self.artwork
API = api.API(item)
API = PlexAPI.API(item)
# If the item already exist in the local Kodi DB we'll perform a full item update
# If the item doesn't exist, we'll add it to the database
update_item = True
itemid = item['Id']
itemid = API.getKey()
self.logMsg("itemid: %s" % itemid, 2)
emby_dbitem = emby_db.getItem_byId(itemid)
try:
episodeid = emby_dbitem[0]
@ -1472,20 +1470,19 @@ class TVShows(Items):
dateplayed = userdata['LastPlayedDate']
# item details
people = API.getPeople()
writer = " / ".join(people['Writer'])
director = " / ".join(people['Director'])
title = item['Name']
plot = API.getOverview()
rating = item.get('CommunityRating')
director, writer, cast, producer = API.getPeople()
director = API.joinList(director)
writer = API.joinList(writer)
cast = API.joinList(cast)
producer = API.joinList(producer)
title, sorttitle = API.getTitle()
plot = API.getPlot()
rating = API.getAudienceRating()
runtime = API.getRuntime()
premieredate = API.getPremiereDate()
# episode details
seriesId = item['SeriesId']
seriesName = item['SeriesName']
season = item.get('ParentIndexNumber')
episode = item.get('IndexNumber', -1)
seriesId, seriesName, season, episode = API.getEpisodeDetails()
if season is None:
if item.get('AbsoluteEpisodeNumber'):
@ -1496,16 +1493,18 @@ class TVShows(Items):
season = -1
# Specials ordering within season
if item.get('AirsAfterSeasonNumber'):
airsBeforeSeason = item['AirsAfterSeasonNumber']
airsBeforeEpisode = 4096 # Kodi default number for afterseason ordering
else:
airsBeforeSeason = item.get('AirsBeforeSeasonNumber', "-1")
airsBeforeEpisode = item.get('AirsBeforeEpisodeNumber', "-1")
# if item.get('AirsAfterSeasonNumber'):
# airsBeforeSeason = item['AirsAfterSeasonNumber']
# airsBeforeEpisode = 4096 # Kodi default number for afterseason ordering
# else:
# airsBeforeSeason = item.get('AirsBeforeSeasonNumber', "-1")
# airsBeforeEpisode = item.get('AirsBeforeEpisodeNumber', "-1")
airsBeforeSeason = "-1"
airsBeforeEpisode = "-1"
# Append multi episodes to title
if item.get('IndexNumberEnd'):
title = "| %02d | %s" % (item['IndexNumberEnd'], title)
# if item.get('IndexNumberEnd'):
# title = "| %02d | %s" % (item['IndexNumberEnd'], title)
# Get season id
show = emby_db.getItem_byId(seriesId)
@ -1519,7 +1518,7 @@ class TVShows(Items):
try:
showid = show[0]
except TypeError:
self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId))
self.logMsg("Skipping: %s. Unable to add series: %s." % (itemid, seriesId), -1)
return False
seasonid = kodi_db.addSeason(showid, season)
@ -1659,11 +1658,12 @@ class TVShows(Items):
))
kodicursor.execute(query, (pathid, filename, dateadded, fileid))
self.logMsg("Start processing getPeopleList", 1)
# Process cast
people = artwork.getPeopleArtwork(item['People'])
people = API.getPeopleList()
kodi_db.addPeople(episodeid, people, "episode")
# Process artwork
artworks = artwork.getAllArtwork(item)
artworks = API.getAllArtwork()
artwork.addOrUpdateArt(artworks['Primary'], episodeid, "episode", "thumb", kodicursor)
# Process stream details
streams = API.getMediaStreams()

View file

@ -87,6 +87,8 @@ class ThreadedProcessMetadata(threading.Thread):
data = {
'itemType': as used to call functions in itemtypes.py
e.g. 'Movies' => itemtypes.Movies()
'method' Name of method in itemtypes.py
e.g. 'add_updateSeason'
'viewName' Plex str for library view (e.g. 'Movies')
'viewId' Plex Id to identifiy the library view
}
@ -108,6 +110,7 @@ class ThreadedProcessMetadata(threading.Thread):
viewId = self.data['viewId']
global processMetadataCount
with itemFkt() as item:
itemSubFkt = getattr(item, self.data['method'])
while self.stopped() is False:
# grabs item from queue
try:
@ -117,7 +120,7 @@ class ThreadedProcessMetadata(threading.Thread):
continue
# Do the work; lock to be sure we've only got 1 Thread
with self.lock:
item.add_update(
itemSubFkt(
plexitem,
viewtag=viewName,
viewid=viewId
@ -159,19 +162,19 @@ class ThreadedShowSyncInfo(threading.Thread):
downloadLock = self.locks[0]
processLock = self.locks[1]
self.dialog.create(
self.addonName + ": Sync " + self.viewName +
': ' + str(total) + 'items',
"Starting"
)
"%s: Sync %s: %s items" % (self.addonName,
self.viewName,
str(total)),
"Starting")
global getMetadataCount
global processMetadataCount
total = 2 * total
totalProgress = 0
while self.stopped() is not True:
while self.stopped() is False:
with downloadLock:
getMetadataProgress = getMetadataCount
with processLock:
processMetadataProgress = processMetadataCount
#with processLock:
processMetadataProgress = processMetadataCount
totalProgress = getMetadataProgress + processMetadataProgress
try:
percentage = int(float(totalProgress) / float(total)*100.0)
@ -182,7 +185,7 @@ class ThreadedShowSyncInfo(threading.Thread):
message="Downloaded: %s, Processed: %s" %
(getMetadataProgress, processMetadataProgress)
)
time.sleep(0.5)
time.sleep(1)
def stopThread(self):
self._shouldstop.set()
@ -345,16 +348,17 @@ class LibrarySync(threading.Thread):
# embyconn.commit()
self.initializeDBs()
# Sync video library
process = {
# process = {
'movies': self.movies,
'musicvideos': self.musicvideos,
'tvshows': self.tvshows,
'homevideos': self.homevideos
}
# 'movies': self.movies,
# 'musicvideos': self.musicvideos,
# 'tvshows': self.tvshows,
# 'homevideos': self.homevideos
# }
process = {
'movies': self.PlexMovies
'movies': self.PlexMovies,
'tvshows': self.PlexTVShows
# 'tvshows': self.PlexTVShows
}
@ -585,30 +589,34 @@ class LibrarySync(threading.Thread):
"""
if self.compare:
# Manual sync
for plexmovie in elementList:
if self.shouldStop():
return False
API = PlexAPI.API(plexmovie)
plex_checksum = API.getChecksum()
itemid = API.getKey()
self.allPlexElementsId[itemid] = plex_checksum
kodi_checksum = self.allKodiElementsId.get(itemid)
if kodi_checksum != plex_checksum:
# Only update if movie is not in Kodi or checksum is
# different
self.updatelist.append(itemid)
for item in elementList:
# Only look at valid items = Plex library items
if item.get('ratingKey', False):
if self.shouldStop():
return False
API = PlexAPI.API(item)
plex_checksum = API.getChecksum()
itemid = API.getKey()
self.allPlexElementsId[itemid] = plex_checksum
kodi_checksum = self.allKodiElementsId.get(itemid)
if kodi_checksum != plex_checksum:
# Only update if movie is not in Kodi or checksum is
# different
self.updatelist.append(itemid)
else:
# Initial or repair sync: get all Plex movies
for plexmovie in elementList:
API = PlexAPI.API(plexmovie)
itemid = API.getKey()
plex_checksum = API.getChecksum()
self.allPlexElementsId[itemid] = plex_checksum
self.updatelist.append(itemid)
for item in elementList:
# Only look at valid items = Plex library items
if item.get('ratingKey', False):
API = PlexAPI.API(item)
itemid = API.getKey()
plex_checksum = API.getChecksum()
self.allPlexElementsId[itemid] = plex_checksum
self.updatelist.append(itemid)
# Update the Kodi popup info
return self.updatelist, self.allPlexElementsId
def GetAndProcessXMLs(self, itemType, viewName, viewId):
def GetAndProcessXMLs(self, itemType, viewName, viewId, method):
"""
Downloads all XMLs for itemType (e.g. Movies, TV-Shows). Processes them
by then calling itemtypes.<itemType>()
@ -617,6 +625,8 @@ class LibrarySync(threading.Thread):
itemType: to construct itemtypes.py function name: 'Movies'
viewName: Plex name of library, e.g. 'My Movies'
viewId: Plex Id for that library
method: name of itemtypes.py method,
e.g. 'add_updateSeason'
Returns True if/when done
"""
@ -639,6 +649,9 @@ class LibrarySync(threading.Thread):
getMetadataCount = 0
global processMetadataCount
processMetadataCount = 0
# Populate queue: GetMetadata
for itemId in self.updatelist:
getMetadataQueue.put(itemId)
# Spawn GetMetadata threads
threads = []
for i in range(self.syncThreadNumber):
@ -652,13 +665,11 @@ class LibrarySync(threading.Thread):
t.start()
threads.append(t)
self.logMsg("%s download threads spawned" % self.syncThreadNumber, 1)
# Populate queue: GetMetadata
for itemId in self.updatelist:
getMetadataQueue.put(itemId)
self.logMsg("Queue populated", 1)
# Spawn one more thread to process Metadata, once downloaded
data = {
'itemType': itemType,
'method': method,
'viewName': viewName,
'viewId': viewId
}
@ -714,7 +725,6 @@ class LibrarySync(threading.Thread):
self.logMsg("%s compare finished." % itemType, 1)
return True
def PlexMovies(self):
# Initialize
plx = PlexAPI.PlexAPI()
@ -724,21 +734,20 @@ class LibrarySync(threading.Thread):
views = plx.GetPlexCollections('movie')
self.logMsg("Media folders: %s" % views, 1)
# Get movies from Plex server
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
if self.compare:
# Get movies from Plex server
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
# Pull the list of movies and boxsets in Kodi
try:
self.allKodiElementsId = dict(emby_db.getChecksum('Movie'))
except ValueError:
self.allKodiElementsId = {}
embyconn.close()
else:
# Getting all metadata, hence set Kodi elements to {}
self.allKodiElementsId = {}
embyconn.close()
##### PROCESS MOVIES #####
for view in views:
@ -752,177 +761,14 @@ class LibrarySync(threading.Thread):
# Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(all_plexmovies)
self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1)
# Returns True if successful
result = self.GetAndProcessXMLs('Movies', viewName, viewId)
result = self.GetAndProcessXMLs(
'Movies',
viewName,
viewId,
'add_update'
)
return result
def movies(self, embycursor, kodicursor, pdialog, compare=False):
# Get movies from emby
emby = self.emby
emby_db = embydb.Embydb_Functions(embycursor)
movies = itemtypes.Movies(embycursor, kodicursor)
views = emby_db.getView_byType('movies')
views += emby_db.getView_byType('mixed')
self.logMsg("Media folders: %s" % views, 1)
if compare:
# Pull the list of movies and boxsets in Kodi
try:
all_kodimovies = dict(emby_db.getChecksum('Movie'))
except ValueError:
all_kodimovies = {}
try:
all_kodisets = dict(emby_db.getChecksum('BoxSet'))
except ValueError:
all_kodisets = {}
all_embymoviesIds = set()
all_embyboxsetsIds = set()
updatelist = []
##### PROCESS MOVIES #####
for view in views:
if self.shouldStop():
return False
# Get items per view
viewId = view['id']
viewName = view['name']
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Gathering movies from view: %s..." % viewName)
if compare:
# Manual sync
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Comparing movies from view: %s..." % viewName)
all_embymovies = emby.getMovies(viewId, basic=True)
for embymovie in all_embymovies['Items']:
if self.shouldStop():
return False
API = api.API(embymovie)
itemid = embymovie['Id']
all_embymoviesIds.add(itemid)
if all_kodimovies.get(itemid) != API.getChecksum():
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
self.logMsg("Movies to update for %s: %s" % (viewName, updatelist), 1)
embymovies = emby.getFullItems(updatelist)
total = len(updatelist)
del updatelist[:]
else:
# Initial or repair sync
all_embymovies = emby.getMovies(viewId)
total = all_embymovies['TotalRecordCount']
embymovies = all_embymovies['Items']
if pdialog:
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
count = 0
for embymovie in embymovies:
# Process individual movies
if self.shouldStop():
return False
title = embymovie['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message=title)
count += 1
movies.add_update(embymovie, viewName, viewId)
else:
self.logMsg("Movies finished.", 2)
##### PROCESS BOXSETS #####
if pdialog:
pdialog.update(heading="Emby for Kodi", message="Gathering boxsets from server...")
boxsets = emby.getBoxset()
if compare:
# Manual sync
embyboxsets = []
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Comparing boxsets...")
for boxset in boxsets['Items']:
if self.shouldStop():
return False
# Boxset has no real userdata, so using etag to compare
checksum = boxset['Etag']
itemid = boxset['Id']
all_embyboxsetsIds.add(itemid)
if all_kodisets.get(itemid) != checksum:
# Only update if boxset is not in Kodi or checksum is different
updatelist.append(itemid)
embyboxsets.append(boxset)
self.logMsg("Boxsets to update: %s" % updatelist, 1)
total = len(updatelist)
else:
total = boxsets['TotalRecordCount']
embyboxsets = boxsets['Items']
if pdialog:
pdialog.update(heading="Processing Boxsets / %s items" % total)
count = 0
for boxset in embyboxsets:
# Process individual boxset
if self.shouldStop():
return False
title = boxset['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message=title)
count += 1
movies.add_updateBoxset(boxset)
else:
self.logMsg("Boxsets finished.", 2)
##### PROCESS DELETES #####
if compare:
# Manual sync, process deletes
for kodimovie in all_kodimovies:
if kodimovie not in all_embymoviesIds:
movies.remove(kodimovie)
else:
self.logMsg("Movies compare finished.", 1)
for boxset in all_kodisets:
if boxset not in all_embyboxsetsIds:
movies.remove(boxset)
else:
self.logMsg("Boxsets compare finished.", 1)
return True
def musicvideos(self, embycursor, kodicursor, pdialog, compare=False):
# Get musicvideos from emby
emby = self.emby
@ -1111,22 +957,21 @@ class LibrarySync(threading.Thread):
return True
def PlexTVShows(self, embycursor, kodicursor):
def PlexTVShows(self):
# Initialize
plx = PlexAPI.PlexAPI()
compare = self.compare
pdialog = self.pDialog
self.updatelist = []
self.allPlexElementsId = {}
# Get shows from emby
emby_db = embydb.Embydb_Functions(embycursor)
tvshows = itemtypes.TVShows(embycursor, kodicursor)
views = plx.GetPlexCollections('show')
self.logMsg("Media folders: %s" % views, 1)
self.allKodiElementsId = {}
if compare:
if self.compare:
# Get movies from Plex server
embyconn = utils.kodiSQL('emby')
embycursor = embyconn.cursor()
emby_db = embydb.Embydb_Functions(embycursor)
# Pull the list of TV shows already in Kodi
try:
all_koditvshows = dict(emby_db.getChecksum('Series'))
@ -1139,145 +984,64 @@ class LibrarySync(threading.Thread):
self.allKodiElementsId.update(all_kodiepisodes)
except ValueError:
pass
embyconn.close()
##### PROCESS TV Shows #####
for view in views:
self.updatelist = []
self.allPlexElementsId = {}
if self.shouldStop():
return False
# Get items per view
viewId = view['id']
viewName = view['name']
if pdialog:
pdialog.update(
heading=self.addonName,
message="Gathering TV Shows from view: %s..." % viewName)
all_plexTvShows = plx.GetPlexSectionResults(viewId)
allPlexTvShows = plx.GetPlexSectionResults(viewId)
# Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(allPlexTvShows)
# Process self.updatelist
self.GetAndProcessXMLs('TVShows',
viewName,
viewId,
'add_update')
self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1)
# Populate self.updatelist with TV shows and self.allPlexElementsId
self.GetUpdatelist(all_plexTvShows, viewName)
# Save for later use
allPlexTvShowsId = self.allPlexElementsId
# Run through self.updatelist, get XML metadata per item and safe
# to Kodi
self.ProcessUpdateList(tvshows, view)
##### PROCESS TV Seasons #####
# Cycle through tv shows
for tvShowId in allPlexTvShowsId:
self.updatelist = []
self.allPlexElementsId = {}
# Grab all seasons to tvshow from PMS
seasons = plx.GetAllPlexChildren(tvShowId)
# Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(seasons)
# Process self.updatelist
self.GetAndProcessXMLs('TVShows',
None,
tvShowId, # send showId instead of viewid
'add_updateSeason')
XMLtvshow = plx.GetPlexMetadata(tvShowId)
with itemtypes.TVShows() as TVshow:
TVshow.refreshSeasonEntry(XMLtvshow, tvShowId)
self.logMsg("Processed all seasons of TV show with Plex Id %s" % tvShowId, 1)
if compare:
# Manual sync
for plexTvShow in all_plexTvShows:
if self.shouldStop():
return False
API = plx(plexTvShow)
plex_checksum = API.getChecksum()
itemid = API.getKey()
kodi_checksum = all_kodimoviesId.get(itemid)
all_plextvshowsIds[itemid] = itemid
kodi_checksum = all_koditvshows.get(itemid)
#if kodi_checksum != plex_checksum:
if all_koditvshows.get(itemid) != API.getChecksum():
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
self.logMsg("TVShows to update for %s: %s" % (viewName, updatelist), 1)
embytvshows = emby.getFullItems(updatelist)
total = len(updatelist)
del updatelist[:]
else:
all_embytvshows = emby.getShows(viewId)
total = all_embytvshows['TotalRecordCount']
embytvshows = all_embytvshows['Items']
if pdialog:
pdialog.update(heading="Processing %s / %s items" % (viewName, total))
count = 0
for embytvshow in embytvshows:
# Process individual show
if self.shouldStop():
return False
itemid = embytvshow['Id']
title = embytvshow['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message=title)
count += 1
tvshows.add_update(embytvshow, viewName, viewId)
if not compare:
# Process episodes
all_episodes = emby.getEpisodesbyShow(itemid)
for episode in all_episodes['Items']:
# Process individual show
if self.shouldStop():
return False
episodetitle = episode['Name']
if pdialog:
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
tvshows.add_updateEpisode(episode)
else:
if compare:
# Get all episodes in view
if pdialog:
pdialog.update(
heading="Emby for Kodi",
message="Comparing episodes from view: %s..." % viewName)
all_embyepisodes = emby.getEpisodes(viewId, basic=True)
for embyepisode in all_embyepisodes['Items']:
if self.shouldStop():
return False
API = api.API(embyepisode)
itemid = embyepisode['Id']
all_embyepisodesIds.add(itemid)
if all_kodiepisodes.get(itemid) != API.getChecksum():
# Only update if movie is not in Kodi or checksum is different
updatelist.append(itemid)
self.logMsg("Episodes to update for %s: %s" % (viewName, updatelist), 1)
embyepisodes = emby.getFullItems(updatelist)
total = len(updatelist)
del updatelist[:]
count = 0
for episode in embyepisodes:
# Process individual episode
if self.shouldStop():
return False
title = episode['SeriesName']
episodetitle = episode['Name']
if pdialog:
percentage = int((float(count) / float(total))*100)
pdialog.update(percentage, message="%s - %s" % (title, episodetitle))
count += 1
tvshows.add_updateEpisode(episode)
else:
self.logMsg("TVShows finished.", 2)
##### PROCESS DELETES #####
if compare:
# Manual sync, process deletes
for koditvshow in all_koditvshows:
if koditvshow not in all_embytvshowsIds:
tvshows.remove(koditvshow)
else:
self.logMsg("TVShows compare finished.", 1)
for kodiepisode in all_kodiepisodes:
if kodiepisode not in all_embyepisodesIds:
tvshows.remove(kodiepisode)
else:
self.logMsg("Episodes compare finished.", 1)
##### PROCESS TV Episodes #####
# Cycle through tv shows
for tvShowId in allPlexTvShowsId:
self.updatelist = []
self.allPlexElementsId = {}
# Grab all episodes to tvshow from PMS
episodes = plx.GetAllPlexLeaves(tvShowId)
# Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(episodes)
# Process self.updatelist
self.GetAndProcessXMLs('TVShows',
None,
None,
'add_updateEpisode')
self.logMsg("Processed all episodes of TV show with Plex Id %s" % tvShowId, 1)
return True