Fixed plex companion headers and resume point
This commit is contained in:
parent
58020021fa
commit
e0330c1a28
8 changed files with 102 additions and 80 deletions
|
@ -90,7 +90,7 @@ class Main:
|
|||
folderid = params['folderid'][0]
|
||||
modes[mode](itemid, folderid)
|
||||
elif mode == "companion":
|
||||
resume = params.get('resume', '')
|
||||
resume = params.get('resume', '')[0]
|
||||
modes[mode](itemid, resume=resume)
|
||||
else:
|
||||
modes[mode]()
|
||||
|
|
|
@ -90,8 +90,6 @@ class PlexAPI():
|
|||
self.userId = utils.window('emby_currUser')
|
||||
self.token = utils.window('emby_accessToken%s' % self.userId)
|
||||
self.server = utils.window('emby_server%s' % self.userId)
|
||||
self.plexLogin = utils.settings('plexLogin')
|
||||
self.plexToken = utils.settings('plexToken')
|
||||
|
||||
self.doUtils = downloadutils.DownloadUtils()
|
||||
|
||||
|
@ -797,6 +795,8 @@ class PlexAPI():
|
|||
"""
|
||||
# Get addon infos
|
||||
xargs = {
|
||||
"Content-type": "application/x-www-form-urlencoded",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
'X-Plex-Language': 'en',
|
||||
'X-Plex-Device': self.addonName,
|
||||
'X-Plex-Client-Platform': self.platform,
|
||||
|
@ -1052,8 +1052,8 @@ class PlexAPI():
|
|||
|
||||
Will return empty strings if failed.
|
||||
"""
|
||||
plexLogin = self.plexLogin
|
||||
plexToken = self.plexToken
|
||||
plexLogin = utils.settings('plexLogin')
|
||||
plexToken = utils.settings('plexToken')
|
||||
machineIdentifier = utils.settings('plex_machineIdentifier')
|
||||
self.logMsg("Getting user list.", 1)
|
||||
# Get list of Plex home users
|
||||
|
@ -1412,7 +1412,7 @@ class PlexAPI():
|
|||
|
||||
def GetPlexSectionResults(self, viewId, headerOptions={}):
|
||||
"""
|
||||
Returns a list (raw JSON API dump) of all Plex items in the Plex
|
||||
Returns a list (raw JSON or XML API dump) of all Plex items in the Plex
|
||||
section with key = viewId.
|
||||
"""
|
||||
result = []
|
||||
|
@ -1421,21 +1421,29 @@ class PlexAPI():
|
|||
try:
|
||||
result = jsondata['_children']
|
||||
except TypeError:
|
||||
# Received an XML
|
||||
pass
|
||||
except:
|
||||
# Maybe we received an XML, check for that with tag attribute
|
||||
try:
|
||||
jsondata.tag
|
||||
result = jsondata
|
||||
# Nope, not an XML, abort
|
||||
except AttributeError:
|
||||
self.logMsg("Error retrieving all items for Plex section %s"
|
||||
% viewId, -1)
|
||||
return result
|
||||
except KeyError:
|
||||
self.logMsg("Error retrieving all items for Plex section %s"
|
||||
% viewId, -1)
|
||||
return []
|
||||
return result
|
||||
|
||||
def GetAllPlexLeaves(self, viewId, headerOptions={}):
|
||||
"""
|
||||
Returns a list (raw JSON API dump) of all Plex subitems for the key.
|
||||
Returns a list (raw JSON or XML API dump) of all Plex subitems for the
|
||||
key.
|
||||
(e.g. /library/sections/2/allLeaves pointing to all TV shows)
|
||||
|
||||
Input:
|
||||
viewId Id of Plex library, e.g. '2'
|
||||
headerOptions to override the download headers
|
||||
"""
|
||||
result = []
|
||||
url = "{server}/library/sections/%s/allLeaves" % viewId
|
||||
|
@ -1443,12 +1451,18 @@ class PlexAPI():
|
|||
try:
|
||||
result = jsondata['_children']
|
||||
except TypeError:
|
||||
# received an XMl
|
||||
pass
|
||||
except KeyError:
|
||||
self.logMsg("Error retrieving all children for Plex viewId %s"
|
||||
# Maybe we received an XML, check for that with tag attribute
|
||||
try:
|
||||
jsondata.tag
|
||||
result = jsondata
|
||||
# Nope, not an XML, abort
|
||||
except AttributeError:
|
||||
self.logMsg("Error retrieving all leaves for Plex section %s"
|
||||
% viewId, -1)
|
||||
return result
|
||||
except KeyError:
|
||||
self.logMsg("Error retrieving all leaves for Plex viewId %s"
|
||||
% viewId, -1)
|
||||
pass
|
||||
return result
|
||||
|
||||
def GetAllPlexChildren(self, key):
|
||||
|
@ -1471,10 +1485,12 @@ class PlexAPI():
|
|||
|
||||
def GetPlexMetadata(self, key):
|
||||
"""
|
||||
Returns raw API metadata for key.
|
||||
Returns raw API metadata for key as an etree XML.
|
||||
|
||||
Can be called with either Plex key '/library/metadata/xxxx'metadata
|
||||
OR with the digits 'xxxx' only.
|
||||
|
||||
Returns an empty string '' if something went wrong
|
||||
"""
|
||||
xml = ''
|
||||
key = str(key)
|
||||
|
@ -1495,9 +1511,13 @@ class PlexAPI():
|
|||
url = url + '?' + urlencode(arguments)
|
||||
headerOptions = {'Accept': 'application/xml'}
|
||||
xml = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
|
||||
if not xml:
|
||||
# Did we receive a valid XML?
|
||||
try:
|
||||
xml.tag
|
||||
# Nope we did not receive a valid XML
|
||||
except AttributeError:
|
||||
self.logMsg("Error retrieving metadata for %s" % url, -1)
|
||||
xml = None
|
||||
xml = ''
|
||||
return xml
|
||||
|
||||
|
||||
|
@ -1534,7 +1554,6 @@ class API():
|
|||
Which child in the XML response shall we look at and work with?
|
||||
"""
|
||||
self.child = int(number)
|
||||
self.logMsg("Set child number to %s" % number, 1)
|
||||
|
||||
def getChildNumber(self):
|
||||
"""
|
||||
|
@ -1592,7 +1611,7 @@ class API():
|
|||
def getChecksum(self):
|
||||
"""
|
||||
Can be used on both XML and JSON
|
||||
Returns a string, not int!
|
||||
Returns a string, not int
|
||||
"""
|
||||
item = self.item
|
||||
# XML
|
||||
|
|
|
@ -80,15 +80,12 @@ class PlexCompanion(threading.Thread):
|
|||
message_count += 1
|
||||
|
||||
if message_count > 30:
|
||||
if self.stopped():
|
||||
break
|
||||
if self.client.check_client_registration():
|
||||
self.logMsg("Client is still registered", 1)
|
||||
else:
|
||||
self.logMsg("Client is no longer registered",
|
||||
1)
|
||||
self.logMsg("PlexBMC Helper still running on "
|
||||
"port %s" % self.port, 1)
|
||||
self.logMsg("Client is no longer registered", 1)
|
||||
self.logMsg("PlexBMC Helper still running on port %s"
|
||||
% self.port, 1)
|
||||
message_count = 0
|
||||
|
||||
if not is_running:
|
||||
|
|
|
@ -32,7 +32,7 @@ import embydb_functions
|
|||
#################################################################################################
|
||||
|
||||
|
||||
def plexCompanion(fullurl, resume=""):
|
||||
def plexCompanion(fullurl, resume=None):
|
||||
regex = re.compile(r'''/(\d+)$''')
|
||||
itemid = regex.findall(fullurl)
|
||||
try:
|
||||
|
@ -49,9 +49,12 @@ def plexCompanion(fullurl, resume=""):
|
|||
# Get dbid using itemid
|
||||
dbid = emby.getItem_byId(itemid)[0]
|
||||
embyconn.close()
|
||||
# Fix resume timing
|
||||
if resume:
|
||||
resume = round(float(resume) / 1000.0, 6)
|
||||
# Start playing
|
||||
item = PlexAPI.PlexAPI().GetPlexMetadata(itemid)
|
||||
pbutils.PlaybackUtils(item).play(itemid, dbid)
|
||||
pbutils.PlaybackUtils(item).play(itemid, dbid, seektime=resume)
|
||||
|
||||
|
||||
def doPlayback(itemid, dbid):
|
||||
|
|
|
@ -270,7 +270,7 @@ class Movies(Items):
|
|||
Plex resume points for movies in progress.
|
||||
"""
|
||||
API = PlexAPI.API(itemList)
|
||||
for itemNumber in range(0, len(itemList)):
|
||||
for itemNumber in range(len(itemList)):
|
||||
API.setChildNumber(itemNumber)
|
||||
itemid = API.getKey()
|
||||
# Get key and db entry on the Kodi db side
|
||||
|
@ -890,7 +890,7 @@ class TVShows(Items):
|
|||
Plex resume points for movies in progress.
|
||||
"""
|
||||
API = PlexAPI.API(itemList)
|
||||
for itemNumber in range(0, len(itemList)):
|
||||
for itemNumber in range(len(itemList)):
|
||||
API.setChildNumber(itemNumber)
|
||||
itemid = API.getKey()
|
||||
# Get key and db entry on the Kodi db side
|
||||
|
|
|
@ -64,15 +64,12 @@ class ThreadedGetMetadata(threading.Thread):
|
|||
except:
|
||||
raise
|
||||
# check whether valid XML
|
||||
try:
|
||||
# .tag works for XML
|
||||
plexXML.tag
|
||||
if plexXML:
|
||||
updateItem['XML'] = plexXML
|
||||
# place item into out queue
|
||||
self.out_queue.put(updateItem)
|
||||
# If we don't have a valid XML, don't put that into the queue
|
||||
except AttributeError:
|
||||
pass
|
||||
# but skip this item for now
|
||||
# Keep track of where we are at
|
||||
with self.lock:
|
||||
getMetadataCount += 1
|
||||
|
@ -128,11 +125,9 @@ class ThreadedProcessMetadata(threading.Thread):
|
|||
title = updateItem['title']
|
||||
itemSubFkt = getattr(item, method)
|
||||
with self.lock:
|
||||
itemSubFkt(
|
||||
plexitem,
|
||||
itemSubFkt(plexitem,
|
||||
viewtag=viewName,
|
||||
viewid=viewId
|
||||
)
|
||||
viewid=viewId)
|
||||
# Keep track of where we are at
|
||||
processMetadataCount += 1
|
||||
processingViewName = title
|
||||
|
@ -170,10 +165,8 @@ class ThreadedShowSyncInfo(threading.Thread):
|
|||
total = self.total
|
||||
downloadLock = self.locks[0]
|
||||
processLock = self.locks[1]
|
||||
self.dialog.create(
|
||||
"%s: Sync %s: %s items" % (self.addonName,
|
||||
self.itemType,
|
||||
str(total)),
|
||||
self.dialog.create("%s: Sync %s: %s items"
|
||||
% (self.addonName, self.itemType, str(total)),
|
||||
"Starting")
|
||||
global getMetadataCount
|
||||
global processMetadataCount
|
||||
|
@ -191,11 +184,11 @@ class ThreadedShowSyncInfo(threading.Thread):
|
|||
percentage = int(float(totalProgress) / float(total)*100.0)
|
||||
except ZeroDivisionError:
|
||||
percentage = 0
|
||||
self.dialog.update(
|
||||
percentage,
|
||||
message="Downloaded: %s, Processed: %s: %s" % (
|
||||
getMetadataProgress, processMetadataProgress, viewName)
|
||||
)
|
||||
self.dialog.update(percentage,
|
||||
message="Downloaded: %s, Processed: %s: %s"
|
||||
% (getMetadataProgress,
|
||||
processMetadataProgress, viewName))
|
||||
# Sleep for x milliseconds
|
||||
xbmc.sleep(500)
|
||||
self.dialog.close()
|
||||
|
||||
|
@ -431,8 +424,8 @@ class LibrarySync(threading.Thread):
|
|||
utils.window('emby_initialScan', clear=True)
|
||||
xbmcgui.Dialog().notification(
|
||||
heading=self.addonName,
|
||||
message="%s completed in: %s" %
|
||||
(message, str(elapsedtotal).split('.')[0]),
|
||||
message="%s completed in: %s"
|
||||
% (message, str(elapsedtotal).split('.')[0]),
|
||||
icon="special://home/addons/plugin.video.plexkodiconnect/icon.png",
|
||||
sound=False)
|
||||
return True
|
||||
|
@ -567,22 +560,25 @@ class LibrarySync(threading.Thread):
|
|||
Adds items to self.updatelist as well as self.allPlexElementsId dict
|
||||
|
||||
Input:
|
||||
elementList: List of elements, e.g. a list of '_children'
|
||||
movie elements as received via JSON from PMS
|
||||
elementList: List of elements, e.g. list of '_children'
|
||||
movie elements as received from PMS
|
||||
itemType: 'Movies', 'TVShows', ...
|
||||
method: Method name to be called with this itemtype
|
||||
see itemtypes.py
|
||||
viewName: Name of the Plex view (e.g. 'My TV shows')
|
||||
viewId: Id/Key of Plex library (e.g. '1')
|
||||
|
||||
Output: self.updatelist, self.allPlexElementsId
|
||||
self.updatelist APPENDED(!!) list itemids (Plex Keys as
|
||||
as received from API.getKey())
|
||||
= [
|
||||
{
|
||||
One item in this list is of the form:
|
||||
'itemId': xxx,
|
||||
'itemType': 'Movies'/'TVShows'/...,
|
||||
'itemType': 'Movies','TVShows', ...
|
||||
'method': 'add_update', 'add_updateSeason', ...
|
||||
'viewName': xxx,
|
||||
'viewId': xxx
|
||||
}, ...
|
||||
]
|
||||
self.allPlexElementsId APPENDED(!!) dic
|
||||
|
||||
self.allPlexElementsId APPENDED(!!) dict
|
||||
= {itemid: checksum}
|
||||
"""
|
||||
if self.compare:
|
||||
|
@ -635,6 +631,7 @@ class LibrarySync(threading.Thread):
|
|||
by then calling itemtypes.<itemType>()
|
||||
|
||||
Input:
|
||||
itemType: 'Movies', 'TVShows', ...
|
||||
self.updatelist
|
||||
"""
|
||||
# Some logging, just in case.
|
||||
|
@ -672,7 +669,6 @@ class LibrarySync(threading.Thread):
|
|||
thread.start()
|
||||
threads.append(thread)
|
||||
self.logMsg("%s download threads spawned" % self.syncThreadNumber, 1)
|
||||
self.logMsg("Queue populated", 1)
|
||||
# Spawn one more thread to process Metadata, once downloaded
|
||||
thread = ThreadedProcessMetadata(processMetadataQueue,
|
||||
itemType,
|
||||
|
@ -783,17 +779,17 @@ class LibrarySync(threading.Thread):
|
|||
"""
|
||||
starttotal = datetime.now()
|
||||
plx = PlexAPI.PlexAPI()
|
||||
# Download XML, not JSON
|
||||
# Download XML, not JSON, because PMS JSON seems to be damaged
|
||||
headerOptions = {'Accept': 'application/xml'}
|
||||
plexItems = plx.GetAllPlexLeaves(viewId,
|
||||
headerOptions=headerOptions)
|
||||
itemMth = getattr(itemtypes, itemType)
|
||||
with itemMth() as method:
|
||||
method.UpdateWatched(plexItems)
|
||||
method.updateUserdata(plexItems)
|
||||
|
||||
elapsedtotal = datetime.now() - starttotal
|
||||
self.logMsg("Syncing userdata for itemtype %s and viewid %s took "
|
||||
"%s seconds" % (itemType, viewId, elapsedtotal), 0)
|
||||
"%s seconds" % (itemType, viewId, elapsedtotal), 1)
|
||||
|
||||
def musicvideos(self, embycursor, kodicursor, pdialog):
|
||||
# Get musicvideos from emby
|
||||
|
@ -877,6 +873,7 @@ class LibrarySync(threading.Thread):
|
|||
self.allKodiElementsId.update(all_kodiepisodes)
|
||||
except ValueError:
|
||||
pass
|
||||
# Close DB connections
|
||||
embyconn.close()
|
||||
|
||||
##### PROCESS TV Shows #####
|
||||
|
|
|
@ -47,7 +47,7 @@ class PlaybackUtils():
|
|||
self.className = self.__class__.__name__
|
||||
utils.logMsg("%s %s" % (self.addonName, self.className), msg, lvl)
|
||||
|
||||
def play(self, itemid, dbid=None):
|
||||
def play(self, itemid, dbid=None, seektime=None):
|
||||
|
||||
self.logMsg("Play called.", 1)
|
||||
|
||||
|
@ -89,6 +89,7 @@ class PlaybackUtils():
|
|||
|
||||
############### RESUME POINT ################
|
||||
|
||||
if seektime is None:
|
||||
userdata = API.getUserData()
|
||||
seektime = userdata['Resume']
|
||||
|
||||
|
|
|
@ -200,12 +200,17 @@ class Subscriber:
|
|||
printDebug("sending xml to subscriber %s: %s" % (self.tostr(), msg))
|
||||
url = self.protocol + '://' + self.host + ':' + self.port \
|
||||
+ "/:/timeline"
|
||||
response = self.download.downloadUrl(url,
|
||||
# Override some headers
|
||||
headerOptions = {
|
||||
'Accept': '*/*'
|
||||
}
|
||||
response = self.download.downloadUrl(
|
||||
url,
|
||||
postBody=msg,
|
||||
type="POSTXML")
|
||||
type="POSTXML",
|
||||
headerOptions=headerOptions)
|
||||
# if not requests.post(self.host, self.port, "/:/timeline", msg, getPlexHeaders(), self.protocol):
|
||||
# subMgr.removeSubscriber(self.uuid)
|
||||
if response in [False, 401]:
|
||||
subMgr.removeSubscriber(self.uuid)
|
||||
|
||||
subMgr = SubscriptionManager()
|
||||
|
|
Loading…
Reference in a new issue