Added UpdateUserdata to Movies and TV Shows

This commit is contained in:
tomkat83 2016-01-14 16:17:24 +01:00
parent eddfa23a71
commit 40c02395a2
3 changed files with 108 additions and 121 deletions

View file

@ -1412,37 +1412,44 @@ class PlexAPI():
}) })
return collections return collections
def GetPlexSectionResults(self, viewId): def GetPlexSectionResults(self, viewId, headerOptions={}):
""" """
Returns a list (raw JSON API dump) of all Plex items in the Plex Returns a list (raw JSON API dump) of all Plex items in the Plex
section with key = viewId. section with key = viewId.
""" """
result = [] result = []
url = "{server}/library/sections/%s/all" % viewId url = "{server}/library/sections/%s/all" % viewId
jsondata = self.doUtils.downloadUrl(url) jsondata = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
try: try:
result = jsondata['_children'] result = jsondata['_children']
except KeyError: except TypeError:
self.logMsg("Error retrieving all items for Plex section %s" % viewId, -1) # Received an XML
pass pass
except:
self.logMsg("Error retrieving all items for Plex section %s"
% viewId, -1)
return []
return result return result
def GetAllPlexLeaves(self, key): def GetAllPlexLeaves(self, viewId, headerOptions={}):
""" """
Returns a list (raw JSON API dump) of all Plex subitems for the key. Returns a list (raw JSON API dump) of all Plex subitems for the key.
(e.g. /library/metadata/194853/allLeaves pointing to all episodes (e.g. /library/sections/2/allLeaves pointing to all TV shows)
of a TV show)
Input: Input:
key Key to a Plex item, e.g. 12345 viewId Id of Plex library, e.g. '2'
""" """
result = [] result = []
url = "{server}/library/metadata/%s/allLeaves" % key url = "{server}/library/sections/%s/allLeaves" % viewId
jsondata = self.doUtils.downloadUrl(url) jsondata = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
try: try:
result = jsondata['_children'] result = jsondata['_children']
except TypeError:
# received an XMl
pass
except KeyError: except KeyError:
self.logMsg("Error retrieving all children for Plex item %s" % key, -1) self.logMsg("Error retrieving all children for Plex viewId %s"
% viewId, -1)
pass pass
return result return result
@ -1517,6 +1524,8 @@ class API():
self.server = utils.window('emby_server%s' % self.userId) self.server = utils.window('emby_server%s' % self.userId)
self.token = utils.window('emby_accessToken%s' % self.userId) self.token = utils.window('emby_accessToken%s' % self.userId)
self.jumpback = int(utils.settings('resumeJumpBack'))
def logMsg(self, msg, lvl=1): def logMsg(self, msg, lvl=1):
className = self.__class__.__name__ className = self.__class__.__name__
utils.logMsg("%s %s" % (self.addonName, className), msg, lvl) utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
@ -1643,6 +1652,7 @@ class API():
'Played': played, # True/False 'Played': played, # True/False
'LastPlayedDate': lastPlayedDate, 'LastPlayedDate': lastPlayedDate,
'Resume': resume, # Resume time in seconds 'Resume': resume, # Resume time in seconds
'Runtime': runtime,
'Rating': rating 'Rating': rating
} }
""" """
@ -1670,17 +1680,14 @@ class API():
except KeyError: except KeyError:
lastPlayedDate = None lastPlayedDate = None
try: resume, runtime = self.getRuntime()
resume = float(item['viewOffset']) * 1.0/1000.0
resume = round(resume, 6)
except KeyError:
resume = 0.0
return { return {
'Favorite': favorite, 'Favorite': favorite,
'PlayCount': playcount, 'PlayCount': playcount,
'Played': played, 'Played': played,
'LastPlayedDate': lastPlayedDate, 'LastPlayedDate': lastPlayedDate,
'Resume': resume, 'Resume': resume,
'Runtime': runtime,
'Rating': rating 'Rating': rating
} }
@ -1890,6 +1897,14 @@ class API():
resume = float(item['viewOffset']) resume = float(item['viewOffset'])
except KeyError: except KeyError:
resume = 0.0 resume = 0.0
# Adjust the resume point by x seconds as chosen by the user in the
# settings
if resume:
# To avoid negative bookmark
if resume > self.jumpback:
resume = resume - self.jumpback
runtime = runtime * time_factor runtime = runtime * time_factor
resume = resume * time_factor resume = resume * time_factor
resume = round(resume, 6) resume = round(resume, 6)
@ -2465,16 +2480,6 @@ class API():
urlencode(args) urlencode(args)
return url return url
def adjustResume(self, resume_seconds):
resume = 0
if resume_seconds:
resume = round(float(resume_seconds), 6)
jumpback = int(utils.settings('resumeJumpBack'))
if resume > jumpback:
# To avoid negative bookmark
resume = resume - jumpback
return resume
def externalSubs(self, playurl): def externalSubs(self, playurl):
externalsubs = [] externalsubs = []
mapping = {} mapping = {}

View file

@ -281,6 +281,26 @@ class Movies(Items):
count += 1 count += 1
self.add_updateBoxset(boxset) self.add_updateBoxset(boxset)
def updateUserdata(self, itemList):
"""
Updates the Kodi watched state of the item from PMS. Also retrieves
Plex resume points for movies in progress.
"""
API = PlexAPI.API(itemList)
for itemNumber in range(0, len(itemList)):
API.setChildNumber(itemNumber)
itemid = API.getKey()
# Get key and db entry on the Kodi db side
fileid = self.emby_db.getItem_byId(itemid)[1]
# Grab the user's viewcount, resume points etc. from PMS' answer
userdata = API.getUserData()
# Write to Kodi DB
self.kodi_db.addPlaystate(fileid,
userdata['Resume'],
userdata['Runtime'],
userdata['PlayCount'],
userdata['LastPlayedDate'])
def add_update(self, item, viewtag=None, viewid=None): def add_update(self, item, viewtag=None, viewid=None):
# Process single movie # Process single movie
kodicursor = self.kodicursor kodicursor = self.kodicursor
@ -485,48 +505,8 @@ class Movies(Items):
# tags.append("Favorite movies") # tags.append("Favorite movies")
kodi_db.addTags(movieid, tags, "movie") kodi_db.addTags(movieid, tags, "movie")
# Process playstates # Process playstates
resume = API.adjustResume(userdata['Resume'])
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed) kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
def updateUserdata(self, item):
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
# Poster with progress bar
emby_db = self.emby_db
kodi_db = self.kodi_db
API = api.API(item)
# Get emby information
itemid = item['Id']
checksum = API.getChecksum()
userdata = API.getUserData()
runtime = API.getRuntime()
# Get Kodi information
emby_dbitem = emby_db.getItem_byId(itemid)
try:
movieid = emby_dbitem[0]
fileid = emby_dbitem[1]
self.logMsg(
"Update playstate for movie: %s fileid: %s"
% (item['Name'], fileid), 1)
except TypeError:
return
# Process favorite tags
if userdata['Favorite']:
kodi_db.addTag(movieid, "Favorite movies", "movie")
else:
kodi_db.removeTag(movieid, "Favorite movies", "movie")
# Process playstates
playcount = userdata['PlayCount']
dateplayed = userdata['LastPlayedDate']
resume = API.adjustResume(userdata['Resume'])
total = round(float(runtime), 6)
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
emby_db.updateReference(itemid, checksum)
def remove(self, itemid): def remove(self, itemid):
# Remove movieid, fileid, emby reference # Remove movieid, fileid, emby reference
emby_db = self.emby_db emby_db = self.emby_db
@ -1171,6 +1151,26 @@ class TVShows(Items):
if not pdialog and self.contentmsg: if not pdialog and self.contentmsg:
self.contentPop(title) self.contentPop(title)
def updateUserdata(self, itemList):
"""
Updates the Kodi watched state of the item from PMS. Also retrieves
Plex resume points for movies in progress.
"""
API = PlexAPI.API(itemList)
for itemNumber in range(0, len(itemList)):
API.setChildNumber(itemNumber)
itemid = API.getKey()
# Get key and db entry on the Kodi db side
fileid = self.emby_db.getItem_byId(itemid)[1]
# Grab the user's viewcount, resume points etc. from PMS' answer
userdata = API.getUserData()
# Write to Kodi DB
self.kodi_db.addPlaystate(fileid,
userdata['Resume'],
userdata['Runtime'],
userdata['PlayCount'],
userdata['LastPlayedDate'])
def add_update(self, item, viewtag=None, viewid=None): def add_update(self, item, viewtag=None, viewid=None):
# Process single tvshow # Process single tvshow
kodicursor = self.kodicursor kodicursor = self.kodicursor
@ -1611,9 +1611,7 @@ class TVShows(Items):
streams = API.getMediaStreams() streams = API.getMediaStreams()
kodi_db.addStreams(fileid, streams, runtime) kodi_db.addStreams(fileid, streams, runtime)
# Process playstates # Process playstates
resume = API.adjustResume(userdata['Resume']) kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
total = round(float(runtime), 6)
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
if not self.directpath and resume: if not self.directpath and resume:
# Create additional entry for widgets. This is only required for plugin/episode. # Create additional entry for widgets. This is only required for plugin/episode.
temppathid = kodi_db.getPath("plugin://plugin.video.plexkodiconnect.tvshows/") temppathid = kodi_db.getPath("plugin://plugin.video.plexkodiconnect.tvshows/")
@ -1625,53 +1623,7 @@ class TVShows(Items):
"WHERE idFile = ?" "WHERE idFile = ?"
)) ))
kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid)) kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
kodi_db.addPlaystate(tempfileid, resume, total, playcount, dateplayed) kodi_db.addPlaystate(tempfileid, resume, runtime, playcount, dateplayed)
def updateUserdata(self, item):
# This updates: Favorite, LastPlayedDate, Playcount, PlaybackPositionTicks
# Poster with progress bar
emby_db = self.emby_db
kodi_db = self.kodi_db
API = api.API(item)
# Get emby information
itemid = item['Id']
checksum = API.getChecksum()
userdata = API.getUserData()
runtime = API.getRuntime()
# Get Kodi information
emby_dbitem = emby_db.getItem_byId(itemid)
try:
kodiid = emby_dbitem[0]
fileid = emby_dbitem[1]
mediatype = emby_dbitem[4]
self.logMsg(
"Update playstate for %s: %s fileid: %s"
% (mediatype, item['Name'], fileid), 1)
except TypeError:
return
# Process favorite tags
if mediatype == "tvshow":
if userdata['Favorite']:
kodi_db.addTag(kodiid, "Favorite tvshows", "tvshow")
else:
kodi_db.removeTag(kodiid, "Favorite tvshows", "tvshow")
# Process playstates
if mediatype == "episode":
playcount = userdata['PlayCount']
dateplayed = userdata['LastPlayedDate']
resume = API.adjustResume(userdata['Resume'])
total = round(float(runtime), 6)
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
if not self.directpath and not resume:
# Make sure there's no other bookmarks created by widget.
filename = kodi_db.getFile(fileid)
kodi_db.removeFile("plugin://plugin.video.plexkodiconnect.tvshows/", filename)
emby_db.updateReference(itemid, checksum)
def remove(self, itemid): def remove(self, itemid):
# Remove showid, fileid, pathid, emby reference # Remove showid, fileid, pathid, emby reference

View file

@ -302,7 +302,6 @@ class LibrarySync(threading.Thread):
# Save last sync time # Save last sync time
overlap = 2 overlap = 2
self.logMsg("An exception occurred: %s" % e, 1)
time_now = datetime.utcnow()-timedelta(minutes=overlap) time_now = datetime.utcnow()-timedelta(minutes=overlap)
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ') lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
self.logMsg("New sync time: client time -%s min: %s" self.logMsg("New sync time: client time -%s min: %s"
@ -755,6 +754,10 @@ class LibrarySync(threading.Thread):
viewId) viewId)
self.GetAndProcessXMLs(itemType) self.GetAndProcessXMLs(itemType)
self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1) self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1)
# Update viewstate
for view in views:
self.PlexUpdateWatched(view['id'], itemType)
##### PROCESS DELETES ##### ##### PROCESS DELETES #####
if self.compare: if self.compare:
# Manual sync, process deletes # Manual sync, process deletes
@ -765,6 +768,27 @@ class LibrarySync(threading.Thread):
self.logMsg("%s sync is finished." % itemType, 1) self.logMsg("%s sync is finished." % itemType, 1)
return True return True
def PlexUpdateWatched(self, viewId, itemType):
"""
Updates ALL plex elements' view status ('watched' or 'unwatched') and
also updates resume times.
This is done by downloading one XML for ALL elements with viewId
"""
starttotal = datetime.now()
plx = PlexAPI.PlexAPI()
# Download XML, not JSON
headerOptions = {'Accept': 'application/xml'}
plexItems = plx.GetAllPlexLeaves(viewId,
headerOptions=headerOptions)
itemMth = getattr(itemtypes, itemType)
with itemMth() as method:
method.UpdateWatched(plexItems)
elapsedtotal = datetime.now() - starttotal
self.logMsg("Syncing userdata for itemtype %s and viewid %s took "
"%s seconds" % (itemType, viewId, elapsedtotal), 0)
def musicvideos(self, embycursor, kodicursor, pdialog, compare=False): def musicvideos(self, embycursor, kodicursor, pdialog, compare=False):
# Get musicvideos from emby # Get musicvideos from emby
emby = self.emby emby = self.emby
@ -1022,22 +1046,24 @@ class LibrarySync(threading.Thread):
'add_updateSeason', 'add_updateSeason',
None, None,
tvShowId) # send showId instead of viewid tvShowId) # send showId instead of viewid
self.logMsg("Analyzed all seasons of TV show with Plex Id %s" % tvShowId, 1) self.logMsg("Analyzed all seasons of TV show with Plex Id %s"
% tvShowId, 1)
##### PROCESS TV Episodes ##### ##### PROCESS TV Episodes #####
# Cycle through tv shows # Cycle through tv shows
for tvShowId in allPlexTvShowsId: for view in views:
if self.shouldStop(): if self.shouldStop():
return False return False
# Grab all episodes to tvshow from PMS # Grab all episodes to tvshow from PMS
episodes = plx.GetAllPlexLeaves(tvShowId) episodes = plx.GetAllPlexLeaves(view['id'])
# Populate self.updatelist and self.allPlexElementsId # Populate self.updatelist and self.allPlexElementsId
self.GetUpdatelist(episodes, self.GetUpdatelist(episodes,
itemType, itemType,
'add_updateEpisode', 'add_updateEpisode',
None, None,
None) None)
self.logMsg("Analyzed all episodes of TV show with Plex Id %s" % tvShowId, 1) self.logMsg("Analyzed all episodes of TV show with Plex Id %s"
% tvShowId, 1)
# Process self.updatelist # Process self.updatelist
self.GetAndProcessXMLs(itemType) self.GetAndProcessXMLs(itemType)
@ -1050,6 +1076,10 @@ class LibrarySync(threading.Thread):
TVshow.refreshSeasonEntry(XMLtvshow, tvShowId) TVshow.refreshSeasonEntry(XMLtvshow, tvShowId)
self.logMsg("Season info refreshed", 1) self.logMsg("Season info refreshed", 1)
# Update viewstate:
for view in views:
self.PlexUpdateWatched(view['id'], itemType)
##### PROCESS DELETES ##### ##### PROCESS DELETES #####
if self.compare: if self.compare:
# Manual sync, process deletes # Manual sync, process deletes