Added UpdateUserdata to Movies and TV Shows
This commit is contained in:
parent
eddfa23a71
commit
40c02395a2
3 changed files with 108 additions and 121 deletions
|
@ -1412,37 +1412,44 @@ class PlexAPI():
|
|||
})
|
||||
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
|
||||
section with key = viewId.
|
||||
"""
|
||||
result = []
|
||||
url = "{server}/library/sections/%s/all" % viewId
|
||||
jsondata = self.doUtils.downloadUrl(url)
|
||||
jsondata = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
|
||||
try:
|
||||
result = jsondata['_children']
|
||||
except KeyError:
|
||||
self.logMsg("Error retrieving all items for Plex section %s" % viewId, -1)
|
||||
except TypeError:
|
||||
# Received an XML
|
||||
pass
|
||||
except:
|
||||
self.logMsg("Error retrieving all items for Plex section %s"
|
||||
% viewId, -1)
|
||||
return []
|
||||
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.
|
||||
(e.g. /library/metadata/194853/allLeaves pointing to all episodes
|
||||
of a TV show)
|
||||
(e.g. /library/sections/2/allLeaves pointing to all TV shows)
|
||||
|
||||
Input:
|
||||
key Key to a Plex item, e.g. 12345
|
||||
viewId Id of Plex library, e.g. '2'
|
||||
"""
|
||||
result = []
|
||||
url = "{server}/library/metadata/%s/allLeaves" % key
|
||||
jsondata = self.doUtils.downloadUrl(url)
|
||||
url = "{server}/library/sections/%s/allLeaves" % viewId
|
||||
jsondata = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
|
||||
try:
|
||||
result = jsondata['_children']
|
||||
except TypeError:
|
||||
# received an XMl
|
||||
pass
|
||||
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
|
||||
return result
|
||||
|
||||
|
@ -1517,6 +1524,8 @@ class API():
|
|||
self.server = utils.window('emby_server%s' % self.userId)
|
||||
self.token = utils.window('emby_accessToken%s' % self.userId)
|
||||
|
||||
self.jumpback = int(utils.settings('resumeJumpBack'))
|
||||
|
||||
def logMsg(self, msg, lvl=1):
|
||||
className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)
|
||||
|
@ -1643,6 +1652,7 @@ class API():
|
|||
'Played': played, # True/False
|
||||
'LastPlayedDate': lastPlayedDate,
|
||||
'Resume': resume, # Resume time in seconds
|
||||
'Runtime': runtime,
|
||||
'Rating': rating
|
||||
}
|
||||
"""
|
||||
|
@ -1670,17 +1680,14 @@ class API():
|
|||
except KeyError:
|
||||
lastPlayedDate = None
|
||||
|
||||
try:
|
||||
resume = float(item['viewOffset']) * 1.0/1000.0
|
||||
resume = round(resume, 6)
|
||||
except KeyError:
|
||||
resume = 0.0
|
||||
resume, runtime = self.getRuntime()
|
||||
return {
|
||||
'Favorite': favorite,
|
||||
'PlayCount': playcount,
|
||||
'Played': played,
|
||||
'LastPlayedDate': lastPlayedDate,
|
||||
'Resume': resume,
|
||||
'Runtime': runtime,
|
||||
'Rating': rating
|
||||
}
|
||||
|
||||
|
@ -1890,6 +1897,14 @@ class API():
|
|||
resume = float(item['viewOffset'])
|
||||
except KeyError:
|
||||
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
|
||||
resume = resume * time_factor
|
||||
resume = round(resume, 6)
|
||||
|
@ -2465,16 +2480,6 @@ class API():
|
|||
urlencode(args)
|
||||
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):
|
||||
externalsubs = []
|
||||
mapping = {}
|
||||
|
|
|
@ -281,6 +281,26 @@ class Movies(Items):
|
|||
count += 1
|
||||
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):
|
||||
# Process single movie
|
||||
kodicursor = self.kodicursor
|
||||
|
@ -485,48 +505,8 @@ class Movies(Items):
|
|||
# tags.append("Favorite movies")
|
||||
kodi_db.addTags(movieid, tags, "movie")
|
||||
# Process playstates
|
||||
resume = API.adjustResume(userdata['Resume'])
|
||||
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):
|
||||
# Remove movieid, fileid, emby reference
|
||||
emby_db = self.emby_db
|
||||
|
@ -1171,6 +1151,26 @@ class TVShows(Items):
|
|||
if not pdialog and self.contentmsg:
|
||||
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):
|
||||
# Process single tvshow
|
||||
kodicursor = self.kodicursor
|
||||
|
@ -1611,9 +1611,7 @@ class TVShows(Items):
|
|||
streams = API.getMediaStreams()
|
||||
kodi_db.addStreams(fileid, streams, runtime)
|
||||
# Process playstates
|
||||
resume = API.adjustResume(userdata['Resume'])
|
||||
total = round(float(runtime), 6)
|
||||
kodi_db.addPlaystate(fileid, resume, total, playcount, dateplayed)
|
||||
kodi_db.addPlaystate(fileid, resume, runtime, playcount, dateplayed)
|
||||
if not self.directpath and resume:
|
||||
# Create additional entry for widgets. This is only required for plugin/episode.
|
||||
temppathid = kodi_db.getPath("plugin://plugin.video.plexkodiconnect.tvshows/")
|
||||
|
@ -1625,53 +1623,7 @@ class TVShows(Items):
|
|||
"WHERE idFile = ?"
|
||||
))
|
||||
kodicursor.execute(query, (temppathid, filename, dateadded, tempfileid))
|
||||
kodi_db.addPlaystate(tempfileid, resume, total, 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)
|
||||
kodi_db.addPlaystate(tempfileid, resume, runtime, playcount, dateplayed)
|
||||
|
||||
def remove(self, itemid):
|
||||
# Remove showid, fileid, pathid, emby reference
|
||||
|
|
|
@ -302,7 +302,6 @@ class LibrarySync(threading.Thread):
|
|||
# Save last sync time
|
||||
overlap = 2
|
||||
|
||||
self.logMsg("An exception occurred: %s" % e, 1)
|
||||
time_now = datetime.utcnow()-timedelta(minutes=overlap)
|
||||
lastSync = time_now.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
self.logMsg("New sync time: client time -%s min: %s"
|
||||
|
@ -755,6 +754,10 @@ class LibrarySync(threading.Thread):
|
|||
viewId)
|
||||
self.GetAndProcessXMLs(itemType)
|
||||
self.logMsg("Processed view %s with ID %s" % (viewName, viewId), 1)
|
||||
# Update viewstate
|
||||
for view in views:
|
||||
self.PlexUpdateWatched(view['id'], itemType)
|
||||
|
||||
##### PROCESS DELETES #####
|
||||
if self.compare:
|
||||
# Manual sync, process deletes
|
||||
|
@ -765,6 +768,27 @@ class LibrarySync(threading.Thread):
|
|||
self.logMsg("%s sync is finished." % itemType, 1)
|
||||
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):
|
||||
# Get musicvideos from emby
|
||||
emby = self.emby
|
||||
|
@ -1022,22 +1046,24 @@ class LibrarySync(threading.Thread):
|
|||
'add_updateSeason',
|
||||
None,
|
||||
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 #####
|
||||
# Cycle through tv shows
|
||||
for tvShowId in allPlexTvShowsId:
|
||||
for view in views:
|
||||
if self.shouldStop():
|
||||
return False
|
||||
# Grab all episodes to tvshow from PMS
|
||||
episodes = plx.GetAllPlexLeaves(tvShowId)
|
||||
episodes = plx.GetAllPlexLeaves(view['id'])
|
||||
# Populate self.updatelist and self.allPlexElementsId
|
||||
self.GetUpdatelist(episodes,
|
||||
itemType,
|
||||
'add_updateEpisode',
|
||||
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
|
||||
self.GetAndProcessXMLs(itemType)
|
||||
|
@ -1050,6 +1076,10 @@ class LibrarySync(threading.Thread):
|
|||
TVshow.refreshSeasonEntry(XMLtvshow, tvShowId)
|
||||
self.logMsg("Season info refreshed", 1)
|
||||
|
||||
# Update viewstate:
|
||||
for view in views:
|
||||
self.PlexUpdateWatched(view['id'], itemType)
|
||||
|
||||
##### PROCESS DELETES #####
|
||||
if self.compare:
|
||||
# Manual sync, process deletes
|
||||
|
|
Loading…
Reference in a new issue