diff --git a/addon.xml b/addon.xml index 3c21e2e..1254dc5 100644 --- a/addon.xml +++ b/addon.xml @@ -6,6 +6,7 @@ + video audio diff --git a/resources/lib/cache_images.py b/resources/lib/cache_images.py index 803c81d..ad92dd9 100644 --- a/resources/lib/cache_images.py +++ b/resources/lib/cache_images.py @@ -2,7 +2,7 @@ # Gnu General Public License - see LICENSE.TXT import urllib -import httplib +import requests import base64 import sys import threading @@ -15,7 +15,7 @@ import xbmcaddon from .downloadutils import DownloadUtils from .simple_logging import SimpleLogging -from .jsonrpc import JsonRpc +from .jsonrpc import JsonRpc, get_value from .translation import string_load from .datamanager import DataManager from .utils import get_art, double_urlencode @@ -254,29 +254,20 @@ class CacheArtwork(threading.Thread): log.debug("cache_artwork") # is the web server enabled - web_query = {"setting": "services.webserver"} - result = JsonRpc('Settings.GetSettingValue').execute(web_query) - xbmc_webserver_enabled = result['result']['value'] - if not xbmc_webserver_enabled: + if not get_value("services.webserver"): log.error("Kodi web server not enabled, can not cache images") return # get the port - web_port = {"setting": "services.webserverport"} - result = JsonRpc('Settings.GetSettingValue').execute(web_port) - xbmc_port = result['result']['value'] + xbmc_port = get_value("services.webserverport") log.debug("xbmc_port: {0}", xbmc_port) # get the user - web_user = {"setting": "services.webserverusername"} - result = JsonRpc('Settings.GetSettingValue').execute(web_user) - xbmc_username = result['result']['value'] + xbmc_username = get_value("services.webserverusername") log.debug("xbmc_username: {0}", xbmc_username) # get the password - web_pass = {"setting": "services.webserverpassword"} - result = JsonRpc('Settings.GetSettingValue').execute(web_pass) - xbmc_password = result['result']['value'] + xbmc_password = get_value("services.webserverpassword") progress.update(0, string_load(30356)) @@ -313,6 +304,7 @@ class CacheArtwork(threading.Thread): return missing_texture_urls = set() + # image_types = ["thumb", "poster", "banner", "clearlogo", "tvshow.poster", "tvshow.banner", "tvshow.landscape"] for image_url in jellyfin_texture_urls: if image_url not in texture_urls and not image_url.endswith("&Tag=") and len(image_url) > 0: @@ -320,7 +312,7 @@ class CacheArtwork(threading.Thread): if self.stop_all_activity: return - + log.debug("texture_urls: {0}", texture_urls) log.debug("missing_texture_urls: {0}", missing_texture_urls) log.debug("Number of existing textures: {0}", len(texture_urls)) @@ -333,10 +325,9 @@ class CacheArtwork(threading.Thread): headers = {'Authorization': 'Basic %s' % base64.b64encode(auth)} total = len(missing_texture_urls) - index = 1 count_done = 0 - for get_url in missing_texture_urls: + for index, get_url in enumerate(missing_texture_urls, 1): # log.debug("texture_url: {0}", get_url) url = double_urlencode(get_url) kodi_texture_url = ("/image/image://%s" % url) @@ -346,14 +337,13 @@ class CacheArtwork(threading.Thread): message = "%s of %s" % (index, total) progress.update(percentage, message) - conn = httplib.HTTPConnection(kodi_http_server, timeout=20) - conn.request(method="GET", url=kodi_texture_url, headers=headers) - data = conn.getresponse() - if data.status == 200: - count_done += 1 - log.debug("Get Image Result: {0}", data.status) + cache_url = "http://%s%s" % (kodi_http_server, kodi_texture_url) + data = requests.get(cache_url, timeout=20, headers=headers) + + if data.status_code == 200: + count_done += 1 + log.debug("Get Image Result: {0}", data.status_code) - index += 1 # if progress.iscanceled(): # if "iscanceled" in dir(progress) and progress.iscanceled(): if isinstance(progress, xbmcgui.DialogProgress) and progress.iscanceled(): diff --git a/resources/lib/downloadutils.py b/resources/lib/downloadutils.py index cf79b68..d174516 100644 --- a/resources/lib/downloadutils.py +++ b/resources/lib/downloadutils.py @@ -3,7 +3,7 @@ import xbmcgui import xbmcaddon -import httplib +import requests import hashlib import ssl import StringIO @@ -13,6 +13,7 @@ from urlparse import urlparse import urllib from base64 import b64encode from collections import defaultdict +from traceback import format_exc from .kodi_utils import HomeWindow from .clientinfo import ClientInformation @@ -680,7 +681,6 @@ class DownloadUtils: def download_url(self, url, suppress=False, post_body=None, method="GET", authenticate=True, headers=None): log.debug("downloadUrl") - return_data = "null" settings = xbmcaddon.Addon() user_details = load_user_details(settings) username = user_details.get("username", "") @@ -689,7 +689,7 @@ class DownloadUtils: http_timeout = int(settings.getSetting("http_timeout")) if authenticate and username == "": - return return_data + return "null" if settings.getSetting("suppressErrors") == "true": suppress = True @@ -699,13 +699,13 @@ class DownloadUtils: if url.find("{server}") != -1: server = self.get_server() if server is None: - return return_data + return "null" url = url.replace("{server}", server) if url.find("{userid}") != -1: userid = self.get_user_id() if not userid: - return return_data + return "null" url = url.replace("{userid}", userid) if url.find("{ItemLimit}") != -1: @@ -720,47 +720,20 @@ class DownloadUtils: home_window = HomeWindow() random_movies = home_window.get_property("random-movies") if not random_movies: - return return_data + return "null" url = url.replace("{random_movies}", random_movies) log.debug("After: {0}", url) - conn = None - + try: - url_bits = urlparse(url.strip()) - - protocol = url_bits.scheme - host_name = url_bits.hostname - port = url_bits.port user_name = url_bits.username user_password = url_bits.password - url_path = url_bits.path - url_puery = url_bits.query - - if not host_name or host_name == "": - return return_data - - local_use_https = False - if protocol.lower() == "https": - local_use_https = True - - server = "%s:%s" % (host_name, port) - url_path = url_path + "?" + url_puery - - if local_use_https and self.verify_cert: - log.debug("Connection: HTTPS, Cert checked") - conn = httplib.HTTPSConnection(server, timeout=http_timeout) - elif local_use_https and not self.verify_cert: - log.debug("Connection: HTTPS, Cert NOT checked") - conn = httplib.HTTPSConnection(server, timeout=http_timeout, context=ssl._create_unverified_context()) - else: - log.debug("Connection: HTTP") - conn = httplib.HTTPConnection(server, timeout=http_timeout) head = self.get_auth_header(authenticate) if user_name and user_password: + log.info("Replacing username & Password info") # add basic auth headers user_and_pass = b64encode(b"%s:%s" % (user_name, user_password)).decode("ascii") head["Authorization"] = 'Basic %s' % user_and_pass @@ -768,46 +741,36 @@ class DownloadUtils: head["User-Agent"] = "JellyCon-" + ClientInformation().get_version() log.debug("HEADERS: {0}", head) - if post_body is not None: - if isinstance(post_body, dict): - content_type = "application/json" - post_body = json.dumps(post_body) - else: - content_type = "application/x-www-form-urlencoded" + http_request = getattr(requests, method.lower()) - head["Content-Type"] = content_type - log.debug("Content-Type: {0}", content_type) + if post_body: + head["Content-Type"] = "application/json" if isinstance(post_body, dict) else "application/x-www-form-urlencoded" + + log.debug("Content-Type: {0}", head["Content-Type"]) log.debug("POST DATA: {0}", post_body) - conn.request(method=method, url=url_path, body=post_body, headers=head) + + data = http_request(url, data=json.dumps(post_body), headers=head) else: - conn.request(method=method, url=url_path, headers=head) + data = http_request(url, headers=head) - data = conn.getresponse() - log.debug("HTTP response: {0} {1}", data.status, data.reason) - log.debug("GET URL HEADERS: {0}", data.getheaders()) - if int(data.status) == 200: - ret_data = data.read() - content_type = data.getheader('content-encoding') - log.debug("Data Len Before: {0}", len(ret_data)) - if content_type == "gzip": - ret_data = StringIO.StringIO(ret_data) - gzipper = gzip.GzipFile(fileobj=ret_data) - return_data = gzipper.read() - else: - return_data = ret_data + log.debug("HTTP response: {0} {1}", data.status_code, data.content) + log.debug("{0} URL HEADERS: {1}", method, data.headers) + + if data.status_code == 200: + if headers is not None and isinstance(headers, dict): - headers.update(data.getheaders()) - log.debug("Data Len After: {0}", len(return_data)) + headers.update(data.headers) + log.debug("Data Length: {0}", len(data.content)) log.debug("====== 200 returned =======") - log.debug("Content-Type: {0}", content_type) - log.debug("{0}", return_data) + log.debug("Content-Type: {0}", data.headers.get("content-type")) + log.debug("{0}", str(data.content)) log.debug("====== 200 finished ======") - elif int(data.status) >= 400: + elif data.status_code >= 400: - if int(data.status) == 401: + if data.status_code == 401: # remove any saved password m = hashlib.md5() m.update(username) @@ -816,24 +779,16 @@ class DownloadUtils: settings.setSetting("saved_user_password_" + hashed_username, "") save_user_details(settings, "", "") - log.error("HTTP response error: {0} {1}", data.status, data.reason) + log.error("HTTP response error: {0} {1}", data.status_code, data.content) if suppress is False: xbmcgui.Dialog().notification(string_load(30316), - string_load(30200) % str(data.reason), + string_load(30200) % str(data.content), icon="special://home/addons/plugin.video.jellycon/icon.png") - + return data.content or "null" except Exception as msg: + log.error("{0}", format_exc()) log.error("Unable to connect to {0} : {1}", server, msg) - if suppress is False: + if not suppress: xbmcgui.Dialog().notification(string_load(30316), str(msg), - icon="special://home/addons/plugin.video.jellycon/icon.png") - - finally: - try: - log.debug("Closing HTTP connection: {0}", conn) - conn.close() - except: - pass - - return return_data + icon="special://home/addons/plugin.video.jellycon/icon.png") \ No newline at end of file diff --git a/resources/lib/image_server.py b/resources/lib/image_server.py index d2a349f..0927ee1 100644 --- a/resources/lib/image_server.py +++ b/resources/lib/image_server.py @@ -1,4 +1,3 @@ - import xbmcvfs import xbmc import base64 @@ -7,7 +6,7 @@ from urlparse import urlparse from random import shuffle import threading -import httplib +import requests import io from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer @@ -119,10 +118,9 @@ def build_image(path): log.debug("Loading image from : {0} {1} {2}", image_count, server, url_full_path) try: - conn = httplib.HTTPConnection(server) - conn.request("GET", url_full_path) - image_responce = conn.getresponse() - image_data = image_responce.read() + + image_responce = requests.get(thumb_url) + image_data = image_responce.content loaded_image = Image.open(io.BytesIO(image_data)) image = ImageOps.fit(loaded_image, size, method=Image.ANTIALIAS, bleed=0.0, centering=(0.5, 0.5)) @@ -170,12 +168,6 @@ class HttpImageHandler(BaseHTTPRequestHandler): self.end_headers() return - def do_QUIT(self): - log.debug("HttpImageHandler:do_QUIT()") - self.send_response(200) - self.end_headers() - return - def serve_image(self): if pil_loaded: @@ -211,14 +203,8 @@ class HttpImageServerThread(threading.Thread): threading.Thread.__init__(self) def stop(self): - self.keep_running = False log.debug("HttpImageServerThread:stop called") - try: - conn = httplib.HTTPConnection("localhost:%d" % PORT_NUMBER) - conn.request("QUIT", "/") - conn.getresponse() - except: - pass + self.keep_running = False def run(self): log.debug("HttpImageServerThread:started") diff --git a/resources/lib/server_detect.py b/resources/lib/server_detect.py index 1eeea11..edb92d9 100644 --- a/resources/lib/server_detect.py +++ b/resources/lib/server_detect.py @@ -3,7 +3,7 @@ import socket import json from urlparse import urlparse -import httplib +import requests import ssl import time import hashlib @@ -39,65 +39,44 @@ def check_connection_speed(): server = du.get_server() url = server + "/playback/bitratetest?size=%s" % test_data_size - - url_bits = urlparse(url.strip()) - - protocol = url_bits.scheme - host_name = url_bits.hostname - port = url_bits.port - # user_name = url_bits.username - # user_password = url_bits.password - url_path = url_bits.path - url_puery = url_bits.query - - server = "%s:%s" % (host_name, port) - url_path = url_path + "?" + url_puery - - local_use_https = False - if protocol.lower() == "https": - local_use_https = True - - if local_use_https and verify_cert: - log.debug("Connection: HTTPS, Cert checked") - conn = httplib.HTTPSConnection(server, timeout=http_timeout) - elif local_use_https and not verify_cert: - log.debug("Connection: HTTPS, Cert NOT checked") - conn = httplib.HTTPSConnection(server, timeout=http_timeout, context=ssl._create_unverified_context()) - else: - log.debug("Connection: HTTP") - conn = httplib.HTTPConnection(server, timeout=http_timeout) - + head = du.get_auth_header(True) head["User-Agent"] = "JellyCon-" + ClientInformation().get_version() - conn.request(method="GET", url=url, headers=head) + request_details = { + "stream": True, + "headers": head + } + + if not verify_cert: + request_details["verify"] = False progress_dialog = xbmcgui.DialogProgress() message = 'Testing with {0} MB of data'.format(speed_test_data_size) progress_dialog.create("JellyCon connection speed test", message) - total_data_read = 0 - total_time = time.time() + start_time = time.time() log.debug("Starting Connection Speed Test") - response = conn.getresponse() + + response = requests.get(url, **request_details) + last_percentage_done = 0 - if int(response.status) == 200: - data = response.read(10240) - while len(data) > 0: + total_data_read = 0 + if response.status_code == 200: + for data in response.iter_content(chunk_size=10240): total_data_read += len(data) percentage_done = int(float(total_data_read) / float(test_data_size) * 100.0) if last_percentage_done != percentage_done: progress_dialog.update(percentage_done) last_percentage_done = percentage_done - data = response.read(10240) else: - log.error("HTTP response error: {0} {1}", response.status, response.reason) - error_message = "HTTP response error: %s\n%s" % (response.status, response.reason) + log.error("HTTP response error: {0} {1}", response.status_code, response.content) + error_message = "HTTP response error: %s\n%s" % (response.status_code, response.content) xbmcgui.Dialog().ok("Speed Test Error", error_message) return -1 total_data_read_kbits = (total_data_read * 8) / 1000 - total_time = time.time() - total_time + total_time = time.time() - start_time speed = int(total_data_read_kbits / total_time) log.debug("Finished Connection Speed Test, speed: {0} total_data: {1}, total_time: {2}", speed, total_data_read, total_time)