jellyfin-kodi/resources/lib/api.py

413 lines
11 KiB
Python
Raw Normal View History

2015-12-24 20:07:00 +00:00
# -*- coding: utf-8 -*-
2016-02-02 01:29:43 +00:00
# Read an api response and convert more complex cases
2015-12-24 20:07:00 +00:00
##################################################################################################
import logging
from utils import settings
import artwork
##################################################################################################
log = logging.getLogger("EMBY."+__name__)
2015-12-24 20:07:00 +00:00
##################################################################################################
2016-09-10 11:15:58 +00:00
class API(object):
2015-12-24 20:07:00 +00:00
def __init__(self, item):
2016-02-02 01:29:43 +00:00
# item is the api response
2015-12-24 20:07:00 +00:00
self.item = item
self.artwork = artwork.Artwork()
2016-02-02 01:29:43 +00:00
2016-09-10 11:15:58 +00:00
def get_userdata(self):
2015-12-24 20:07:00 +00:00
# Default
favorite = False
2016-01-11 18:26:38 +00:00
likes = None
2015-12-24 20:07:00 +00:00
playcount = None
played = False
2016-09-10 11:15:58 +00:00
last_played = None
2015-12-24 20:07:00 +00:00
resume = 0
try:
userdata = self.item['UserData']
except KeyError: # No userdata found.
pass
else:
favorite = userdata['IsFavorite']
likes = userdata.get('Likes')
2016-09-10 11:15:58 +00:00
last_played = userdata.get('LastPlayedDate')
if last_played:
last_played = last_played.split('.')[0].replace('T', " ")
2016-03-31 03:01:37 +00:00
2015-12-24 20:07:00 +00:00
if userdata['Played']:
# Playcount is tied to the watch status
played = True
playcount = userdata['PlayCount']
if playcount == 0:
playcount = 1
2016-09-10 11:15:58 +00:00
if last_played is None:
last_played = self.get_date_created()
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
playback_position = userdata.get('PlaybackPositionTicks')
if playback_position:
resume = playback_position / 10000000.0
2015-12-24 20:07:00 +00:00
return {
'Favorite': favorite,
'Likes': likes,
2015-12-24 20:07:00 +00:00
'PlayCount': playcount,
'Played': played,
2016-09-10 11:15:58 +00:00
'LastPlayedDate': last_played,
'Resume': resume
2015-12-24 20:07:00 +00:00
}
2016-09-10 11:15:58 +00:00
def get_people(self):
2015-12-24 20:07:00 +00:00
# Process People
director = []
writer = []
cast = []
if 'People' in self.item:
for person in self.item['People']:
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
type_ = person['Type']
2015-12-24 20:07:00 +00:00
name = person['Name']
2016-09-10 11:15:58 +00:00
if type_ == 'Director':
2015-12-24 20:07:00 +00:00
director.append(name)
2016-09-10 11:15:58 +00:00
elif type_ == 'Actor':
2015-12-24 20:07:00 +00:00
cast.append(name)
2016-09-10 11:15:58 +00:00
elif type_ in ('Writing', 'Writer'):
2015-12-24 20:07:00 +00:00
writer.append(name)
return {
'Director': director,
'Writer': writer,
'Cast': cast
}
def get_actors(self):
cast = []
if 'People' in self.item:
self.artwork.get_people_artwork(self.item['People'])
for person in self.item['People']:
if person['Type'] == "Actor":
cast.append({
'name': person['Name'],
'role': person['Role'],
'order': len(cast) + 1,
'thumbnail': person['imageurl']
})
return cast
2016-09-10 11:15:58 +00:00
def get_media_streams(self):
video_tracks = []
audio_tracks = []
subtitle_languages = []
2015-12-24 20:07:00 +00:00
try:
2016-03-31 03:01:37 +00:00
media_streams = self.item['MediaSources'][0]['MediaStreams']
2015-12-24 20:07:00 +00:00
except KeyError:
2016-09-10 11:15:58 +00:00
if not self.item.get("MediaStreams"):
return None
2016-03-31 03:01:37 +00:00
media_streams = self.item['MediaStreams']
2015-12-24 20:07:00 +00:00
for media_stream in media_streams:
# Sort through Video, Audio, Subtitle
stream_type = media_stream['Type']
if stream_type == "Video":
2016-09-10 11:15:58 +00:00
self._video_stream(video_tracks, media_stream)
2015-12-24 20:07:00 +00:00
elif stream_type == "Audio":
2016-09-10 11:15:58 +00:00
self._audio_stream(audio_tracks, media_stream)
2016-03-31 03:01:37 +00:00
2016-09-10 11:15:58 +00:00
elif stream_type == "Subtitle":
subtitle_languages.append(media_stream.get('Language', "Unknown"))
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
return {
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
'video': video_tracks,
'audio': audio_tracks,
'subtitle': subtitle_languages
}
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
def _video_stream(self, video_tracks, stream):
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
codec = stream.get('Codec', "").lower()
profile = stream.get('Profile', "").lower()
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
# Height, Width, Codec, AspectRatio, AspectFloat, 3D
track = {
'codec': codec,
'height': stream.get('Height'),
'width': stream.get('Width'),
'video3DFormat': self.item.get('Video3DFormat'),
'aspect': 1.85
2015-12-24 20:07:00 +00:00
}
2016-09-10 11:15:58 +00:00
try:
container = self.item['MediaSources'][0]['Container'].lower()
except Exception:
container = ""
# Sort codec vs container/profile
if "msmpeg4" in codec:
track['codec'] = "divx"
elif "mpeg4" in codec:
if "simple profile" in profile or not profile:
track['codec'] = "xvid"
elif "h264" in codec:
if container in ("mp4", "mov", "m4v"):
track['codec'] = "avc1"
# Aspect ratio
if 'AspectRatio' in self.item:
# Metadata AR
aspect = self.item['AspectRatio']
else: # File AR
aspect = stream.get('AspectRatio', "0")
try:
aspect_width, aspect_height = aspect.split(':')
track['aspect'] = round(float(aspect_width) / float(aspect_height), 6)
except (ValueError, ZeroDivisionError):
width = track.get('width')
height = track.get('height')
if width and height:
track['aspect'] = round(float(width / height), 6)
else:
track['aspect'] = 1.85
if 'RunTimeTicks' in self.item:
track['duration'] = self.get_runtime()
video_tracks.append(track)
def _audio_stream(self, audio_tracks, stream):
codec = stream.get('Codec', "").lower()
profile = stream.get('Profile', "").lower()
# Codec, Channels, language
track = {
'codec': codec,
'channels': stream.get('Channels'),
'language': stream.get('Language')
}
if "dts-hd ma" in profile:
2016-09-10 11:15:58 +00:00
track['codec'] = "dtshd_ma"
if "dts-hd hra" in profile:
track['codec'] = "dtshd_hra"
2016-09-10 11:15:58 +00:00
audio_tracks.append(track)
def get_runtime(self):
2015-12-24 20:07:00 +00:00
try:
2016-03-31 03:01:37 +00:00
runtime = self.item['RunTimeTicks'] / 10000000.0
2015-12-24 20:07:00 +00:00
except KeyError:
2016-03-31 03:01:37 +00:00
runtime = self.item.get('CumulativeRunTimeTicks', 0) / 10000000.0
2015-12-24 20:07:00 +00:00
return runtime
2016-09-10 11:15:58 +00:00
@classmethod
def adjust_resume(cls, resume_seconds):
2015-12-24 20:07:00 +00:00
resume = 0
if resume_seconds:
resume = round(float(resume_seconds), 6)
2016-06-16 05:43:36 +00:00
jumpback = int(settings('resumeJumpBack'))
2015-12-24 20:07:00 +00:00
if resume > jumpback:
# To avoid negative bookmark
resume = resume - jumpback
return resume
2016-09-10 11:15:58 +00:00
def get_studios(self):
2015-12-24 20:07:00 +00:00
# Process Studios
studios = []
try:
2016-03-31 03:01:37 +00:00
studio = self.item['SeriesStudio']
2016-09-10 11:15:58 +00:00
studios.append(self.verify_studio(studio))
2016-03-31 03:01:37 +00:00
2015-12-24 20:07:00 +00:00
except KeyError:
2016-09-10 11:15:58 +00:00
for studio in self.item['Studios']:
2015-12-24 20:07:00 +00:00
name = studio['Name']
2016-09-10 11:15:58 +00:00
studios.append(self.verify_studio(name))
2016-03-31 03:01:37 +00:00
2015-12-24 20:07:00 +00:00
return studios
2016-09-10 11:15:58 +00:00
@classmethod
def verify_studio(cls, studio_name):
2015-12-24 20:07:00 +00:00
# Convert studio for Kodi to properly detect them
studios = {
'abc (us)': "ABC",
'fox (us)': "FOX",
'mtv (us)': "MTV",
'showcase (ca)': "Showcase",
2016-11-05 09:57:03 +00:00
'wgn america': "WGN",
'bravo (us)': "Bravo",
'tnt (us)': "TNT",
'comedy central': "Comedy Central (US)"
2015-12-24 20:07:00 +00:00
}
2016-09-10 11:15:58 +00:00
return studios.get(studio_name.lower(), studio_name)
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
def get_checksum(self):
2015-12-24 20:07:00 +00:00
# Use the etags checksum and userdata
2016-03-31 03:01:37 +00:00
userdata = self.item['UserData']
2015-12-24 20:07:00 +00:00
checksum = "%s%s%s%s%s%s%s" % (
2016-03-31 03:01:37 +00:00
self.item['Etag'],
2015-12-24 20:07:00 +00:00
userdata['Played'],
userdata['IsFavorite'],
2016-09-10 11:15:58 +00:00
userdata.get('Likes', ""),
2015-12-24 20:07:00 +00:00
userdata['PlaybackPositionTicks'],
userdata.get('UnplayedItemCount', ""),
userdata.get('LastPlayedDate', "")
)
return checksum
2016-09-10 11:15:58 +00:00
def get_genres(self):
2015-12-24 20:07:00 +00:00
all_genres = ""
2016-03-31 03:01:37 +00:00
genres = self.item.get('Genres', self.item.get('SeriesGenres'))
2015-12-24 20:07:00 +00:00
if genres:
all_genres = " / ".join(genres)
return all_genres
2016-09-10 11:15:58 +00:00
def get_date_created(self):
2015-12-24 20:07:00 +00:00
try:
2016-09-10 11:15:58 +00:00
date_added = self.item['DateCreated']
date_added = date_added.split('.')[0].replace('T', " ")
2015-12-24 20:07:00 +00:00
except KeyError:
2016-09-10 11:15:58 +00:00
date_added = None
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
return date_added
2015-12-24 20:07:00 +00:00
2016-09-10 11:15:58 +00:00
def get_premiere_date(self):
2015-12-24 20:07:00 +00:00
try:
premiere = self.item['PremiereDate']
premiere = premiere.split('.')[0].replace('T', " ")
except KeyError:
premiere = None
return premiere
2016-09-10 11:15:58 +00:00
def get_overview(self):
2015-12-24 20:07:00 +00:00
try:
overview = self.item['Overview']
overview = overview.replace("\"", "\'")
overview = overview.replace("\n", " ")
overview = overview.replace("\r", " ")
except KeyError:
overview = ""
return overview
2016-09-10 11:15:58 +00:00
def get_tagline(self):
2015-12-24 20:07:00 +00:00
try:
tagline = self.item['Taglines'][0]
except IndexError:
tagline = None
return tagline
2016-09-10 11:15:58 +00:00
def get_provider(self, name):
2015-12-24 20:07:00 +00:00
try:
2016-09-10 11:15:58 +00:00
provider = self.item['ProviderIds'][name]
2015-12-24 20:07:00 +00:00
except KeyError:
provider = None
return provider
2016-09-10 11:15:58 +00:00
def get_mpaa(self):
2015-12-24 20:07:00 +00:00
# Convert more complex cases
mpaa = self.item.get('OfficialRating', "")
2016-03-31 03:01:37 +00:00
2015-12-24 20:07:00 +00:00
if mpaa in ("NR", "UR"):
# Kodi seems to not like NR, but will accept Not Rated
mpaa = "Not Rated"
2016-09-18 06:24:07 +00:00
if "FSK-" in mpaa:
mpaa = mpaa.replace("-", " ")
2015-12-24 20:07:00 +00:00
return mpaa
2016-09-10 11:15:58 +00:00
def get_country(self):
2015-12-24 20:07:00 +00:00
try:
country = self.item['ProductionLocations'][0]
except (IndexError, KeyError):
2015-12-24 20:07:00 +00:00
country = None
return country
2016-09-10 11:15:58 +00:00
def get_file_path(self):
2015-12-24 20:07:00 +00:00
try:
2016-03-31 03:01:37 +00:00
filepath = self.item['Path']
2015-12-24 20:07:00 +00:00
except KeyError:
filepath = ""
else:
if filepath.startswith('\\\\'):
2015-12-24 20:07:00 +00:00
# append smb protocol
filepath = filepath.replace("\\\\", "smb://", 1)
filepath = filepath.replace("\\\\", "\\")
2015-12-24 20:07:00 +00:00
filepath = filepath.replace("\\", "/")
if 'VideoType' in self.item:
if self.item['VideoType'] == "Dvd":
2015-12-24 20:07:00 +00:00
filepath = "%s/VIDEO_TS/VIDEO_TS.IFO" % filepath
elif self.item['VideoType'] == "BluRay":
2015-12-24 20:07:00 +00:00
filepath = "%s/BDMV/index.bdmv" % filepath
2016-03-31 03:01:37 +00:00
# In case user made a mistake with the network share
filepath = filepath.replace("\\\\", "\\")
2015-12-24 20:07:00 +00:00
if "\\" in filepath:
# Local path scenario, with special videotype
filepath = filepath.replace("/", "\\")
2018-01-28 04:25:32 +00:00
if "://" in filepath:
# Protocol needs to be lowercase, otherwise weird things happen.
protocol = filepath.split('://')[0]
filepath = filepath.replace(protocol, protocol.lower())
return filepath