Switched metadata processing from JSON to XML
This commit is contained in:
parent
f2294569e6
commit
3fe10ba851
4 changed files with 210 additions and 91 deletions
|
@ -612,10 +612,10 @@ class PlexAPI():
|
|||
xargs['X-Plex-Product'] = self.addonName
|
||||
xargs['X-Plex-Version'] = self.plexversion
|
||||
xargs['X-Plex-Client-Identifier'] = self.clientId
|
||||
if options:
|
||||
xargs.update(options)
|
||||
if JSON:
|
||||
xargs['Accept'] = 'application/json'
|
||||
if options:
|
||||
xargs.update(options)
|
||||
return xargs
|
||||
|
||||
def getXMLFromMultiplePMS(self, ATV_udid, path, type, options={}):
|
||||
|
@ -1293,19 +1293,28 @@ class PlexAPI():
|
|||
Can be called with either Plex key '/library/metadata/xxxx'metadata
|
||||
OR with the digits 'xxxx' only.
|
||||
"""
|
||||
result = []
|
||||
xml = ''
|
||||
key = str(key)
|
||||
if '/library/metadata/' in key:
|
||||
url = "{server}" + key
|
||||
else:
|
||||
url = "{server}/library/metadata/" + key
|
||||
jsondata = self.doUtils.downloadUrl(url)
|
||||
try:
|
||||
result = jsondata['_children'][0]
|
||||
except KeyError:
|
||||
arguments = {
|
||||
'checkFiles': 1, # No idea
|
||||
'includeExtras': 1, # Trailers and Extras => Extras
|
||||
'includeRelated': 1, # Similar movies => Video -> Related
|
||||
'includeRelatedCount': 5,
|
||||
'includeOnDeck': 1,
|
||||
'includeChapters': 1,
|
||||
'includePopularLeaves': 1,
|
||||
'includeConcerts': 1
|
||||
}
|
||||
url = url + '?' + urllib.urlencode(arguments)
|
||||
headerOptions = {'Accept': 'application/xml'}
|
||||
xml = self.doUtils.downloadUrl(url, headerOptions=headerOptions)
|
||||
if not xml:
|
||||
self.logMsg("Error retrieving metadata for %s" % url, 1)
|
||||
pass
|
||||
return result
|
||||
return xml
|
||||
|
||||
|
||||
class API():
|
||||
|
@ -1345,7 +1354,7 @@ class API():
|
|||
# return localtime + ' ' + localdate
|
||||
DATEFORMAT = xbmc.getRegion('dateshort')
|
||||
TIMEFORMAT = xbmc.getRegion('meridiem')
|
||||
date_time = time.localtime(stamp)
|
||||
date_time = time.localtime(float(stamp))
|
||||
localdate = time.strftime('%Y-%m-%d', date_time)
|
||||
return localdate
|
||||
|
||||
|
@ -1356,6 +1365,12 @@ class API():
|
|||
"""
|
||||
item = self.item
|
||||
# Include a letter to prohibit saving as an int!
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
checksum = "K%s%s%s%s%s" % (
|
||||
self.getKey(),
|
||||
item['updatedAt'],
|
||||
|
@ -1371,11 +1386,24 @@ class API():
|
|||
"""
|
||||
item = self.item
|
||||
key_regex = re.compile(r'/(\d+)$')
|
||||
key = key_regex.findall(item['key'])[0]
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
key = item['key']
|
||||
key = key_regex.findall(key)[0]
|
||||
return str(key)
|
||||
|
||||
def getDateCreated(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
dateadded = item['addedAt']
|
||||
dateadded = self.convert_date(dateadded)
|
||||
|
@ -1393,6 +1421,12 @@ class API():
|
|||
resume = 0
|
||||
rating = 0
|
||||
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
playcount = int(item['viewCount'])
|
||||
except KeyError:
|
||||
|
@ -1423,7 +1457,8 @@ class API():
|
|||
|
||||
def getPeople(self):
|
||||
"""
|
||||
returns a dictionary of lists of people found in item.
|
||||
Input is Plex' XMl
|
||||
Returns a dictionary of lists of people found in item.
|
||||
|
||||
{
|
||||
'Director': list,
|
||||
|
@ -1433,21 +1468,19 @@ class API():
|
|||
}
|
||||
"""
|
||||
item = self.item
|
||||
item = item['_children']
|
||||
# Process People
|
||||
director = []
|
||||
writer = []
|
||||
cast = []
|
||||
producer = []
|
||||
for entry in item:
|
||||
if entry['_elementType'] == 'Director':
|
||||
director.append(entry['tag'])
|
||||
elif entry['_elementType'] == 'Writer':
|
||||
writer.append(entry['tag'])
|
||||
elif entry['_elementType'] == 'Role':
|
||||
cast.append(entry['tag'])
|
||||
elif entry['_elementType'] == 'Producer':
|
||||
producer.append(entry['tag'])
|
||||
for child in item[0]:
|
||||
if child.tag == 'Director':
|
||||
director.append(child.attrib['tag'])
|
||||
elif child.tag == 'Writer':
|
||||
writer.append(child.attrib['tag'])
|
||||
elif child.tag == 'Role':
|
||||
cast.append(child.attrib['tag'])
|
||||
elif child.tag == 'Producer':
|
||||
producer.append(child.attrib['tag'])
|
||||
return {
|
||||
'Director': director,
|
||||
'Writer': writer,
|
||||
|
@ -1462,10 +1495,11 @@ class API():
|
|||
'Name': xxx,
|
||||
'Type': xxx,
|
||||
'Id': xxx
|
||||
'imageurl': url to picture
|
||||
('Role': xxx for cast/actors only)
|
||||
}
|
||||
"""
|
||||
item = self.item['_children']
|
||||
item = self.item
|
||||
people = []
|
||||
# Key of library: Plex-identifier. Value represents the Kodi/emby side
|
||||
people_of_interest = {
|
||||
|
@ -1474,26 +1508,30 @@ class API():
|
|||
'Role': 'Actor',
|
||||
'Producer': 'Producer'
|
||||
}
|
||||
for entry in item:
|
||||
if entry['_elementType'] in people_of_interest.keys():
|
||||
name = entry['tag']
|
||||
name_id = entry['id']
|
||||
Type = entry['_elementType']
|
||||
for child in item[0]:
|
||||
if child.tag in people_of_interest.keys():
|
||||
name = child.attrib['tag']
|
||||
name_id = child.attrib['id']
|
||||
Type = child.tag
|
||||
Type = people_of_interest[Type]
|
||||
if Type == 'Actor':
|
||||
Role = entry['role']
|
||||
people.append({
|
||||
'Name': name,
|
||||
'Type': Type,
|
||||
'Id': name_id,
|
||||
'Role': Role
|
||||
})
|
||||
else:
|
||||
people.append({
|
||||
'Name': name,
|
||||
'Type': Type,
|
||||
'Id': name_id
|
||||
})
|
||||
try:
|
||||
url = child.attrib['thumb']
|
||||
except KeyError:
|
||||
url = None
|
||||
try:
|
||||
Role = child.attrib['role']
|
||||
except KeyError:
|
||||
Role = None
|
||||
people.append({
|
||||
'Name': name,
|
||||
'Type': Type,
|
||||
'Id': name_id,
|
||||
'imageurl': url
|
||||
})
|
||||
if url:
|
||||
people[-1].update({'imageurl': url})
|
||||
if Role:
|
||||
people[-1].update({'Role': Role})
|
||||
return people
|
||||
|
||||
def getGenres(self):
|
||||
|
@ -1501,11 +1539,10 @@ class API():
|
|||
returns a list of genres found in item. (Not a string!!)
|
||||
"""
|
||||
item = self.item
|
||||
item = item['_children']
|
||||
genre = []
|
||||
for entry in item:
|
||||
if entry['_elementType'] == 'Genre':
|
||||
genre.append(entry['tag'])
|
||||
for child in item[0]:
|
||||
if child.tag == 'Genre':
|
||||
genre.append(child.attrib['tag'])
|
||||
return genre
|
||||
|
||||
def getProvider(self, providername):
|
||||
|
@ -1518,6 +1555,12 @@ class API():
|
|||
Return IMDB: "tt1234567"
|
||||
"""
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
imdb_regex = re.compile(r'''(
|
||||
imdb:// # imdb tag, which will be followed be tt1234567
|
||||
(tt\d{7}) # actual IMDB ID, e.g. tt1234567
|
||||
|
@ -1540,8 +1583,14 @@ class API():
|
|||
provider = None
|
||||
return provider
|
||||
|
||||
def GetTitle(self):
|
||||
def getTitle(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
title = item['title']
|
||||
try:
|
||||
sorttitle = item['titleSort']
|
||||
|
@ -1549,6 +1598,56 @@ class API():
|
|||
sorttitle = title
|
||||
return title, sorttitle
|
||||
|
||||
def getPlot(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
plot = item['summary']
|
||||
return plot
|
||||
|
||||
def getTagline(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
tagline = item['tagline']
|
||||
except KeyError:
|
||||
tagline = None
|
||||
return tagline
|
||||
|
||||
def getAudienceRating(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
rating = item['audienceRating']
|
||||
except:
|
||||
rating = None
|
||||
return rating
|
||||
|
||||
def getYear(self):
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
year = item['year']
|
||||
return year
|
||||
|
||||
def getRuntime(self):
|
||||
"""
|
||||
Resume point of time and runtime/totaltime. Rounded to 6th decimal.
|
||||
|
@ -1557,10 +1656,16 @@ class API():
|
|||
milliseconds on the Plex side and in seconds on the Kodi side.
|
||||
"""
|
||||
item = self.item
|
||||
time_factor = 1/1000
|
||||
runtime = item['duration'] * time_factor
|
||||
# xml
|
||||
try:
|
||||
resume = item['viewOffset'] * time_factor
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
time_factor = 1/1000
|
||||
runtime = int(item['duration']) * time_factor
|
||||
try:
|
||||
resume = int(item['viewOffset']) * time_factor
|
||||
except KeyError:
|
||||
resume = 0
|
||||
resume = round(float(resume), 6)
|
||||
|
@ -1570,6 +1675,12 @@ class API():
|
|||
def getMpaa(self):
|
||||
# Convert more complex cases
|
||||
item = self.item
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
mpaa = item['contentRating']
|
||||
except KeyError:
|
||||
|
@ -1584,16 +1695,21 @@ class API():
|
|||
Returns a list of all countries found in item.
|
||||
"""
|
||||
item = self.item
|
||||
item = item['_children']
|
||||
country = []
|
||||
for entry in item:
|
||||
if entry['_elementType'] == 'Country':
|
||||
country.append(entry['tag'])
|
||||
for child in item[0]:
|
||||
if child.tag == 'Country':
|
||||
country.append(child.attrib['tag'])
|
||||
return country
|
||||
|
||||
def getStudios(self):
|
||||
item = self.item
|
||||
studio = []
|
||||
# xml
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
studio.append(self.getStudio(item['studio']))
|
||||
except KeyError:
|
||||
|
@ -1621,9 +1737,13 @@ class API():
|
|||
|
||||
def getFilePath(self):
|
||||
item = self.item
|
||||
try:
|
||||
item = item[0].attrib
|
||||
# json
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
filepath = item['key']
|
||||
|
||||
except KeyError:
|
||||
filepath = ""
|
||||
|
||||
|
@ -1656,28 +1776,23 @@ class API():
|
|||
|
||||
def getMediaStreams(self):
|
||||
item = self.item
|
||||
item = item['_children']
|
||||
videotracks = []
|
||||
audiotracks = []
|
||||
subtitlelanguages = []
|
||||
|
||||
MediaStreams = []
|
||||
aspectratio = None
|
||||
for entry in item:
|
||||
if entry['_elementType'] == 'Media':
|
||||
MediaStreams.append(entry)
|
||||
try:
|
||||
aspectratio = entry['aspectRatio']
|
||||
except KeyError:
|
||||
pass
|
||||
# Abort if no Media found
|
||||
if not MediaStreams:
|
||||
return
|
||||
try:
|
||||
aspectratio = item[0][0].attrib['aspectRatio']
|
||||
except KeyError:
|
||||
pass
|
||||
# Loop over parts:
|
||||
# TODO: what if several Media tags exist?!?
|
||||
for part in MediaStreams[0]['_children']:
|
||||
# Loop over parts
|
||||
for child in item[0][0]:
|
||||
part = child.attrib
|
||||
container = part['container'].lower()
|
||||
for mediaStream in part['_children']:
|
||||
# Loop over Streams
|
||||
for grandchild in child:
|
||||
mediaStream = grandchild.attrib
|
||||
try:
|
||||
type = mediaStream['streamType']
|
||||
except KeyError:
|
||||
|
@ -1737,8 +1852,6 @@ class API():
|
|||
server = self.server
|
||||
item = self.item
|
||||
|
||||
id = item['key']
|
||||
|
||||
maxHeight = 10000
|
||||
maxWidth = 10000
|
||||
customquery = ""
|
||||
|
@ -1762,6 +1875,7 @@ class API():
|
|||
|
||||
# Process backdrops
|
||||
# Get background artwork URL
|
||||
item = item[0].attrib
|
||||
try:
|
||||
background = item['art']
|
||||
background = "%s%s" % (server, background)
|
||||
|
|
|
@ -13,6 +13,10 @@ import utils
|
|||
import clientinfo
|
||||
|
||||
import PlexAPI
|
||||
try:
|
||||
import xml.etree.cElementTree as etree
|
||||
except ImportError:
|
||||
import xml.etree.ElementTree as etree
|
||||
|
||||
##################################################################################################
|
||||
|
||||
|
@ -205,16 +209,16 @@ class DownloadUtils():
|
|||
# Replace for the real values
|
||||
url = url.replace("{server}", self.server)
|
||||
url = url.replace("{UserId}", self.userId)
|
||||
|
||||
header = self.getHeader(options=headerOptions)
|
||||
# Prepare request
|
||||
if type == "GET":
|
||||
r = s.get(url, json=postBody, params=parameters, timeout=timeout)
|
||||
r = s.get(url, json=postBody, params=parameters, timeout=timeout, headers=header)
|
||||
elif type == "POST":
|
||||
r = s.post(url, json=postBody, timeout=timeout)
|
||||
r = s.post(url, json=postBody, timeout=timeout, headers=header)
|
||||
elif type == "DELETE":
|
||||
r = s.delete(url, json=postBody, timeout=timeout)
|
||||
r = s.delete(url, json=postBody, timeout=timeout, headers=header)
|
||||
elif type == "OPTIONS":
|
||||
r = s.options(url, json=postBody, timeout=timeout)
|
||||
r = s.options(url, json=postBody, timeout=timeout, headers=header)
|
||||
|
||||
except AttributeError:
|
||||
# request session does not exists
|
||||
|
@ -317,12 +321,15 @@ class DownloadUtils():
|
|||
return r
|
||||
|
||||
except:
|
||||
# Allow for xml responses, but do not process them
|
||||
if 'xml' in r.headers.get('content-type'):
|
||||
self.logMsg("Received an XML response for: %s" % url, 1)
|
||||
return 'xml'
|
||||
elif r.headers.get('content-type') != "text/html":
|
||||
# Allow for xml responses
|
||||
try:
|
||||
r = etree.fromstring(r.content)
|
||||
self.logMsg("====== 200 Success ======", 2)
|
||||
self.logMsg("Received an XML response for: %s" % url, 2)
|
||||
return r
|
||||
except:
|
||||
self.logMsg("Unable to convert the response for: %s" % url, 1)
|
||||
self.logMsg("Content-type was: %s" % r.headers['content-type'], 1)
|
||||
else:
|
||||
r.raise_for_status()
|
||||
|
||||
|
|
|
@ -309,13 +309,13 @@ class Movies(Items):
|
|||
writer = API.joinList(people['Writer'])
|
||||
director = API.joinList(people['Director'])
|
||||
genres = API.getGenres()
|
||||
title, sorttitle = API.GetTitle()
|
||||
plot = item.get('summary', None)
|
||||
title, sorttitle = API.getTitle()
|
||||
plot = API.getPlot()
|
||||
shortplot = None
|
||||
tagline = item.get('tagline', None)
|
||||
tagline = API.getTagline()
|
||||
votecount = None
|
||||
rating = item.get('audienceRating', None)
|
||||
year = item.get('year', None)
|
||||
rating = API.getAudienceRating()
|
||||
year = API.getYear()
|
||||
imdb = API.getProvider('Imdb')
|
||||
resume, runtime = API.getRuntime()
|
||||
mpaa = API.getMpaa()
|
||||
|
@ -438,8 +438,6 @@ class Movies(Items):
|
|||
kodi_db.addCountries(movieid, countries, "movie")
|
||||
# Process cast
|
||||
people = API.getPeopleList()
|
||||
# TODO: get IMDB pictures?
|
||||
people = artwork.getPeopleArtwork(people)
|
||||
kodi_db.addPeople(movieid, people, "movie")
|
||||
# Process genres
|
||||
kodi_db.addGenres(movieid, genres, "movie")
|
||||
|
|
|
@ -543,7 +543,7 @@ class LibrarySync(threading.Thread):
|
|||
# Process individual movies
|
||||
if self.shouldStop():
|
||||
return False
|
||||
title = plexmovie['title']
|
||||
title = plexmovie[0].attrib['title']
|
||||
if pdialog:
|
||||
percentage = int((float(count) / float(total))*100)
|
||||
pdialog.update(percentage, message=title)
|
||||
|
|
Loading…
Reference in a new issue