From 474f368c8f6aaff50f79004608dfc13932dd3057 Mon Sep 17 00:00:00 2001 From: vasilky3 Date: Sat, 28 Oct 2023 00:37:48 +0300 Subject: [PATCH] add progress dialog helper. remove uninformative load from socket progress small FLAKE8 warn fixes --- resources/language/English/strings.po | 2 +- resources/language/messages.pot | 2 +- src/client.py | 33 +++++--------------- src/jackett.py | 17 +++++------ src/pdialoghelper.py | 43 +++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 36 deletions(-) create mode 100644 src/pdialoghelper.py diff --git a/resources/language/English/strings.po b/resources/language/English/strings.po index e7e8077..79a3441 100644 --- a/resources/language/English/strings.po +++ b/resources/language/English/strings.po @@ -335,7 +335,7 @@ msgid "Filtering result..." msgstr "" msgctxt "#32751" -msgid "Resolving {} magnet links..." +msgid "Resolved {}/{} magnet links..." msgstr "" msgctxt "#32752" diff --git a/resources/language/messages.pot b/resources/language/messages.pot index b32b0e5..cf383ab 100644 --- a/resources/language/messages.pot +++ b/resources/language/messages.pot @@ -336,7 +336,7 @@ msgid "Filtering result..." msgstr "" msgctxt "#32751" -msgid "Resolving {} magnet links..." +msgid "Resolved {}/{} magnet links..." msgstr "" msgctxt "#32752" diff --git a/src/client.py b/src/client.py index a20423a..3ca9f9c 100644 --- a/src/client.py +++ b/src/client.py @@ -4,11 +4,10 @@ import http.client as httplib import os import re -import xml.etree.ElementTree as ET +import xml.etree.ElementTree as ElT from urllib.parse import urljoin from xml.etree import ElementTree -from kodi_six import xbmcgui from requests_toolbelt import sessions import torrent @@ -37,9 +36,8 @@ class Jackett(object): } } - def __init__(self, host, api_key, p_dialog: xbmcgui.DialogProgressBG = None): + def __init__(self, host, api_key): super(Jackett, self).__init__() - self.p_dialog = p_dialog self._api_key = api_key self._caps = {} @@ -47,7 +45,7 @@ def __init__(self, host, api_key, p_dialog: xbmcgui.DialogProgressBG = None): self.get_caps() def get_error(self, content): - xml = ET.ElementTree(ET.fromstring(content)).getroot() + xml = ElT.ElementTree(ElT.fromstring(content)).getroot() if xml.tag == "error": return xml.attrib @@ -71,7 +69,7 @@ def get_caps(self): set_setting('settings_validated', 'Success') - xml = ET.ElementTree(ET.fromstring(caps_resp.content)).getroot() + xml = ElT.ElementTree(ElT.fromstring(caps_resp.content)).getroot() # todo handle gracefully, doesn't exist for individual trackers # self._caps["limits"] = xml.find("limits").attrib @@ -194,20 +192,12 @@ def search_query(self, query): return self._do_search_request(request_params) def _get_with_progress(self, *args, **kwargs): - if not self.p_dialog: - r = self._session.get(*args, **kwargs) - return r, r.content - - prog_from, prog_to = 0, 25 - self._update_progress(prog_from, prog_to, 0, 100) - r = self._session.get(stream=True, *args, **kwargs) total_size = int(r.headers.get('content-length', 0)) search_resp = b"" for chunk in r.iter_content(64 * 1024): if chunk: search_resp += chunk - self._update_progress(prog_from, prog_to, len(search_resp), total_size) return r, search_resp @@ -242,7 +232,7 @@ def _do_search_request(self, request_params): def _parse_items(self, resp_content): results = [] - xml = ET.ElementTree(ET.fromstring(resp_content)) + xml = ElT.ElementTree(ElT.fromstring(resp_content)) items = xml.getroot().findall("channel/item") log.info(f"Found {len(items)} items from response") for item in items: @@ -256,17 +246,16 @@ def _parse_items(self, resp_content): # todo for some reason Elementum cannot resolve the link that gets proxied through Jackett. # So we will resolve it manually for Elementum for now. # In actuality, this should be fixed within Elementum - def async_magnet_resolve(self, results): + def async_magnet_resolve(self, results, update_pg): size = len(results) - prog_from, prog_to = 25, 90 - self.p_dialog.update(prog_from, message=translation(32751).format(size)) + update_pg(message=translation(32751).format(0, size)) failed, count = 0, 0 with concurrent.futures.ThreadPoolExecutor(max_workers=os.cpu_count() * 10) as executor: future_to_magnet = {executor.submit(torrent.get_magnet, res["uri"]): res for res in results} for future in concurrent.futures.as_completed(future_to_magnet): count += 1 - self._update_progress(prog_from, prog_to, count, size) + update_pg(count, size, message=translation(32751).format(count, size)) res = future_to_magnet[future] try: magnet = future.result() @@ -284,12 +273,6 @@ def async_magnet_resolve(self, results): log.warning(f"Failed to resolve {failed} magnet links") return results - def _update_progress(self, pfrom, pto, current, total): - if not self.p_dialog: - return - - self.p_dialog.update(int((pfrom + (pto - pfrom) * (current / total)) // 1)) - def _parse_item(self, item): result = { "name": None, diff --git a/src/jackett.py b/src/jackett.py index 662fcbd..3ba57c1 100644 --- a/src/jackett.py +++ b/src/jackett.py @@ -16,12 +16,13 @@ from client import Jackett from logger import log from utils import get_setting +from pdialoghelper import PDialog available_providers = 0 special_chars = "()\"':.[]<>/\\?" -def get_client(p_dialog: xbmcgui.DialogProgressBG = None): +def get_client(): host = urlparse(get_setting('host')) if host.netloc == '' or host.scheme == '': log.warning(f"Host {get_setting('host')} is invalid. Can't return anything") @@ -37,7 +38,7 @@ def get_client(p_dialog: xbmcgui.DialogProgressBG = None): log.debug(f"jackett host: {host}") log.debug(f"jackett api_key: {api_key[0:2]}{'*' * 26}{api_key[-4:]}") - return Jackett(host=host.geturl(), api_key=api_key, p_dialog=p_dialog) + return Jackett(host=host.geturl(), api_key=api_key) def validate_client(): @@ -58,12 +59,10 @@ def search(payload, method="general"): payload = parse_payload(method, payload) log.debug(f"Searching with payload ({method}): f{payload}") - - p_dialog = xbmcgui.DialogProgressBG() - p_dialog.create('Elementum [COLOR FFFF6B00]Jackett[/COLOR]', utils.translation(32602)) results = [] - try: + p_dialog = PDialog(utils.translation(32602)) + request_start_time = time.time() results = search_jackett(p_dialog, payload, method) request_end_time = time.time() @@ -179,13 +178,13 @@ def sort_results(results): def search_jackett(p_dialog, payload, method): - jackett = get_client(p_dialog) + jackett = get_client() if jackett is None: utils.notify(utils.translation(32603), image=utils.get_icon_path()) return [] log.debug(f"Processing {method} with Jackett") - p_dialog.update(message=utils.translation(32604)) + p_dialog.update(25, message=utils.translation(32604)) if method == 'movie': res = jackett.search_movie(payload["search_title"], payload['year'], payload["imdb_id"]) elif method == 'season': @@ -210,7 +209,7 @@ def search_jackett(p_dialog, payload, method): payload.get('episode', None), payload.get('absolute_number', None), payload.get('year', None), payload.get('season_year', None), payload.get('show_year', None)) - res = jackett.async_magnet_resolve(res) + res = jackett.async_magnet_resolve(res, p_dialog.callback(90)) p_dialog.update(90, message=utils.translation(32752)) res = filter.unique(res) diff --git a/src/pdialoghelper.py b/src/pdialoghelper.py new file mode 100644 index 0000000..6d56ac3 --- /dev/null +++ b/src/pdialoghelper.py @@ -0,0 +1,43 @@ +from kodi_six import xbmcgui + + +class PDialog: + default_heading = 'Elementum [COLOR FFFF6B00]Jackett[/COLOR]' + + def __init__(self, msg, heading=default_heading): + self.heading = None + self.start_pg = None + self.curr_pg = None + self.to_pg = None + self.pd = xbmcgui.DialogProgressBG() + self._init(msg, heading) + + def _init(self, msg, heading): + self.pd.create(heading, msg) + self.heading = heading + self.start_pg = 0 + self.curr_pg = 0 + self.to_pg = 100 + + def reset(self, msg, heading=default_heading): + self.pd.close() + self._init(msg, heading) + + def callback(self, to_pg): + self.start_pg = self.curr_pg + self.to_pg = 100 if 0 > to_pg > 100 else to_pg + return self.update_progress + + def update(self, percent=None, heading=None, message=None): + self.curr_pg = percent if percent is not None else self.curr_pg + self.pd.update(percent, heading, message) + + def update_progress(self, curr_step=0, total_steps=100, heading: str = None, message: str = None): + self.curr_pg = int((self.start_pg + (self.to_pg - self.start_pg) * (curr_step / total_steps)) // 1) + self.pd.update(self.curr_pg, heading, message) + + def close(self): + self.pd.close() + + def __del__(self): + del self.pd