Merge pull request #32 from mcarlton00/json-payloads

Proper API json parsing
This commit is contained in:
mcarlton00
2020-11-15 14:44:11 -05:00
committed by GitHub
9 changed files with 138 additions and 173 deletions

View File

@@ -1,7 +1,6 @@
# Gnu General Public License - see LICENSE.TXT
from __future__ import division, absolute_import, print_function, unicode_literals
import json
from collections import defaultdict
import threading
import hashlib
@@ -47,15 +46,9 @@ class DataManager:
# log.debug("DataManager __init__")
pass
@staticmethod
def load_json_data(json_data):
return json.loads(json_data, object_hook=lambda d: defaultdict(lambda: None, d))
@timer
def get_content(self, url):
json_data = DownloadUtils().download_url(url)
result = self.load_json_data(json_data)
return result
return DownloadUtils().download_url(url)
@timer
def get_items(self, url, gui_options, use_cache=False):

View File

@@ -337,7 +337,6 @@ class DownloadUtils:
log.debug("PlaybackInfo : {0}".format(url))
log.debug("PlaybackInfo : {0}".format(profile))
play_info_result = self.download_url(url, post_body=playback_info, method="POST")
play_info_result = json.loads(play_info_result)
log.debug("PlaybackInfo : {0}".format(play_info_result))
return play_info_result
@@ -393,25 +392,25 @@ class DownloadUtils:
# for episodes always use the parent BG
if item_type == "Episode" and art_type == "Backdrop":
item_id = data["ParentBackdropItemId"]
bg_item_tags = data["ParentBackdropImageTags"]
if bg_item_tags is not None and len(bg_item_tags) > 0:
item_id = data.get("ParentBackdropItemId")
bg_item_tags = data.get("ParentBackdropImageTags", [])
if bg_item_tags:
image_tag = bg_item_tags[0]
elif art_type == "Backdrop" and parent is True:
item_id = data["ParentBackdropItemId"]
bg_item_tags = data["ParentBackdropImageTags"]
if bg_item_tags is not None and len(bg_item_tags) > 0:
item_id = data.get("ParentBackdropItemId")
bg_item_tags = data.get("ParentBackdropImageTags", [])
if bg_item_tags:
image_tag = bg_item_tags[0]
elif art_type == "Backdrop":
bg_tags = data["BackdropImageTags"]
if bg_tags is not None and len(bg_tags) > index:
bg_tags = data.get("BackdropImageTags", [])
if bg_tags:
image_tag = bg_tags[index]
# log.debug("Background Image Tag: {0}", imageTag)
elif parent is False:
image_tags = data["ImageTags"]
if image_tags is not None:
image_tag_type = image_tags[art_type]
if image_tag_type is not None:
image_tags = data.get("ImageTags", [])
if image_tags:
image_tag_type = image_tags.get(art_type)
if image_tag_type:
image_tag = image_tag_type
# log.debug("Image Tag: {0}", imageTag)
elif parent is True:
@@ -421,8 +420,8 @@ class DownloadUtils:
else:
tag_name = 'Parent%sImageTag' % art_type
id_name = 'Parent%sItemId' % art_type
parent_image_id = data[id_name]
parent_image_tag = data[tag_name]
parent_image_id = data.get(id_name)
parent_image_tag = data.get(tag_name)
if parent_image_id is not None and parent_image_tag is not None:
item_id = parent_image_id
image_tag = parent_image_tag
@@ -499,20 +498,14 @@ class DownloadUtils:
log.debug("Looking for user name: {0}".format(user_name))
try:
json_data = self.download_url("{server}/Users/Public?format=json", suppress=True, authenticate=False)
result = self.download_url("{server}/Users/Public?format=json", suppress=True, authenticate=False)
except Exception as msg:
log.error("Get User unable to connect: {0}".format(msg))
return ""
log.debug("GETUSER_JSONDATA_01: {0}".format(py2_decode(json_data)))
log.debug("GETUSER_JSONDATA_01: {0}".format(py2_decode(result)))
try:
result = json.loads(json_data)
except Exception as e:
log.debug("Could not load user data: {0}".format(e))
return ""
if result is None:
if not result:
return ""
log.debug("GETUSER_JSONDATA_02: {0}".format(result))
@@ -573,18 +566,13 @@ class DownloadUtils:
message_data = "username=" + user_name + "&pw=" + pwd_text
resp = self.download_url(url, post_body=message_data, method="POST", suppress=True, authenticate=False)
log.debug("AuthenticateByName: {0}".format(resp))
result = self.download_url(url, post_body=message_data, method="POST", suppress=True, authenticate=False)
log.debug("AuthenticateByName: {0}".format(result))
access_token = None
userid = None
try:
result = json.loads(resp)
access_token = result.get("AccessToken")
# userid = result["SessionInfo"].get("UserId")
userid = result["User"].get("Id")
except:
pass
access_token = result.get("AccessToken")
userid = result["User"].get("Id")
if access_token is not None:
log.debug("User Authenticated: {0}".format(access_token))
@@ -650,7 +638,7 @@ class DownloadUtils:
http_timeout = int(settings.getSetting("http_timeout"))
if authenticate and username == "":
return "null"
return {}
if settings.getSetting("suppressErrors") == "true":
suppress = True
@@ -660,13 +648,13 @@ class DownloadUtils:
if url.find("{server}") != -1:
server = self.get_server()
if server is None:
return "null"
return {}
url = url.replace("{server}", server)
if url.find("{userid}") != -1:
userid = self.get_user_id()
if not userid:
return "null"
return {}
url = url.replace("{userid}", userid)
if url.find("{ItemLimit}") != -1:
@@ -681,7 +669,7 @@ class DownloadUtils:
home_window = HomeWindow()
random_movies = home_window.get_property("random-movies")
if not random_movies:
return "null"
return {}
url = url.replace("{random_movies}", random_movies)
log.debug("After: {0}".format(url))
@@ -741,7 +729,11 @@ class DownloadUtils:
xbmcgui.Dialog().notification(string_load(30316),
string_load(30200) % str(data.content),
icon="special://home/addons/plugin.video.jellycon/icon.png")
return data.content or "null"
try:
result = data.json()
except:
result = {}
return result
except Exception as msg:
log.error("{0}".format(format_exc()))
log.error("Unable to connect to {0} : {1}".format(server, msg))

View File

@@ -281,8 +281,7 @@ def unmark_item_favorite(item_id):
def delete(item_id):
json_data = downloadUtils.download_url("{server}/Users/{userid}/Items/" + item_id + "?format=json")
item = json.loads(json_data)
item = downloadUtils.download_url("{server}/Users/{userid}/Items/" + item_id + "?format=json")
item_id = item.get("Id")
item_name = item.get("Name", "")
@@ -578,8 +577,7 @@ def show_menu(params):
elif selected_action == "safe_delete":
url = "{server}/jellyfin_safe_delete/delete_item/" + item_id
delete_action = downloadUtils.download_url(url)
result = json.loads(delete_action)
result = downloadUtils.download_url(url)
dialog = xbmcgui.Dialog()
if result:
log.debug("Safe_Delete_Action: {0}".format(result))
@@ -622,11 +620,10 @@ def show_menu(params):
}
delete_action = downloadUtils.download_url(url, method="POST", post_body=playback_info)
log.debug("Delete result action: {0}".format(delete_action))
delete_action_result = json.loads(delete_action)
if not delete_action_result:
if not delete_action:
dialog.ok("Error", "Error deleting files", "Error in responce from server")
elif not delete_action_result["result"]:
dialog.ok("Error", "Error deleting files", delete_action_result["message"])
elif not delete_action.get("result"):
dialog.ok("Error", "Error deleting files", delete_action["message"])
else:
dialog.ok("Deleted", "Files deleted")
else:
@@ -690,8 +687,7 @@ def populate_listitem(item_id):
log.debug("populate_listitem: {0}".format(item_id))
url = "{server}/Users/{userid}/Items/" + item_id + "?format=json"
json_data = downloadUtils.download_url(url)
result = json.loads(json_data)
result = downloadUtils.download_url(url)
log.debug("populate_listitem item info: {0}".format(result))
item_title = result.get("Name", string_load(30280))
@@ -989,8 +985,7 @@ def play_item_trailer(item_id):
url = ("{server}/Users/{userid}/Items/%s/LocalTrailers?format=json" % item_id)
json_data = downloadUtils.download_url(url)
result = json.loads(json_data)
result = downloadUtils.download_url(url)
if result is None:
return
@@ -1014,8 +1009,7 @@ def play_item_trailer(item_id):
trailer_list.append(info)
url = ("{server}/Users/{userid}/Items/%s?format=json&Fields=RemoteTrailers" % item_id)
json_data = downloadUtils.download_url(url)
result = json.loads(json_data)
result = downloadUtils.download_url(url)
log.debug("RemoteTrailers: {0}".format(result))
count = 1

View File

@@ -101,27 +101,27 @@ def extract_item_info(item, gui_options):
item_details = ItemDetails()
item_details.id = item["Id"]
item_details.etag = item["Etag"]
item_details.is_folder = item["IsFolder"]
item_details.item_type = item["Type"]
item_details.location_type = item["LocationType"]
item_details.name = item["Name"]
item_details.sort_name = item["SortName"]
item_details.id = item.get("Id")
item_details.etag = item.get("Etag")
item_details.is_folder = item.get("IsFolder")
item_details.item_type = item.get("Type")
item_details.location_type = item.get("LocationType")
item_details.name = item.get("Name")
item_details.sort_name = item.get("SortName")
item_details.original_title = item_details.name
if item_details.item_type == "Episode":
item_details.episode_number = item["IndexNumber"]
item_details.season_number = item["ParentIndexNumber"]
item_details.series_id = item["SeriesId"]
item_details.episode_number = item.get("IndexNumber")
item_details.season_number = item.get("ParentIndexNumber")
item_details.series_id = item.get("SeriesId")
if item_details.season_number != 0:
item_details.season_sort_number = item_details.season_number
item_details.episode_sort_number = item_details.episode_number
else:
special_after_season = item["AirsAfterSeasonNumber"]
special_before_season = item["AirsBeforeSeasonNumber"]
special_before_episode = item["AirsBeforeEpisodeNumber"]
special_after_season = item.get("AirsAfterSeasonNumber")
special_before_season = item.get("AirsBeforeSeasonNumber")
special_before_episode = item.get("AirsBeforeEpisodeNumber")
if special_after_season:
item_details.season_sort_number = special_after_season + 1
@@ -132,21 +132,21 @@ def extract_item_info(item, gui_options):
item_details.episode_sort_number = special_before_episode - 1
elif item_details.item_type == "Season":
item_details.season_number = item["IndexNumber"]
item_details.series_id = item["SeriesId"]
item_details.season_number = item.get("IndexNumber")
item_details.series_id = item.get("SeriesId")
elif item_details.item_type == "Series":
item_details.status = item["Status"]
item_details.status = item.get("Status")
elif item_details.item_type == "Audio":
item_details.track_number = item["IndexNumber"]
item_details.album_name = item["Album"]
artists = item["Artists"]
if artists is not None and len(artists) > 0:
item_details.track_number = item.get("IndexNumber")
item_details.album_name = item.get("Album")
artists = item.get("Artists", [])
if artists:
item_details.song_artist = artists[0] # get first artist
elif item_details.item_type == "MusicAlbum":
item_details.album_artist = item["AlbumArtist"]
item_details.album_artist = item.get("AlbumArtist")
item_details.album_name = item_details.name
if item_details.season_number is None:
@@ -154,23 +154,23 @@ def extract_item_info(item, gui_options):
if item_details.episode_number is None:
item_details.episode_number = 0
if item["Taglines"] is not None and len(item["Taglines"]) > 0:
item_details.tagline = item["Taglines"][0]
if item.get("Taglines", []):
item_details.tagline = item.get("Taglines")[0]
item_details.tags = []
if item["TagItems"] is not None and len(item["TagItems"]) > 0:
for tag_info in item["TagItems"]:
item_details.tags.append(tag_info["Name"])
if item.get("TagItems", []):
for tag_info in item.get("TagItems"):
item_details.tags.append(tag_info.get("Name"))
# set the item name
# override with name format string from request
name_format = gui_options["name_format"]
name_format_type = gui_options["name_format_type"]
name_format = gui_options.get("name_format")
name_format_type = gui_options.get("name_format_type")
if name_format is not None and item_details.item_type == name_format_type:
name_info = {}
name_info["ItemName"] = item["Name"]
season_name = item["SeriesName"]
name_info["ItemName"] = item.get("Name")
season_name = item.get("SeriesName")
if season_name:
name_info["SeriesName"] = season_name
else:
@@ -180,8 +180,8 @@ def extract_item_info(item, gui_options):
log.debug("FormatName: {0} | {1}".format(name_format, name_info))
item_details.name = unicode(name_format).format(**name_info).strip()
year = item["ProductionYear"]
prem_date = item["PremiereDate"]
year = item.get("ProductionYear")
prem_date = item.get("PremiereDate")
if year is not None:
item_details.year = year
@@ -192,35 +192,35 @@ def extract_item_info(item, gui_options):
tokens = prem_date.split("T")
item_details.premiere_date = tokens[0]
create_date = item["DateCreated"]
if create_date is not None:
create_date = item.get("DateCreated")
if create_date:
item_details.date_added = create_date.split('.')[0].replace('T', " ")
# add the premiered date for Upcoming TV
if item_details.location_type == "Virtual":
airtime = item["AirTime"]
airtime = item.get("AirTime")
item_details.name = item_details.name + ' - ' + item_details.premiere_date + ' - ' + str(airtime)
if item_details.item_type == "Program":
item_details.program_channel_name = item["ChannelName"]
item_details.program_start_date = item["StartDate"]
item_details.program_end_date = item["EndDate"]
item_details.program_channel_name = item.get("ChannelName")
item_details.program_start_date = item.get("StartDate")
item_details.program_end_date = item.get("EndDate")
# Process MediaStreams
media_streams = item["MediaStreams"]
if media_streams is not None:
media_streams = item.get("MediaStreams", [])
if media_streams:
media_info_list = []
for mediaStream in media_streams:
stream_type = mediaStream["Type"]
stream_type = mediaStream.get("Type")
if stream_type == "Video":
media_info = {}
media_info["type"] = "video"
media_info["codec"] = mediaStream["Codec"]
media_info["height"] = mediaStream["Height"]
media_info["width"] = mediaStream["Width"]
aspect_ratio = mediaStream["AspectRatio"]
media_info["codec"] = mediaStream.get("Codec")
media_info["height"] = mediaStream.get("Height")
media_info["width"] = mediaStream.get("Width")
aspect_ratio = mediaStream.get("AspectRatio")
media_info["apect"] = aspect_ratio
if aspect_ratio is not None and len(aspect_ratio) >= 3:
if aspect_ratio and len(aspect_ratio) >= 3:
try:
aspect_width, aspect_height = aspect_ratio.split(':')
media_info["apect_ratio"] = float(aspect_width) / float(aspect_height)
@@ -232,36 +232,36 @@ def extract_item_info(item, gui_options):
if stream_type == "Audio":
media_info = {}
media_info["type"] = "audio"
media_info["codec"] = mediaStream["Codec"]
media_info["channels"] = mediaStream["Channels"]
media_info["language"] = mediaStream["Language"]
media_info["codec"] = mediaStream.get("Codec")
media_info["channels"] = mediaStream.get("Channels")
media_info["language"] = mediaStream.get("Language")
media_info_list.append(media_info)
if stream_type == "Subtitle":
item_details.subtitle_available = True
media_info = {}
media_info["type"] = "sub"
media_info["language"] = mediaStream["Language"]
media_info["language"] = mediaStream.get("Language", '')
media_info_list.append(media_info)
item_details.media_streams = media_info_list
# Process People
people = item["People"]
people = item.get("People", [])
if people is not None:
cast = []
for person in people:
person_type = person["Type"]
person_type = person.get("Type")
if person_type == "Director":
item_details.director = item_details.director + person["Name"] + ' '
item_details.director = item_details.director + person.get("Name") + ' '
elif person_type == "Writing":
item_details.writer = person["Name"]
elif person_type == "Actor":
# log.debug("Person: {0}", person)
person_name = person["Name"]
person_role = person["Role"]
person_id = person["Id"]
person_tag = person["PrimaryImageTag"]
if person_tag is not None:
person_name = person.get("Name")
person_role = person.get("Role")
person_id = person.get("Id")
person_tag = person.get("PrimaryImageTag")
if person_tag:
person_thumbnail = download_utils.image_url(person_id,
"Primary", 0, 400, 400,
person_tag,
@@ -273,64 +273,62 @@ def extract_item_info(item, gui_options):
item_details.cast = cast
# Process Studios
studios = item["Studios"]
studios = item.get("Studios", [])
if studios is not None:
for studio in studios:
if item_details.studio is None: # Just take the first one
studio_name = studio["Name"]
studio_name = studio.get("Name")
item_details.studio = studio_name
break
# production location
prod_location = item["ProductionLocations"]
prod_location = item.get("ProductionLocations", [])
# log.debug("ProductionLocations : {0}", prod_location)
if prod_location and len(prod_location) > 0:
if prod_location:
item_details.production_location = prod_location[0]
# Process Genres
genres = item["Genres"]
if genres is not None and len(genres) > 0:
genres = item.get("Genres", [])
if genres:
item_details.genres = genres
# Process UserData
user_data = item["UserData"]
if user_data is None:
user_data = defaultdict(lambda: None, {})
user_data = item.get("UserData", {})
if user_data["Played"] is True:
if user_data.get("Played"):
item_details.overlay = "6"
item_details.play_count = 1
else:
item_details.overlay = "7"
item_details.play_count = 0
if user_data["IsFavorite"] is True:
if user_data.get("IsFavorite"):
item_details.overlay = "5"
item_details.favorite = "true"
else:
item_details.favorite = "false"
reasonable_ticks = user_data["PlaybackPositionTicks"]
if reasonable_ticks is not None:
reasonable_ticks = user_data.get("PlaybackPositionTicks", 0)
if reasonable_ticks:
reasonable_ticks = int(reasonable_ticks) / 1000
item_details.resume_time = int(reasonable_ticks / 10000)
item_details.series_name = item["SeriesName"]
item_details.plot = item["Overview"]
item_details.series_name = item.get("SeriesName", '')
item_details.plot = item.get("Overview", '')
runtime = item["RunTimeTicks"]
if item_details.is_folder is False and runtime is not None:
runtime = item.get("RunTimeTicks")
if item_details.is_folder is False and runtime:
item_details.duration = long(runtime) / 10000000
child_count = item["ChildCount"]
if child_count is not None:
child_count = item.get("ChildCount")
if child_count:
item_details.total_seasons = child_count
recursive_item_count = item["RecursiveItemCount"]
if recursive_item_count is not None:
recursive_item_count = item.get("RecursiveItemCount")
if recursive_item_count:
item_details.total_episodes = recursive_item_count
unplayed_item_count = user_data["UnplayedItemCount"]
unplayed_item_count = user_data.get("UnplayedItemCount")
if unplayed_item_count is not None:
item_details.unwatched_episodes = unplayed_item_count
item_details.watched_episodes = item_details.total_episodes - unplayed_item_count
@@ -338,20 +336,20 @@ def extract_item_info(item, gui_options):
item_details.number_episodes = item_details.total_episodes
item_details.art = get_art(item, gui_options["server"])
item_details.rating = item["OfficialRating"]
item_details.mpaa = item["OfficialRating"]
item_details.rating = item.get("OfficialRating")
item_details.mpaa = item.get("OfficialRating")
item_details.community_rating = item["CommunityRating"]
if item_details.community_rating is None:
item_details.community_rating = item.get("CommunityRating")
if not item_details.community_rating:
item_details.community_rating = 0.0
item_details.critic_rating = item["CriticRating"]
if item_details.critic_rating is None:
item_details.critic_rating = item.get("CriticRating")
if not item_details.critic_rating:
item_details.critic_rating = 0.0
item_details.location_type = item["LocationType"]
item_details.recursive_item_count = item["RecursiveItemCount"]
item_details.recursive_unplayed_items_count = user_data["UnplayedItemCount"]
item_details.location_type = item.get("LocationType")
item_details.recursive_item_count = item.get("RecursiveItemCount")
item_details.recursive_unplayed_items_count = user_data.get("UnplayedItemCount")
item_details.mode = "GET_CONTENT"
@@ -498,7 +496,7 @@ def add_gui_item(url, item_details, display_options, folder=True, default_sort=F
info_labels["rating"] = item_details.rating
info_labels["year"] = item_details.year
if item_details.genres is not None and len(item_details.genres) > 0:
if item_details.genres:
genres_list = []
for genre in item_details.genres:
genres_list.append(urllib.quote(genre.encode('utf8')))

View File

@@ -3,7 +3,6 @@
from __future__ import division, absolute_import, print_function, unicode_literals
import sys
import json
import urllib
import base64
import string

View File

@@ -100,9 +100,8 @@ def check_safe_delete_available():
log.debug("check_safe_delete_available")
du = DownloadUtils()
json_data = du.download_url("{server}/Plugins")
result = json.loads(json_data)
if result is not None:
result = du.download_url("{server}/Plugins")
if result:
log.debug("Server Plugin List: {0}".format(result))
safe_delete_found = False
@@ -234,11 +233,10 @@ def check_server(force=False, change_user=False, notify=False):
progress = xbmcgui.DialogProgress()
progress.create(__addon_name__ + " : " + string_load(30376))
progress.update(0, string_load(30377))
json_data = du.download_url(public_lookup_url, authenticate=False)
result = du.download_url(public_lookup_url, authenticate=False)
progress.close()
result = json.loads(json_data)
if result is not None:
if result:
xbmcgui.Dialog().ok(__addon_name__ + " : " + string_load(30167),
server_url)
break
@@ -268,15 +266,11 @@ def check_server(force=False, change_user=False, notify=False):
# get a list of users
log.debug("Getting user list")
json_data = du.download_url(server_url + "/Users/Public?format=json", authenticate=False)
result = du.download_url(server_url + "/Users/Public?format=json", authenticate=False)
log.debug("jsonData: {0}".format(py2_decode(json_data)))
try:
result = json.loads(json_data)
except:
result = None
log.debug("jsonData: {0}".format(py2_decode(result)))
if result is None:
if not result:
xbmcgui.Dialog().ok(string_load(30135),
string_load(30201),
string_load(30169) + server_url)

View File

@@ -1,6 +1,5 @@
from __future__ import division, absolute_import, print_function, unicode_literals
import json
import sys
import xbmcgui
import xbmcplugin

View File

@@ -220,8 +220,8 @@ def get_art(item, server):
'tvshow.landscape': ''
}
image_tags = item["ImageTags"]
if image_tags is not None and image_tags["Primary"] is not None:
image_tags = item.get("ImageTags", {})
if image_tags and image_tags.get("Primary"):
# image_tag = image_tags["Primary"]
art['thumb'] = downloadUtils.get_artwork(item, "Primary", server=server)

View File

@@ -45,7 +45,6 @@ def set_random_movies():
url = get_jellyfin_url("{server}/Users/{userid}/Items", url_params)
results = downloadUtils.download_url(url, suppress=True)
results = json.loads(results)
randon_movies_list = []
if results is not None:
@@ -92,7 +91,6 @@ def set_background_image(force=False):
server = downloadUtils.get_server()
results = downloadUtils.download_url(url, suppress=True)
results = json.loads(results)
if results is not None:
items = results.get("Items", [])
@@ -150,8 +148,7 @@ def check_for_new_content():
added_url = get_jellyfin_url('{server}/Users/{userid}/Items', url_params)
added_result = downloadUtils.download_url(added_url, suppress=True)
result = json.loads(added_result)
result = downloadUtils.download_url(added_url, suppress=True)
log.debug("LATEST_ADDED_ITEM: {0}".format(result))
last_added_date = ""
@@ -174,8 +171,7 @@ def check_for_new_content():
played_url = get_jellyfin_url('{server}/Users/{userid}/Items', url_params)
played_result = downloadUtils.download_url(played_url, suppress=True)
result = json.loads(played_result)
result = downloadUtils.download_url(played_url, suppress=True)
log.debug("LATEST_PLAYED_ITEM: {0}".format(result))
last_played_date = ""