From 3bc1575dd19fbb09692d84d8f803fab363ae9cb7 Mon Sep 17 00:00:00 2001 From: marco Date: Wed, 5 Feb 2020 20:19:01 +0100 Subject: [PATCH] test rebase --- lib/future/backports/email/base64mime.py | 1 + lib/future/backports/test/pystone.py | 0 lib/future/backports/urllib/error.py | 4 +- lib/future/backports/urllib/parse.py | 8 +- lib/future/backports/urllib/request.py | 28 +- lib/future/backports/urllib/robotparser.py | 6 +- lib/future/builtins/newround.py | 17 +- lib/future/moves/tkinter/filedialog.py | 6 + lib/future/standard_library/__init__.py | 120 ++-- lib/future/utils/__init__.py | 4 +- platformcode/config.py | 34 +- platformcode/custom_code.py | 260 +++++-- platformcode/download_and_play.py | 32 +- platformcode/keymaptools.py | 7 +- platformcode/launcher.py | 85 ++- platformcode/logger.py | 26 +- platformcode/mct.py | 730 +++++++++++++------- platformcode/platformtools.py | 758 ++++++++++++--------- platformcode/recaptcha.py | 2 +- platformcode/subtitletools.py | 154 ++++- platformcode/unify.py | 577 +++++++++------- platformcode/xbmc_config_menu.py | 34 +- platformcode/xbmc_info_window.py | 3 +- platformcode/xbmc_videolibrary.py | 49 +- 24 files changed, 1825 insertions(+), 1120 deletions(-) mode change 100644 => 100755 lib/future/backports/test/pystone.py diff --git a/lib/future/backports/email/base64mime.py b/lib/future/backports/email/base64mime.py index 416d612e..296392a6 100644 --- a/lib/future/backports/email/base64mime.py +++ b/lib/future/backports/email/base64mime.py @@ -28,6 +28,7 @@ from __future__ import division from __future__ import absolute_import from future.builtins import range from future.builtins import bytes +from future.builtins import str __all__ = [ 'body_decode', diff --git a/lib/future/backports/test/pystone.py b/lib/future/backports/test/pystone.py old mode 100644 new mode 100755 diff --git a/lib/future/backports/urllib/error.py b/lib/future/backports/urllib/error.py index 6bcbeafb..a473e445 100644 --- a/lib/future/backports/urllib/error.py +++ b/lib/future/backports/urllib/error.py @@ -11,9 +11,9 @@ an application may want to handle an exception like a regular response. """ from __future__ import absolute_import, division, unicode_literals -from ... import standard_library +from future import standard_library -from . import response as urllib_response +from future.backports.urllib import response as urllib_response __all__ = ['URLError', 'HTTPError', 'ContentTooShortError'] diff --git a/lib/future/backports/urllib/parse.py b/lib/future/backports/urllib/parse.py index 2def4db8..04e52d49 100644 --- a/lib/future/backports/urllib/parse.py +++ b/lib/future/backports/urllib/parse.py @@ -87,7 +87,7 @@ def clear_cache(): # decoding and encoding. If valid use cases are # presented, we may relax this by using latin-1 # decoding internally for 3.3 -_implicit_encoding = 'utf8' +_implicit_encoding = 'ascii' _implicit_errors = 'strict' def _noop(obj): @@ -122,7 +122,7 @@ class _ResultMixinStr(object): """Standard approach to encoding parsed results from str to bytes""" __slots__ = () - def encode(self, encoding='utf8', errors='strict'): + def encode(self, encoding='ascii', errors='strict'): return self._encoded_counterpart(*(x.encode(encoding, errors) for x in self)) @@ -130,7 +130,7 @@ class _ResultMixinBytes(object): """Standard approach to decoding parsed results from bytes to str""" __slots__ = () - def decode(self, encoding='utf8', errors='strict'): + def decode(self, encoding='ascii', errors='strict'): return self._decoded_counterpart(*(x.decode(encoding, errors) for x in self)) @@ -730,7 +730,7 @@ def quote_from_bytes(bs, safe='/'): ### if isinstance(safe, str): # Normalize 'safe' by converting to bytes and removing non-ASCII chars - safe = str(safe).encode('utf8', 'ignore') + safe = str(safe).encode('ascii', 'ignore') else: ### For Python-Future: safe = bytes(safe) diff --git a/lib/future/backports/urllib/request.py b/lib/future/backports/urllib/request.py index aa28d1e7..baee5401 100644 --- a/lib/future/backports/urllib/request.py +++ b/lib/future/backports/urllib/request.py @@ -827,7 +827,7 @@ class ProxyHandler(BaseHandler): if user and password: user_pass = '%s:%s' % (unquote(user), unquote(password)) - creds = base64.b64encode(user_pass.encode()).decode("utf8") + creds = base64.b64encode(user_pass.encode()).decode("ascii") req.add_header('Proxy-authorization', 'Basic ' + creds) hostport = unquote(hostport) req.set_proxy(hostport, proxy_type) @@ -977,7 +977,7 @@ class AbstractBasicAuthHandler(object): user, pw = self.passwd.find_user_password(realm, host) if pw is not None: raw = "%s:%s" % (user, pw) - auth = "Basic " + base64.b64encode(raw.encode()).decode("utf8") + auth = "Basic " + base64.b64encode(raw.encode()).decode("ascii") if req.headers.get(self.auth_header, None) == auth: return None req.add_unredirected_header(self.auth_header, auth) @@ -1080,7 +1080,7 @@ class AbstractDigestAuthHandler(object): # authentication, and to provide some message integrity protection. # This isn't a fabulous effort, but it's probably Good Enough. s = "%s:%s:%s:" % (self.nonce_count, nonce, time.ctime()) - b = s.encode("utf8") + _randombytes(8) + b = s.encode("ascii") + _randombytes(8) dig = hashlib.sha1(b).hexdigest() return dig[:16] @@ -1147,9 +1147,9 @@ class AbstractDigestAuthHandler(object): def get_algorithm_impls(self, algorithm): # lambdas assume digest modules are imported at the top level if algorithm == 'MD5': - H = lambda x: hashlib.md5(x.encode("utf8")).hexdigest() + H = lambda x: hashlib.md5(x.encode("ascii")).hexdigest() elif algorithm == 'SHA': - H = lambda x: hashlib.sha1(x.encode("utf8")).hexdigest() + H = lambda x: hashlib.sha1(x.encode("ascii")).hexdigest() # XXX MD5-sess KD = lambda s, d: H("%s:%s" % (s, d)) return H, KD @@ -1829,13 +1829,13 @@ class URLopener(object): if proxy_passwd: proxy_passwd = unquote(proxy_passwd) - proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('utf8') + proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii') else: proxy_auth = None if user_passwd: user_passwd = unquote(user_passwd) - auth = base64.b64encode(user_passwd.encode()).decode('utf8') + auth = base64.b64encode(user_passwd.encode()).decode('ascii') else: auth = None http_conn = connection_factory(host) @@ -2040,7 +2040,7 @@ class URLopener(object): msg.append('Content-type: %s' % type) if encoding == 'base64': # XXX is this encoding/decoding ok? - data = base64.decodebytes(data.encode('utf8')).decode('latin-1') + data = base64.decodebytes(data.encode('ascii')).decode('latin-1') else: data = unquote(data) msg.append('Content-Length: %d' % len(data)) @@ -2498,17 +2498,7 @@ def _proxy_bypass_macosx_sysconf(host, proxy_settings): if sys.platform == 'darwin': - try: - from _scproxy import _get_proxy_settings, _get_proxies - except: - try: - # By default use environment variables - _get_proxy_settings = getproxies_environment - _get_proxies = proxy_bypass_environment - getproxies = getproxies_environment - proxy_bypass = proxy_bypass_environment - except: - pass + from _scproxy import _get_proxy_settings, _get_proxies def proxy_bypass_macosx_sysconf(host): proxy_settings = _get_proxy_settings() diff --git a/lib/future/backports/urllib/robotparser.py b/lib/future/backports/urllib/robotparser.py index 6f7abaf6..a0f36511 100644 --- a/lib/future/backports/urllib/robotparser.py +++ b/lib/future/backports/urllib/robotparser.py @@ -1,5 +1,5 @@ from __future__ import absolute_import, division, unicode_literals -from ...builtins import str +from future.builtins import str """ robotparser.py Copyright (C) 2000 Bastian Kleineidam @@ -13,8 +13,8 @@ from ...builtins import str """ # Was: import urllib.parse, urllib.request -from .. import urllib -from . import parse as _parse, request as _request +from future.backports import urllib +from future.backports.urllib import parse as _parse, request as _request urllib.parse = _parse urllib.request = _request diff --git a/lib/future/builtins/newround.py b/lib/future/builtins/newround.py index 394a2c63..e2976a76 100644 --- a/lib/future/builtins/newround.py +++ b/lib/future/builtins/newround.py @@ -2,6 +2,7 @@ ``python-future``: pure Python implementation of Python 3 round(). """ +from __future__ import division from future.utils import PYPY, PY26, bind_method # Use the decimal module for simplicity of implementation (and @@ -29,8 +30,6 @@ def newround(number, ndigits=None): if hasattr(number, '__round__'): return number.__round__(ndigits) - if ndigits < 0: - raise NotImplementedError('negative ndigits not supported yet') exponent = Decimal('10') ** (-ndigits) if PYPY: @@ -42,15 +41,19 @@ def newround(number, ndigits=None): d = number else: if not PY26: - d = Decimal.from_float(number).quantize(exponent, - rounding=ROUND_HALF_EVEN) + d = Decimal.from_float(number) else: - d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN) + d = from_float_26(number) + + if ndigits < 0: + result = newround(d / exponent) * exponent + else: + result = d.quantize(exponent, rounding=ROUND_HALF_EVEN) if return_int: - return int(d) + return int(result) else: - return float(d) + return float(result) ### From Python 2.7's decimal.py. Only needed to support Py2.6: diff --git a/lib/future/moves/tkinter/filedialog.py b/lib/future/moves/tkinter/filedialog.py index 973923e2..6a6f03ca 100644 --- a/lib/future/moves/tkinter/filedialog.py +++ b/lib/future/moves/tkinter/filedialog.py @@ -10,3 +10,9 @@ else: except ImportError: raise ImportError('The FileDialog module is missing. Does your Py2 ' 'installation include tkinter?') + + try: + from tkFileDialog import * + except ImportError: + raise ImportError('The tkFileDialog module is missing. Does your Py2 ' + 'installation include tkinter?') diff --git a/lib/future/standard_library/__init__.py b/lib/future/standard_library/__init__.py index dcfc58fe..cff02f95 100644 --- a/lib/future/standard_library/__init__.py +++ b/lib/future/standard_library/__init__.py @@ -450,63 +450,35 @@ def install_aliases(): # if hasattr(install_aliases, 'run_already'): # return for (newmodname, newobjname, oldmodname, oldobjname) in MOVES: - try: - __import__(newmodname) - # We look up the module in sys.modules because __import__ just returns the - # top-level package: - newmod = sys.modules[newmodname] - # newmod.__future_module__ = True + __import__(newmodname) + # We look up the module in sys.modules because __import__ just returns the + # top-level package: + newmod = sys.modules[newmodname] + # newmod.__future_module__ = True - __import__(oldmodname) - oldmod = sys.modules[oldmodname] + __import__(oldmodname) + oldmod = sys.modules[oldmodname] - obj = getattr(oldmod, oldobjname) - setattr(newmod, newobjname, obj) - except: - try: - flog.warning('*** FUTURE ERROR in module %s %s ' % (str(oldmod), str(oldobjname))) - except: - pass + obj = getattr(oldmod, oldobjname) + setattr(newmod, newobjname, obj) # Hack for urllib so it appears to have the same structure on Py2 as on Py3 - try: - import urllib - from future.backports.urllib import response - urllib.response = response - sys.modules['urllib.response'] = response - from future.backports.urllib import parse - urllib.parse = parse - sys.modules['urllib.parse'] = parse - from future.backports.urllib import error - urllib.error = error - sys.modules['urllib.error'] = error - except ImportError: - try: - flog.warning('*** FUTURE ERROR importing URLLIB.response, parse, error') - urllib.response = urllib - sys.modules['urllib.response'] = urllib - urllib.parse = urllib - sys.modules['urllib.parse'] = urllib - urllib.error = urllib - sys.modules['urllib.error'] = urllib - except: - pass - try: - from future.backports.urllib import request - urllib.request = request - sys.modules['urllib.request'] = request - from future.backports.urllib import robotparser - urllib.robotparser = robotparser - sys.modules['urllib.robotparser'] = robotparser - except ImportError: - try: - flog.warning('*** FUTURE ERROR importing URLLIB.Request') - urllib.request = urllib - sys.modules['urllib.request'] = urllib - urllib.robotparser = urllib - sys.modules['urllib.robotparser'] = urllib - except: - pass + import urllib + from future.backports.urllib import request + from future.backports.urllib import response + from future.backports.urllib import parse + from future.backports.urllib import error + from future.backports.urllib import robotparser + urllib.request = request + urllib.response = response + urllib.parse = parse + urllib.error = error + urllib.robotparser = robotparser + sys.modules['urllib.request'] = request + sys.modules['urllib.response'] = response + sys.modules['urllib.parse'] = parse + sys.modules['urllib.error'] = error + sys.modules['urllib.robotparser'] = robotparser # Patch the test module so it appears to have the same structure on Py2 as on Py3 try: @@ -518,11 +490,8 @@ def install_aliases(): except ImportError: pass else: - try: - test.support = support - sys.modules['test.support'] = support - except: - pass + test.support = support + sys.modules['test.support'] = support # Patch the dbm module so it appears to have the same structure on Py2 as on Py3 try: @@ -530,26 +499,23 @@ def install_aliases(): except ImportError: pass else: + from future.moves.dbm import dumb + dbm.dumb = dumb + sys.modules['dbm.dumb'] = dumb try: - from future.moves.dbm import dumb - dbm.dumb = dumb - sys.modules['dbm.dumb'] = dumb - try: - from future.moves.dbm import gnu - except ImportError: - pass - else: - dbm.gnu = gnu - sys.modules['dbm.gnu'] = gnu - try: - from future.moves.dbm import ndbm - except ImportError: - pass - else: - dbm.ndbm = ndbm - sys.modules['dbm.ndbm'] = ndbm - except: - flog.warning('*** FUTURE ERROR importing MOVES.dbm') + from future.moves.dbm import gnu + except ImportError: + pass + else: + dbm.gnu = gnu + sys.modules['dbm.gnu'] = gnu + try: + from future.moves.dbm import ndbm + except ImportError: + pass + else: + dbm.ndbm = ndbm + sys.modules['dbm.ndbm'] = ndbm # install_aliases.run_already = True diff --git a/lib/future/utils/__init__.py b/lib/future/utils/__init__.py index 46bd96de..846d5da6 100644 --- a/lib/future/utils/__init__.py +++ b/lib/future/utils/__init__.py @@ -527,9 +527,9 @@ def implements_iterator(cls): return cls if PY3: - get_next = lambda x: x.next -else: get_next = lambda x: x.__next__ +else: + get_next = lambda x: x.next def encode_filename(filename): diff --git a/platformcode/config.py b/platformcode/config.py index 386e4b99..f59dc9aa 100644 --- a/platformcode/config.py +++ b/platformcode/config.py @@ -3,6 +3,11 @@ # Parámetros de configuración (kodi) # ------------------------------------------------------------ +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + import os import re @@ -62,10 +67,12 @@ def get_platform(full_version=False): ret = {} codename = {"10": "dharma", "11": "eden", "12": "frodo", "13": "gotham", "14": "helix", "15": "isengard", - "16": "jarvis", "17": "krypton", "18": "leia"} + "16": "jarvis", "17": "krypton", "18": "leia", + "19": "matrix"} code_db = {'10': 'MyVideos37.db', '11': 'MyVideos60.db', '12': 'MyVideos75.db', '13': 'MyVideos78.db', '14': 'MyVideos90.db', '15': 'MyVideos93.db', - '16': 'MyVideos99.db', '17': 'MyVideos107.db', '18': 'MyVideos116.db'} + '16': 'MyVideos99.db', '17': 'MyVideos107.db', '18': 'MyVideos116.db', + '19': 'MyVideos116.db'} num_version = xbmc.getInfoLabel('System.BuildVersion') num_version = re.match("\d+\.\d+", num_version).group(0) @@ -334,7 +341,7 @@ def set_setting(name, value, channel="", server=""): __settings__.setSetting(name, value) - except Exception, ex: + except Exception as ex: from platformcode import logger logger.error("Error al convertir '%s' no se guarda el valor \n%s" % (name, ex)) return None @@ -346,7 +353,18 @@ def get_localized_string(code): dev = __language__(code) try: - dev = dev.encode("utf-8") + # Unicode to utf8 + if isinstance(dev, unicode): + dev = dev.encode("utf8") + if PY3: dev = dev.decode("utf8") + + # All encodings to utf8 + elif not PY3 and isinstance(dev, str): + dev = unicode(dev, "utf8", errors="replace").encode("utf8") + + # Bytes encodings to utf8 + elif PY3 and isinstance(dev, bytes): + dev = dev.decode("utf8") except: pass @@ -391,6 +409,14 @@ def get_data_path(): return dev +def get_icon(): + return xbmc.translatePath(__settings__.getAddonInfo('icon')) + + +def get_fanart(): + return xbmc.translatePath(__settings__.getAddonInfo('fanart')) + + def get_cookie_data(): import os ficherocookies = os.path.join(get_data_path(), 'cookies.dat') diff --git a/platformcode/custom_code.py b/platformcode/custom_code.py index bcfa6319..17381cf6 100644 --- a/platformcode/custom_code.py +++ b/platformcode/custom_code.py @@ -3,17 +3,23 @@ # Updater (kodi) # -------------------------------------------------------------------------------- -import json -import os -import traceback +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int +import traceback import xbmc import xbmcaddon +import threading +import subprocess +import time -from core import filetools -from core import jsontools from platformcode import config, logger, platformtools +from core import jsontools +from core import filetools + json_data_file_name = 'custom_code.json' @@ -21,10 +27,9 @@ def init(): logger.info() """ - Todo el código añadido al add-on se borra con cada actualización. Esta función permite restaurarlo automáticamente con cada actualización. - Esto permite al usuario tener su propio código, bajo su responsabilidad, y restaurarlo al add-on cada vez que se actualiza. + Todo el código añadido al add-on se borra con cada actualización. Esta función permite restaurarlo automáticamente con cada actualización. Esto permite al usuario tener su propio código, bajo su responsabilidad, y restaurarlo al add-on cada vez que se actualiza. - El mecanismo funciona copiando el contenido de la carpeta-arbol ".\userdata\addon_data\plugin.video.alfa\custom_code\..." sobre + El mecanismo funciona copiando el contenido de la carpeta-arbol "./userdata/addon_data/plugin.video.alfa/custom_code/..." sobre las carpetas de código del add-on. No verifica el contenido, solo vuelca(reemplaza) el contenido de "custom_code". El usuario almacenará en las subcarpetas de "custom_code" su código actualizado y listo para ser copiado en cualquier momento. @@ -37,7 +42,7 @@ def init(): from platformcode import custom_code custom_code.init() - 2.- En el inicio de Kodi, comprueba si existe la carpeta "custom_code" en ".\userdata\addon_data\plugin.video.alfa\". + 2.- En el inicio de Kodi, comprueba si existe la carpeta "custom_code" en "./userdata/addon_data/plugin.video.alfa/". Si no existe, la crea y sale sin más, dando al ususario la posibilidad de copiar sobre esa estructura su código, y que la función la vuelque sobre el add-on en el próximo inicio de Kodi. @@ -55,31 +60,45 @@ def init(): Tiempos: Copiando 7 archivos de prueba, el proceso ha tardado una décima de segundo. """ - + try: + #Borra el .zip de instalación de Alfa de la carpeta Packages, por si está corrupto, y que así se pueda descargar de nuevo + version = 'plugin.video.alfa-%s.zip' % config.get_addon_version(with_fix=False) + filetools.remove(filetools.join(xbmc.translatePath('special://home'), 'addons', 'packages', version), True) + #Verifica si Kodi tiene algún achivo de Base de Datos de Vídeo de versiones anteriores, entonces los borra verify_Kodi_video_DB() + #LIBTORRENT: se descarga el binario de Libtorrent cada vez que se actualiza Alfa + try: + threading.Thread(target=update_libtorrent).start() # Creamos un Thread independiente, hasta el fin de Kodi + time.sleep(2) # Dejamos terminar la inicialización... + except: # Si hay problemas de threading, nos vamos + logger.error(traceback.format_exc()) + #QUASAR: Preguntamos si se hacen modificaciones a Quasar - if not filetools.exists(os.path.join(config.get_data_path(), "quasar.json")) and not config.get_setting('addon_quasar_update', default=False): + if not filetools.exists(filetools.join(config.get_data_path(), "quasar.json")) \ + and not config.get_setting('addon_quasar_update', default=False): question_update_external_addon("quasar") #QUASAR: Hacemos las modificaciones a Quasar, si está permitido, y si está instalado - if config.get_setting('addon_quasar_update', default=False): + if config.get_setting('addon_quasar_update', default=False) or \ + (filetools.exists(filetools.join(config.get_data_path(), \ + "quasar.json")) and not xbmc.getCondVisibility('System.HasAddon("plugin.video.quasar")')): if not update_external_addon("quasar"): platformtools.dialog_notification("Actualización Quasar", "Ha fallado. Consulte el log") #Existe carpeta "custom_code" ? Si no existe se crea y se sale - custom_code_dir = os.path.join(config.get_data_path(), 'custom_code') - if os.path.exists(custom_code_dir) == False: + custom_code_dir = filetools.join(config.get_data_path(), 'custom_code') + if not filetools.exists(custom_code_dir): create_folder_structure(custom_code_dir) return else: #Existe "custom_code.json" ? Si no existe se crea custom_code_json_path = config.get_runtime_path() - custom_code_json = os.path.join(custom_code_json_path, 'custom_code.json') - if os.path.exists(custom_code_json) == False: + custom_code_json = filetools.join(custom_code_json_path, 'custom_code.json') + if not filetools.exists(custom_code_json): create_json(custom_code_json_path) #Se verifica si la versión del .json y del add-on son iguales. Si es así se sale. Si no se copia "custom_code" al add-on @@ -92,13 +111,13 @@ def create_folder_structure(custom_code_dir): logger.info() #Creamos todas las carpetas. La importante es "custom_code". Las otras sirven meramente de guía para evitar errores de nombres... - os.mkdir(custom_code_dir) - os.mkdir(filetools.join(custom_code_dir, 'channels')) - os.mkdir(filetools.join(custom_code_dir, 'core')) - os.mkdir(filetools.join(custom_code_dir, 'lib')) - os.mkdir(filetools.join(custom_code_dir, 'platformcode')) - os.mkdir(filetools.join(custom_code_dir, 'resources')) - os.mkdir(filetools.join(custom_code_dir, 'servers')) + filetools.mkdir(custom_code_dir) + filetools.mkdir(filetools.join(custom_code_dir, 'channels')) + filetools.mkdir(filetools.join(custom_code_dir, 'core')) + filetools.mkdir(filetools.join(custom_code_dir, 'lib')) + filetools.mkdir(filetools.join(custom_code_dir, 'platformcode')) + filetools.mkdir(filetools.join(custom_code_dir, 'resources')) + filetools.mkdir(filetools.join(custom_code_dir, 'servers')) return @@ -108,9 +127,9 @@ def create_json(custom_code_json_path, json_name=json_data_file_name): #Guardamaos el json con la versión de Alfa vacía, para permitir hacer la primera copia json_data_file = filetools.join(custom_code_json_path, json_name) - json_file = open(json_data_file, "a+") - json_file.write(json.dumps({"addon_version": ""})) - json_file.close() + if filetools.exists(json_data_file): + filetools.remove(json_data_file) + result = filetools.write(json_data_file, jsontools.dump({"addon_version": ""})) return @@ -122,15 +141,21 @@ def verify_copy_folders(custom_code_dir, custom_code_json_path): json_data_file = filetools.join(custom_code_json_path, json_data_file_name) json_data = jsontools.load(filetools.read(json_data_file)) current_version = config.get_addon_version(with_fix=False) - if current_version == json_data['addon_version']: - return + if not json_data or not 'addon_version' in json_data: + create_json(custom_code_json_path) + json_data = jsontools.load(filetools.read(json_data_file)) + try: + if current_version == json_data['addon_version']: + return + except: + logger.error(traceback.format_exc(1)) #Ahora copiamos los archivos desde el área de Userdata, Custom_code, sobre las carpetas del add-on - for root, folders, files in os.walk(custom_code_dir): + for root, folders, files in filetools.walk(custom_code_dir): for file in files: input_file = filetools.join(root, file) output_file = input_file.replace(custom_code_dir, custom_code_json_path) - if filetools.copy(input_file, output_file, silent=True) == False: + if not filetools.copy(input_file, output_file, silent=True): return #Guardamaos el json con la versión actual de Alfa, para no volver a hacer la copia hasta la nueva versión @@ -160,38 +185,163 @@ def question_update_external_addon(addon_name): create_json(config.get_data_path(), "%s.json" % addon_name) return stat - + + def update_external_addon(addon_name): logger.info(addon_name) - #Verificamos que el addon está instalado - if xbmc.getCondVisibility('System.HasAddon("plugin.video.%s")' % addon_name): - #Path de actuali= 3: PY3 = True; unicode = str; unichr = chr; long = int + +import urllib.request, urllib.parse, urllib.error + import os import re import socket import threading import time -import urllib -import urllib2 import xbmc import xbmcgui - from core import downloadtools from platformcode import config, logger @@ -43,7 +51,7 @@ def download_and_play(url, file_name, download_path): while not cancelled and download_thread.isAlive(): dialog.update(download_thread.get_progress(), config.get_localized_string(60313), - "Velocidad: " + str(int(download_thread.get_speed() / 1024)) + " KB/s " + str( + "Velocidad: " + str(int(old_div(download_thread.get_speed(), 1024))) + " KB/s " + str( download_thread.get_actual_size()) + "MB de " + str( download_thread.get_total_size()) + "MB", "Tiempo restante: " + str(downloadtools.sec_to_hms(download_thread.get_remaining_time()))) @@ -232,7 +240,7 @@ class DownloadThread(threading.Thread): for additional_header in additional_headers: logger.info("additional_header: " + additional_header) name = re.findall("(.*?)=.*?", additional_header)[0] - value = urllib.unquote_plus(re.findall(".*?=(.*?)$", additional_header)[0]) + value = urllib.parse.unquote_plus(re.findall(".*?=(.*?)$", additional_header)[0]) headers.append([name, value]) self.url = self.url.split("|")[0] @@ -242,18 +250,18 @@ class DownloadThread(threading.Thread): socket.setdefaulttimeout(60) # Crea la petición y añade las cabeceras - h = urllib2.HTTPHandler(debuglevel=0) - request = urllib2.Request(self.url) + h = urllib.request.HTTPHandler(debuglevel=0) + request = urllib.request.Request(self.url) for header in headers: logger.info("Header=" + header[0] + ": " + header[1]) request.add_header(header[0], header[1]) # Lanza la petición - opener = urllib2.build_opener(h) - urllib2.install_opener(opener) + opener = urllib.request.build_opener(h) + urllib.request.install_opener(opener) try: connexion = opener.open(request) - except urllib2.HTTPError, e: + except urllib.error.HTTPError as e: logger.error("error %d (%s) al abrir la url %s" % (e.code, e.msg, self.url)) # print e.code # print e.msg @@ -315,10 +323,10 @@ class DownloadThread(threading.Thread): bloqueleido = connexion.read(blocksize) after = time.time() if (after - before) > 0: - self.velocidad = len(bloqueleido) / ((after - before)) + self.velocidad = old_div(len(bloqueleido), ((after - before))) falta = totalfichero - grabado if self.velocidad > 0: - self.tiempofalta = falta / self.velocidad + self.tiempofalta = old_div(falta, self.velocidad) else: self.tiempofalta = 0 break diff --git a/platformcode/keymaptools.py b/platformcode/keymaptools.py index 5997427c..3f2ae5eb 100644 --- a/platformcode/keymaptools.py +++ b/platformcode/keymaptools.py @@ -1,5 +1,10 @@ # -*- coding: utf-8 -*- +from builtins import map +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int from threading import Timer import xbmc @@ -113,7 +118,7 @@ class Main(xbmcgui.WindowXMLDialog): if config.get_platform(True)['num_version'] < 18: self.setCoordinateResolution(2) - for menuentry in MAIN_MENU.keys(): + for menuentry in list(MAIN_MENU.keys()): item = xbmcgui.ListItem(MAIN_MENU[menuentry]["label"]) item.setProperty("thumb", str(MAIN_MENU[menuentry]["icon"])) item.setProperty("identifier", str(menuentry)) diff --git a/platformcode/launcher.py b/platformcode/launcher.py index c89d7a7d..16340862 100644 --- a/platformcode/launcher.py +++ b/platformcode/launcher.py @@ -3,24 +3,33 @@ # XBMC Launcher (xbmc / kodi) # ------------------------------------------------------------ +#from future import standard_library +#standard_library.install_aliases() +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + +if PY3: + import urllib.error as urllib2 # Es muy lento en PY2. En PY3 es nativo +else: + import urllib2 # Usamos el nativo de PY2 que es más rápido + import os import sys - - -import urllib2 +import time from core import channeltools from core import scrapertools from core import servertools -from core import trakt_tools from core import videolibrarytools +from core import trakt_tools from core.item import Item from platformcode import config, logger from platformcode import platformtools from platformcode.logger import WebErrorException - def start(): """ Primera funcion que se ejecuta al entrar en el plugin. Dentro de esta funcion deberian ir todas las llamadas a las @@ -30,21 +39,19 @@ def start(): #config.set_setting('show_once', True) # Test if all the required directories are created config.verify_directories_created() - # controlla se l'utente ha qualche problema di connessione # se lo ha: non lo fa entrare nell'addon # se ha problemi di DNS avvia ma lascia entrare # se tutto ok: entra nell'addon - from specials import resolverdns + from specials.checkhost import test_conn import threading - threading.Thread(target=test_conn, args=(True, not config.get_setting('resolver_dns'), True, [], [], True)).start() - # check_adsl = test_conn(is_exit = True, check_dns = True, view_msg = True, - # lst_urls = [], lst_site_check_dns = [], in_addon = True) - - + threading.Thread(target=test_conn, + args=(True, not config.get_setting('resolver_dns'), True, [], [], True)).start() + def run(item=None): logger.info() + if not item: # Extract item from sys.argv if sys.argv[2]: @@ -88,6 +95,9 @@ def run(item=None): logger.info(item.tostring()) try: + if not config.get_setting('tmdb_active'): + config.set_setting('tmdb_active', True) + # If item has no action, stops here if item.action == "": logger.info("Item sin accion") @@ -169,28 +179,28 @@ def run(item=None): # Checks if channel exists if os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', item.channel + ".py")): - CHANNELS = 'channels' + CHANNELS = 'channels' elif os.path.isfile(os.path.join(config.get_runtime_path(), 'channels', 'porn', item.channel + ".py")): CHANNELS = 'channels.porn' else: - CHANNELS ='specials' + CHANNELS = 'specials' if CHANNELS != 'channels.porn': channel_file = os.path.join(config.get_runtime_path(), CHANNELS, item.channel + ".py") else: - channel_file = os.path.join(config.get_runtime_path(), 'channels', 'porn', item.channel + ".py") + channel_file = os.path.join(config.get_runtime_path(), 'channels', 'porn', + item.channel + ".py") - logger.info("channel_file= " + channel_file + ' - ' + CHANNELS +' - ' + item.channel) + logger.info("channel_file= " + channel_file + ' - ' + CHANNELS + ' - ' + item.channel) channel = None if os.path.exists(channel_file): try: - channel = __import__(CHANNELS + item.channel, None, None, [CHANNELS + item.channel]) + channel = __import__('channels.%s' % item.channel, None, + None, ["channels.%s" % item.channel]) except ImportError: - importer = "import " + CHANNELS + "." + item.channel + " as channel " - - exec(importer) + exec("import channels." + item.channel + " as channel") logger.info("Running channel %s | %s" % (channel.__name__, channel.__file__)) @@ -270,14 +280,22 @@ def run(item=None): # Special action for searching, first asks for the words then call the "search" function elif item.action == "search": logger.info("item.action=%s" % item.action.upper()) - if channeltools.get_channel_setting('last_search', 'search'): - last_search = channeltools.get_channel_setting('Last_searched', 'search', '') - else: - last_search = '' + + # last_search = "" + # last_search_active = config.get_setting("last_search", "search") + # if last_search_active: + # try: + # current_saved_searches_list = list(config.get_setting("saved_searches_list", "search")) + # last_search = current_saved_searches_list[0] + # except: + # pass + + last_search = channeltools.get_channel_setting('Last_searched', 'search', '') + tecleado = platformtools.dialog_input(last_search) + if tecleado is not None: channeltools.set_channel_setting('Last_searched', tecleado, 'search') - if 'search' in dir(channel): itemlist = channel.search(item, tecleado) else: @@ -308,7 +326,7 @@ def run(item=None): platformtools.render_items(itemlist, item) - except urllib2.URLError, e: + except urllib2.URLError as e: import traceback logger.error(traceback.format_exc()) @@ -323,11 +341,12 @@ def run(item=None): logger.error("Codigo de error HTTP : %d" % e.code) # "El sitio web no funciona correctamente (error http %d)" platformtools.dialog_ok(config.get_localized_string(20000), config.get_localized_string(30051) % e.code) - except WebErrorException, e: + except WebErrorException as e: import traceback logger.error(traceback.format_exc()) - patron = 'File "' + os.path.join(config.get_runtime_path(), CHANNELS, "").replace("\\", "\\\\") + '([^.]+)\.py"' + patron = 'File "' + os.path.join(config.get_runtime_path(), "channels", "").replace("\\", + "\\\\") + '([^.]+)\.py"' canal = scrapertools.find_single_match(traceback.format_exc(), patron) platformtools.dialog_ok( @@ -382,13 +401,19 @@ def reorder_itemlist(itemlist): [config.get_localized_string(60336), '[D]']] for item in itemlist: - old_title = unicode(item.title, "utf8").lower().encode("utf8") + if not PY3: + old_title = unicode(item.title, "utf8").lower().encode("utf8") + else: + old_title = item.title.lower() for before, after in to_change: if before in item.title: item.title = item.title.replace(before, after) break - new_title = unicode(item.title, "utf8").lower().encode("utf8") + if not PY3: + new_title = unicode(item.title, "utf8").lower().encode("utf8") + else: + new_title = item.title.lower() if old_title != new_title: mod_list.append(item) modified += 1 diff --git a/platformcode/logger.py b/platformcode/logger.py index 447fe8a1..f5308358 100644 --- a/platformcode/logger.py +++ b/platformcode/logger.py @@ -6,9 +6,12 @@ import inspect import xbmc - from platformcode import config +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + loggeractive = (config.get_setting("debug") == True) @@ -18,13 +21,19 @@ def log_enable(active): def encode_log(message=""): + # Unicode to utf8 - if type(message) == unicode: + if isinstance(message, unicode): message = message.encode("utf8") + if PY3: message = message.decode("utf8") # All encodings to utf8 - elif type(message) == str: + elif not PY3 and isinstance(message, str): message = unicode(message, "utf8", errors="replace").encode("utf8") + + # Bytes encodings to utf8 + elif PY3 and isinstance(message, bytes): + message = message.decode("utf8") # Objects to string else: @@ -34,6 +43,17 @@ def encode_log(message=""): def get_caller(message=None): + + if message and isinstance(message, unicode): + message = message.encode("utf8") + if PY3: message = message.decode("utf8") + elif message and PY3 and isinstance(message, bytes): + message = message.decode("utf8") + elif message and not PY3: + message = unicode(message, "utf8", errors="replace").encode("utf8") + elif message: + message = str(message) + module = inspect.getmodule(inspect.currentframe().f_back.f_back) if module == None: diff --git a/platformcode/mct.py b/platformcode/mct.py index 2c2fe21d..b7d00b44 100644 --- a/platformcode/mct.py +++ b/platformcode/mct.py @@ -3,53 +3,88 @@ # MCT - Mini Cliente Torrent # ------------------------------------------------------------ -import os -import shutil -import tempfile -import urllib +from __future__ import division +from future import standard_library +standard_library.install_aliases() +from builtins import hex +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int +from builtins import range +from past.utils import old_div -import urllib2 +import os +import re +import tempfile +import urllib.request, urllib.parse, urllib.error +import platform +import traceback try: - from python_libtorrent import get_libtorrent, get_platform - - lt = get_libtorrent() -except Exception, e: - import libtorrent as lt - -import xbmc -import xbmcgui + import xbmc + import xbmcgui +except: + pass from platformcode import config -from core import httptools +LIBTORRENT_PATH = config.get_setting("libtorrent_path", server="torrent", default='') + +from servers import torrent as torr +lt, e, e1, e2 = torr.import_libtorrent(LIBTORRENT_PATH) + from core import scrapertools from core import filetools +from core import httptools + +try: + BUFFER = int(config.get_setting("mct_buffer", server="torrent", default="50")) +except: + BUFFER = 50 + config.set_setting("mct_buffer", "50", server="torrent") + +try: + DOWNLOAD_PATH = '' + DOWNLOAD_PATH = xbmc.translatePath(config.get_setting("mct_download_path", \ + server="torrent", default=config.get_setting("downloadpath"))) +except: + DOWNLOAD_PATH = config.get_setting("mct_download_path", server="torrent", default=config.get_setting("downloadpath")) +if not config.get_setting("mct_download_path", server="torrent") and DOWNLOAD_PATH: + config.set_setting("mct_download_path", DOWNLOAD_PATH, server="torrent") +if not DOWNLOAD_PATH: + try: + DOWNLOAD_PATH = str(xbmc.translatePath(os.path.join(config.get_data_path(), 'downloads'))) + config.set_setting("mct_download_path", os.path.join(config.get_data_path(), 'downloads'), server="torrent") + except: + DOWNLOAD_PATH = os.path.join(config.get_data_path(), 'downloads') + config.set_setting("mct_download_path", DOWNLOAD_PATH, server="torrent") + +BACKGROUND = config.get_setting("mct_background_download", server="torrent", default=True) +RAR = config.get_setting("mct_rar_unpack", server="torrent", default=True) +DOWNLOAD_LIMIT = config.get_setting("mct_download_limit", server="torrent", default="") +if DOWNLOAD_LIMIT: + try: + DOWNLOAD_LIMIT = int(DOWNLOAD_LIMIT) * 1024 + except: + DOWNLOAD_LIMIT = 0 +else: + DOWNLOAD_LIMIT = 0 +UPLOAD_LIMIT = 100 * 1024 +msg_header = 'Alfa MCT Cliente Torrent' -def play(url, xlistitem={}, is_view=None, subtitle="", item=None): +def play(url, xlistitem={}, is_view=None, subtitle="", password="", item=None): allocate = True try: - import platform - xbmc.log("XXX KODI XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") - xbmc.log("OS platform: %s %s" % (platform.system(), platform.release())) - xbmc.log("xbmc/kodi version: %s" % xbmc.getInfoLabel("System.BuildVersion")) - xbmc_version = int(xbmc.getInfoLabel("System.BuildVersion")[:2]) - xbmc.log("xbmc/kodi version number: %s" % xbmc_version) - xbmc.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX KODI XXXX") - - _platform = get_platform() - if str(_platform['system']) in ["android_armv7", "linux_armv6", "linux_armv7"]: - allocate = False - # -- log ------------------------------------------------ - xbmc.log("XXX platform XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") - xbmc.log("_platform['system']: %s" % _platform['system']) - xbmc.log("allocate: %s" % allocate) - xbmc.log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX platform XXXX") - # -- ---------------------------------------------------- + log("XXX KODI XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX") + log("OS platform: %s %s" % (platform.system(),platform.release())) + log("xbmc/kodi version: %s" % xbmc.getInfoLabel( "System.BuildVersion" )) + xbmc_version = int(xbmc.getInfoLabel( "System.BuildVersion" )[:2]) + log("Architecture: %s %s" % (str(platform.machine()), \ + str(sys.maxsize > 2 ** 32 and "64-bit" or "32-bit"))) + log("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX KODI & platform XXXX") except: - pass - - DOWNLOAD_PATH = config.get_setting("downloadpath") + log(traceback.format_exc()) # -- adfly: ------------------------------------ if url.startswith("http://adf.ly/"): @@ -58,34 +93,49 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): url = decode_adfly(data) except: ddd = xbmcgui.Dialog() - ddd.ok("alfa-MCT: Sin soporte adf.ly", - "El script no tiene soporte para el acortador de urls adf.ly.", "", "url: " + url) + ddd.ok( msg_header + ": Sin soporte adf.ly", "El script no tiene soporte para el acortador de urls adf.ly.", "", "url: " + url ) return + """ # -- Necesario para algunas webs ---------------------------- if not url.endswith(".torrent") and not url.startswith("magnet"): + #t_file = httptools.downloadpage(url, follow_redirects=False).headers["location"] t_file = scrapertools.get_header_from_response(url, header_to_get="location") - if len(t_file) > 0: - url = t_file - t_file = scrapertools.get_header_from_response(url, header_to_get="location") - if len(t_file) > 0: - url = t_file + if t_file: + if len(t_file) > 0: + url = t_file + t_file = httptools.downloadpage(url, follow_redirects=False).headers["location"] + if len(t_file) > 0: + url = t_file + """ # -- Crear dos carpetas en descargas para los archivos ------ - save_path_videos = os.path.join(DOWNLOAD_PATH, "torrent-videos") - save_path_torrents = os.path.join(DOWNLOAD_PATH, "torrent-torrents") - if not os.path.exists(save_path_torrents): os.mkdir(save_path_torrents) + save_path_videos = os.path.join( DOWNLOAD_PATH , "MCT-torrent-videos" ) + save_path_torrents = os.path.join( DOWNLOAD_PATH , "MCT-torrents" ) + if not os.path.exists( save_path_torrents ): os.mkdir(save_path_torrents) + video_path = '' + global bkg_user + bkg_user = False + ses_lt = False + if item: + if item.contentType == 'movie': + video_path = '%s-%s' % (item.contentTitle, item.infoLabels['tmdb_id']) + else: + video_path = '%s-%sx%s-%s' % (item.contentSerieName, item.contentSeason, \ + item.contentEpisodeNumber, item.infoLabels['tmdb_id']) + item.rar_path = video_path # -- Usar - archivo torrent desde web, magnet o HD --------- if not os.path.isfile(url) and not url.startswith("magnet"): # -- http - crear archivo torrent ----------------------- data = url_get(url) + # -- El nombre del torrent será el que contiene en los -- # -- datos. - - re_name = urllib.unquote(scrapertools.scrapertools.find_single_match(data, ':name\d+:(.*?)\d+:')) - torrent_file = filetools.join(save_path_torrents, filetools.encode(re_name + '.torrent')) + re_name = urllib.parse.unquote( scrapertools.find_single_match(data,':name\d+:(.*?)\d+:') ) + torrent_file = os.path.join(save_path_torrents, encode(re_name + '.torrent')) - f = open(torrent_file, 'wb') + f = open(torrent_file,'wb') f.write(data) f.close() elif os.path.isfile(url): @@ -97,17 +147,22 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): # ----------------------------------------------------------- # -- MCT - MiniClienteTorrent ------------------------------- - ses = lt.session() + try: + log("XXX libtorrent pathname: %s" % str(LIBTORRENT_PATH)) + ses = lt.session() + except Exception as e: + do = xbmcgui.Dialog() + e = e1 or e2 + do.ok('ERROR en el cliente MCT Libtorrent', 'Módulo no encontrado o imcompatible con el dispositivo.', + 'Reporte el fallo adjuntando un "log".', str(e)) + return + + log("XXX libtorrent version: %s" % lt.version) + log("##### Torrent file: %s ##" % torrent_file) - # -- log ---------------------------------------------------- - xbmc.log("### Init session ########") - xbmc.log(lt.version) - xbmc.log("#########################") - # -- -------------------------------------------------------- - - ses.add_dht_router("router.bittorrent.com", 6881) - ses.add_dht_router("router.utorrent.com", 6881) - ses.add_dht_router("dht.transmissionbt.com", 6881) + ses.add_dht_router("router.bittorrent.com",6881) + ses.add_dht_router("router.utorrent.com",6881) + ses.add_dht_router("dht.transmissionbt.com",6881) trackers = [ "udp://tracker.openbittorrent.com:80/announce", @@ -136,8 +191,7 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): if torrent_file.startswith("magnet"): try: import zlib - btih = hex(zlib.crc32( - scrapertools.scrapertools.find_single_match(torrent_file, 'magnet:\?xt=urn:(?:[A-z0-9:]+|)([A-z0-9]{32})')) & 0xffffffff) + btih = hex(zlib.crc32(scrapertools.find_single_match(torrent_file, 'magnet:\?xt=urn:(?:[A-z0-9:]+|)([A-z0-9]{32})')) & 0xffffffff) files = [f for f in os.listdir(save_path_torrents) if os.path.isfile(os.path.join(save_path_torrents, f))] for file in files: if btih in os.path.basename(file): @@ -149,42 +203,45 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): try: tempdir = tempfile.mkdtemp() except IOError: - tempdir = os.path.join(save_path_torrents, "temp") + tempdir = os.path.join(save_path_torrents , "temp") if not os.path.exists(tempdir): os.mkdir(tempdir) params = { 'save_path': tempdir, 'trackers': trackers, - 'storage_mode': lt.storage_mode_t.storage_mode_allocate, + 'storage_mode': lt.storage_mode_t.storage_mode_allocate + } + """ + , 'paused': False, 'auto_managed': True, 'duplicate_is_error': True - } + """ h = lt.add_magnet_uri(ses, torrent_file, params) dp = xbmcgui.DialogProgress() - dp.create('alfa-MCT') + dp.create(msg_header) while not h.has_metadata(): message, porcent, msg_file, s, download = getProgress(h, "Creando torrent desde magnet") dp.update(porcent, message, msg_file) if s.state == 1: download = 1 if dp.iscanceled(): dp.close() - remove_files(download, torrent_file, video_file, ses, h) + remove_files( download, torrent_file, video_file, ses, h ) return h.force_dht_announce() xbmc.sleep(1000) dp.close() info = h.get_torrent_info() - data = lt.bencode(lt.create_torrent(info).generate()) + data = lt.bencode( lt.create_torrent(info).generate() ) - torrent_file = os.path.join(save_path_torrents, - unicode(info.name() + "-" + btih, "'utf-8'", errors="replace") + ".torrent") - f = open(torrent_file, 'wb') + #torrent_file = os.path.join(save_path_torrents, unicode(info.name()+"-"+btih, "'utf-8'", errors="replace") + ".torrent") + torrent_file = os.path.join(save_path_torrents, info.name()+"-"+btih+ ".torrent") + f = open(torrent_file,'wb') f.write(data) f.close() ses.remove_torrent(h) - shutil.rmtree(tempdir) + filetools.rmdirtree(tempdir) # ----------------------------------------------------------- # -- Archivos torrent --------------------------------------- @@ -194,30 +251,64 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): # -- El más gordo o uno de los más gordo se entiende que es - # -- el vídeo o es el vídeo que se usará como referencia - # -- para el tipo de archivo - - xbmc.log("##### Archivos ## %s ##" % len(info.files())) + log("##### Archivos ## %s ##" % len(info.files())) _index_file, _video_file, _size_file = get_video_file(info) # -- Prioritarizar/Seleccionar archivo----------------------- - _index, video_file, video_size, len_files = get_video_files_sizes(info) + _index, video_file, video_size, len_files = get_video_files_sizes( info ) if len_files == 0: dp = xbmcgui.Dialog().ok("No se puede reproducir", "El torrent no contiene ningún archivo de vídeo") - if _index == -1: - _index = _index_file + if _index < 0: + log("##### parts = %s #########" % str(video_file)) + log("##### video_size = %s #########" % str(video_size)) + log("##### _index = %s #########" % str(_index)) + #if _index == -1: + # _index = _index_file + # video_size = _size_file video_file = _video_file - video_size = _size_file - - _video_file_ext = os.path.splitext(_video_file)[1] - xbmc.log("##### _video_file_ext ## %s ##" % _video_file_ext) - if (_video_file_ext == ".avi" or _video_file_ext == ".mp4") and allocate: - xbmc.log("##### storage_mode_t.storage_mode_allocate (" + _video_file_ext + ") #####") - h = ses.add_torrent({'ti': info, 'save_path': save_path_videos, 'trackers': trackers, - 'storage_mode': lt.storage_mode_t.storage_mode_allocate}) else: - xbmc.log("##### storage_mode_t.storage_mode_sparse (" + _video_file_ext + ") #####") - h = ses.add_torrent({'ti': info, 'save_path': save_path_videos, 'trackers': trackers, - 'storage_mode': lt.storage_mode_t.storage_mode_sparse}) + log("##### video_size = %s #########" % str(video_size)) + log("##### _index = %s #########" % str(_index)) + _video_file_ext = os.path.splitext( _video_file )[1] + log("##### _video_file ## %s ##" % str(_video_file)) + log("##### _video_file_ext ## %s ##" % _video_file_ext) + + dp_cerrado = True + rar = False + global extracted_rar + extracted_rar = False + global erase_file_path + erase_file_path = '' + + if _video_file_ext == ".rar": + rar = True + filename = video_file + if "/" in filename: + filename = filename.split("/")[1] + if RAR and BACKGROUND: + xbmcgui.Dialog().notification("Encontrado archivo .RAR de %.2f MB" % (video_size / 1048576.0), + "Puedes realizar otras tareas en Kodi mientrastanto. " + \ + "Te informaremos...", time=10000) + dialog = True + else: + dialog = xbmcgui.Dialog().yesno("Encontrado archivo .RAR...", "Nombre: %s" % filename, + "Tamaño: %.2f MB" % (video_size / 1048576.0), + "¿Descargar en segundo plano? Cancelar en menú Descargas") + if dialog: + dp_cerrado = False + dp = xbmcgui.DialogProgressBG() + dp.create(msg_header) + + if (_video_file_ext == ".avi" or _video_file_ext == ".mp4" or _video_file_ext == ".mkv") and allocate: + log("##### storage_mode_t.storage_mode_allocate ("+_video_file_ext+") #####") + h = ses.add_torrent( { 'ti':info, 'save_path': save_path_videos, 'trackers':trackers, 'storage_mode':lt.storage_mode_t.storage_mode_allocate } ) + else: + log("##### storage_mode_t.storage_mode_sparse ("+_video_file_ext+") #####") + h = ses.add_torrent( { 'ti':info, 'save_path': save_path_videos, 'trackers':trackers, 'storage_mode':lt.storage_mode_t.storage_mode_sparse } ) allocate = True + global ses_lt + ses_lt = True # ----------------------------------------------------------- # -- Descarga secuencial - trozo 1, trozo 2, ... ------------ @@ -225,6 +316,7 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): h.force_reannounce() h.force_dht_announce() + h.set_upload_limit(UPLOAD_LIMIT) # -- Inicio de variables para 'pause' automático cuando el - # -- el vídeo se acerca a una pieza sin completar - @@ -232,37 +324,48 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): is_greater_num_pieces_plus = False is_greater_num_pieces_pause = False - porcent4first_pieces = int(video_size * 0.000000005) - if porcent4first_pieces < 10: porcent4first_pieces = 10 + porcent4first_pieces = int( video_size * 0.000000005 ) + porcent4first_pieces = BUFFER + if porcent4first_pieces < BUFFER: porcent4first_pieces = BUFFER if porcent4first_pieces > 100: porcent4first_pieces = 100 - porcent4last_pieces = int(porcent4first_pieces / 2) + porcent4last_pieces = int(old_div(porcent4first_pieces,2)) - num_pieces_to_resume = int(video_size * 0.0000000025) - if num_pieces_to_resume < 5: num_pieces_to_resume = 5 + num_pieces_to_resume = int( video_size * 0.0000000025 ) + if num_pieces_to_resume < 10: num_pieces_to_resume = 10 if num_pieces_to_resume > 25: num_pieces_to_resume = 25 - xbmc.log("##### porcent4first_pieces ## %s ##" % porcent4first_pieces) - xbmc.log("##### porcent4last_pieces ## %s ##" % porcent4last_pieces) - xbmc.log("##### num_pieces_to_resume ## %s ##" % num_pieces_to_resume) + log("##### porcent4first_pieces ## %s ##" % porcent4first_pieces) + log("##### porcent4last_pieces ## %s ##" % porcent4last_pieces) + log("##### num_pieces_to_resume ## %s ##" % num_pieces_to_resume) # -- Prioritarizar o seleccionar las piezas del archivo que - # -- se desea reproducir con 'file_priorities' - piece_set = set_priority_pieces(h, _index, video_file, video_size, porcent4first_pieces, porcent4last_pieces, allocate) + global tot_piece_set + tot_piece_set = len(piece_set) + log("##### total piece_set ## %s ##" % len(piece_set)) - # -- Crear diálogo de progreso para el primer bucle --------- - dp = xbmcgui.DialogProgress() - dp.create('alfa-MCT') + if dp_cerrado: + # -- Crear diálogo de progreso para el primer bucle --------- + dp = xbmcgui.DialogProgress() + dp.create(msg_header) _pieces_info = {} + ren_video_file = os.path.join( save_path_videos, video_file ) # -- Doble bucle anidado ------------------------------------ - # -- Descarga - Primer bucle - + # -- Descarga - Primer bucle while not h.is_seed(): s = h.status() - xbmc.sleep(100) - + xbmc.sleep(1000) + if not dp_cerrado and not BACKGROUND: + dp.close() + dp_cerrado = True + dp = xbmcgui.DialogProgress() + dp.create(msg_header) + # -- Recuperar los datos del progreso ------------------- message, porcent, msg_file, s, download = getProgress(h, video_file, _pf=_pieces_info) @@ -271,45 +374,73 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): # -- descargados para el diálogo de 'remove_files' - if s.state == 1: download = 1 + if (s.state == 5 or s.state == 4) and rar: + # -- Borrar sesión para que libere los archivos y se pueda renombrar la carpeta ------- + ses.pause() + #video_file, rar, play_file = extract_files(video_file, save_path_videos, password, dp, item=item) + video_file, rar, play_file, erase_path = torr.extract_files(video_file, \ + save_path_videos, password, dp, item=item, torr_client='MCT') # ... extraemos el vídeo del RAR + dp.close() + + erase_file_path = erase_path + ren_video_file = erase_file_path + extracted_rar = rar + if not play_file: + remove_files( download, torrent_file, erase_file_path, ses, h, ren_video_file ) + return + is_view = "Ok" + save_path_videos = play_file + xbmc.sleep(3000) + # -- Player - play -------------------------------------- # -- Comprobar si se han completado las piezas para el - # -- inicio del vídeo - first_pieces = True - + #if not extracted_rar: _c = 0 - for i in range(piece_set[0], piece_set[porcent4first_pieces]): + for i in range( piece_set[0], piece_set[porcent4first_pieces] ): first_pieces &= h.have_piece(i) - if h.have_piece(i): _c += 1 - _pieces_info = {'current': 0, 'continuous': "%s/%s" % (_c, porcent4first_pieces), 'continuous2': "", - 'have': h.status().num_pieces, 'len': len(piece_set)} + if h.have_piece(i): _c+= 1 + _pieces_info = {'current': 0, 'continuous': "%s/%s" % (_c, porcent4first_pieces), \ + 'continuous2': "", 'have': h.status().num_pieces, 'len': len(piece_set)} last_pieces = True if not allocate: - _c = len(piece_set) - 1; - _cc = 0 - for i in range(len(piece_set) - porcent4last_pieces, len(piece_set)): + _c = len(piece_set)-1; _cc = 0 + for i in range(len(piece_set)-porcent4last_pieces, len(piece_set)): last_pieces &= h.have_piece(i) - if h.have_piece(i): _c -= 1; _cc += 1 + if h.have_piece(i): _c-= 1; _cc+=1 _pieces_info['continuous2'] = "[%s/%s] " % (_cc, porcent4last_pieces) - if is_view != "Ok" and first_pieces and last_pieces: + if is_view != "Ok" and h.status().num_pieces >= BUFFER and not rar and not bkg_user \ + or ((s.state == 5 or s.state == 4) and bkg_user): _pieces_info['continuous2'] = "" - xbmc.log("##### porcent [%.2f%%]" % (s.progress * 100)) - is_view = "Ok" + log("##### porcent [%.2f%%]" % (s.progress * 100)) dp.close() + dp_cerrado = True + if not bkg_user: + is_view = "Ok" + else: + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) + return + if is_view == "Ok": + # -- Esperando a que termine otra reproducción -------------------------- + while xbmc.Player().isPlaying(): + xbmc.sleep(3000) + # -- Player - Ver el vídeo -------------------------- - playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) + playlist = xbmc.PlayList( xbmc.PLAYLIST_VIDEO ) playlist.clear() - ren_video_file = os.path.join(save_path_videos, video_file) + ren_video_file = os.path.join( save_path_videos, video_file ) try: - playlist.add(ren_video_file, xlistitem) + playlist.add( ren_video_file, xlistitem ) except: - playlist.add(ren_video_file) + playlist.add( ren_video_file ) if xbmc_version < 17: - player = play_video(xbmc.PLAYER_CORE_AUTO) + player = play_video( xbmc.PLAYER_CORE_AUTO ) else: player = play_video() player.play(playlist) @@ -333,13 +464,11 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): _sub = False # -- Segundo bucle - Player - Control de eventos ---- + bkg_auto = True + log("##### PLAY %s" % (h.status().num_pieces)) + if item: torr.mark_auto_as_watched(item) + if ses_lt: h.set_download_limit(DOWNLOAD_LIMIT) while player.isPlaying(): - xbmc.sleep(100) - - # -- Añadir subTítulos - if subtitle != "" and not _sub: - _sub = True - player.setSubtitles(subtitle) # -- Impedir que kodi haga 'resume' al inicio --- # -- de la descarga de un archivo conocido - @@ -350,20 +479,30 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): # -- Control 'pause' automático - continuous_pieces = count_completed_continuous_pieces(h, piece_set) - if xbmc.Player().isPlaying(): + if xbmc.Player().isPlaying() and not rar: # -- Porcentage del progreso del vídeo ------ + # -- En kodi 18.x se debe controlar - + # -- ZeroDivisionError: float division by - + # -- zero - player_getTime = player.getTime() player_getTotalTime = player.getTotalTime() - porcent_time = player_getTime / player_getTotalTime * 100 + try: porcent_time = old_div(player_getTime, player_getTotalTime) * 100 + except: porcent_time = 0 # -- Pieza que se está reproduciendo -------- - current_piece = int(porcent_time / 100 * len(piece_set)) + # -- En kodi 18.x se debe controlar - + # -- ZeroDivisionError: float division by - + # -- zero - + try: current_piece = int( old_div(porcent_time, 100) * len(piece_set) ) + except: current_piece = 0 # -- Banderas de control -------------------- is_greater_num_pieces = (current_piece > continuous_pieces - num_pieces_to_resume) - is_greater_num_pieces_plus = (current_piece + porcent4first_pieces > continuous_pieces) - is_greater_num_pieces_finished = (current_piece + porcent4first_pieces >= len(piece_set)) + #is_greater_num_pieces_plus = (current_piece + porcent4first_pieces > continuous_pieces) + is_greater_num_pieces_plus = (current_piece + BUFFER > continuous_pieces) + #is_greater_num_pieces_finished = (current_piece + porcent4first_pieces >= len(piece_set)) + is_greater_num_pieces_finished = (current_piece + BUFFER >= len(piece_set)) # -- Activa 'pause' automático -------------- if is_greater_num_pieces and not player.paused and not is_greater_num_pieces_finished: @@ -372,163 +511,184 @@ def play(url, xlistitem={}, is_view=None, subtitle="", item=None): if continuous_pieces >= set_next_continuous_pieces: set_next_continuous_pieces = continuous_pieces + num_pieces_to_resume - next_continuous_pieces = str(continuous_pieces - current_piece) + "/" + str( - set_next_continuous_pieces - current_piece) - _pieces_info = {'current': current_piece, 'continuous': next_continuous_pieces, - 'continuous2': _pieces_info['continuous2'], 'have': h.status().num_pieces, - 'len': len(piece_set)} - - # si es un archivo de la videoteca enviar a marcar como visto - if item.strm_path: - from platformcode import xbmc_videolibrary - xbmc_videolibrary.mark_auto_as_watched(item) + next_continuous_pieces = str(continuous_pieces - current_piece) + "/" + str(set_next_continuous_pieces - current_piece) + _pieces_info = {'current': current_piece, 'continuous': next_continuous_pieces , 'continuous2': _pieces_info['continuous2'], 'have': h.status().num_pieces, 'len': len(piece_set)} # -- Cerrar el diálogo de progreso -------------- if player.resumed: dp.close() # -- Mostrar el diálogo de progreso ------------- - if player.paused: + if player.paused and dp_cerrado and not rar: # -- Crear diálogo si no existe ------------- + log("##### PAUSED %s" % (h.status().num_pieces)) if not player.statusDialogoProgress: - dp = xbmcgui.DialogProgress() - dp.create('alfa-MCT') + dp = xbmcgui.DialogProgressBG() + dp.create(msg_header) player.setDialogoProgress() # -- Diálogos de estado en el visionado ----- if not h.is_seed(): # -- Recuperar los datos del progreso --- message, porcent, msg_file, s, download = getProgress(h, video_file, _pf=_pieces_info) - dp.update(porcent, message, msg_file) + dp.update(porcent, message, '[CR]' + message + '[CR]' + msg_file) else: dp.update(100, "Descarga completa: " + video_file) # -- Se canceló el progreso en el visionado - # -- Continuar - - if dp.iscanceled(): + if not bkg_auto and dp.iscanceled(): dp.close() player.pause() # -- Se canceló el progreso en el visionado - # -- en la ventana de 'pause' automático. - # -- Parar si el contador llega a 3 - - if dp.iscanceled() and is_greater_num_pieces_pause: - is_greater_num_pieces_canceled += 1 + if not bkg_auto and dp.iscanceled() and is_greater_num_pieces_pause: + is_greater_num_pieces_canceled+= 1 if is_greater_num_pieces_canceled == 3: player.stop() # -- Desactiva 'pause' automático y --------- # -- reinicia el contador de cancelaciones - - if not dp.iscanceled() and not is_greater_num_pieces_plus and is_greater_num_pieces_pause: + if not is_greater_num_pieces_plus and is_greater_num_pieces_pause: dp.close() player.pause() is_greater_num_pieces_pause = False is_greater_num_pieces_canceled = 0 - + # -- El usuario cancelo el visionado -------- # -- Terminar - if player.ended: # -- Diálogo eliminar archivos ---------- - remove_files(download, torrent_file, video_file, ses, h) + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) return - + + xbmc.sleep(1000) + # -- Kodi - Se cerró el visionado ----------------------- # -- Continuar | Terminar - if is_view == "Ok" and not xbmc.Player().isPlaying(): - - if info.num_files() == 1: + dp.close() + + if h.status().num_pieces < tot_piece_set: # -- Diálogo continuar o terminar --------------- - d = xbmcgui.Dialog() - ok = d.yesno('alfa-MCT', 'XBMC-Kodi Cerró el vídeo.', '¿Continuar con la sesión?') - else: - ok = False - # -- SI --------------------------------------------- - if ok: - # -- Continuar: --------------------------------- - is_view = None + # Preguntamos si el usuario quiere pasar a backgroung + ok = xbmcgui.Dialog().yesno(msg_header, "¿Borramos los archivo descargados? (incompletos)", + "Selecciona NO para seguir descargando en segundo plano") + else: ok = True + # -- NO --------------------------------------------- + if not ok: + is_view=None + bkg_user = True + dp_cerrado = False + dp = xbmcgui.DialogProgressBG() + dp.create(msg_header) + else: # -- Terminar: ---------------------------------- # -- Comprobar si el vídeo pertenece a una ------ # -- lista de archivos - - _index, video_file, video_size, len_files = get_video_files_sizes(info) - if _index == -1 or len_files == 1: + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) + dp.close() + return + """ + #_index, video_file, video_size, len_files = get_video_files_sizes( info ) + if _index < 0 or len_files == 1: # -- Diálogo eliminar archivos -------------- - remove_files(download, torrent_file, video_file, ses, h) + #video_file = _video_file + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) + dp.close() return else: # -- Lista de archivos. Diálogo de opciones - piece_set = set_priority_pieces(h, _index, video_file, video_size, porcent4first_pieces, porcent4last_pieces, allocate) - is_view = None + is_view=None dp = xbmcgui.DialogProgress() - dp.create('alfa-MCT') + dp.create(msg_header) + """ # -- Mostar progeso antes del visionado ----------------- - if is_view != "Ok": + if is_view != "Ok" : dp.update(porcent, message, msg_file) # -- Se canceló el progreso antes del visionado --------- - # -- Terminar - - if dp.iscanceled(): + # -- Dar otra oportunidad en background o Terminar - + if not bkg_user and dp_cerrado and dp.iscanceled(): dp.close() - # -- Comprobar si el vídeo pertenece a una lista de - - # -- archivos - - _index, video_file, video_size, len_files = get_video_files_sizes(info) - if _index == -1 or len_files == 1: - # -- Diálogo eliminar archivos ------------------ - remove_files(download, torrent_file, video_file, ses, h) - return + # Preguntamos si el usuario quiere pasar a backgroung + dialog = xbmcgui.Dialog().yesno(msg_header, "¿Borramos los archivo descargados? (incompletos)", + "Seleccione NO para seguir descargando en segundo plano") + if not dialog: + bkg_user = True + dp_cerrado = False + dp = xbmcgui.DialogProgressBG() + dp.create(msg_header) + if ses_lt: h.set_download_limit(DOWNLOAD_LIMIT) + else: - # -- Lista de archivos. Diálogo de opciones ----- - piece_set = set_priority_pieces(h, _index, video_file, video_size, - porcent4first_pieces, porcent4last_pieces, allocate) - is_view = None - dp = xbmcgui.DialogProgress() - dp.create('alfa-MCT') + + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) + return + # -- Comprobar si el vídeo pertenece a una lista de - + # -- archivos - + #_index, video_file, video_size, len_files = get_video_files_sizes( info ) + if _index < 0 or len_files == 1: + # -- Diálogo eliminar archivos ------------------ + #video_file = _video_file + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) + return + else: + # -- Lista de archivos. Diálogo de opciones ----- + piece_set = set_priority_pieces(h, _index, video_file, video_size, + porcent4first_pieces, porcent4last_pieces, allocate) + is_view=None + dp = xbmcgui.DialogProgress() + dp.create(msg_header) # -- Kodi - Error? - No debería llegar aquí ----------------- if is_view == "Ok" and not xbmc.Player().isPlaying(): dp.close() # -- Diálogo eliminar archivos -------------------------- - remove_files(download, torrent_file, video_file, ses, h) + remove_files( download, torrent_file, video_file, ses, h, ren_video_file ) return # -- Progreso de la descarga ------------------------------------ def getProgress(h, video_file, _pf={}): + if len(_pf) > 0: - _pf_msg = "[%s] [%s] %s[%s] [%s]" % ( - _pf['current'], _pf['continuous'], _pf['continuous2'], _pf['have'], _pf['len']) - else: - _pf_msg = "" + _pf_msg = "[%s] [%s] %s[%s] [%s]" % (_pf['current'], _pf['continuous'], _pf['continuous2'], _pf['have'], _pf['len']) + else: _pf_msg = "" s = h.status() state_str = ['queued', 'checking', 'downloading metadata', \ - 'downloading', 'finished', 'seeding', 'allocating', 'checking fastresume'] + 'downloading', 'finished', 'seeding', 'allocating', 'checking fastresume'] message = '%.2f%% d:%.1f kb/s u:%.1f kb/s p:%d s:%d %s' % \ - (s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, \ - s.num_peers, s.num_seeds, state_str[s.state]) - porcent = int(s.progress * 100) + (s.progress * 100, old_div(s.download_rate, 1000), old_div(s.upload_rate, 1000), \ + s.num_peers, s.num_seeds, state_str[s.state]) + porcent = int( s.progress * 100 ) - download = (s.progress * 100) + download = ( s.progress * 100 ) if "/" in video_file: video_file = video_file.split("/")[1] msg_file = video_file if len(msg_file) > 50: - msg_file = msg_file.replace(video_file, - os.path.splitext(video_file)[0][:40] + "... " + os.path.splitext(video_file)[1]) - msg_file = msg_file + "[CR]" + "%.2f MB" % (s.total_wanted / 1048576.0) + " - " + _pf_msg + msg_file = msg_file.replace( video_file, os.path.splitext(video_file)[0][:40] + "... " + os.path.splitext(video_file)[1] ) + msg_file = msg_file + "[CR]" + "%.2f MB" % (s.total_wanted/1048576.0) + " - " + _pf_msg return (message, porcent, msg_file, s, download) # -- Clase play_video - Controlar eventos ----------------------- class play_video(xbmc.Player): - def __init__(self, *args, **kwargs): + + def __init__( self, *args, **kwargs ): self.paused = False self.resumed = True self.statusDialogoProgress = False @@ -560,24 +720,34 @@ class play_video(xbmc.Player): # -- El más gordo o uno de los más gordo se entiende que es el - # -- vídeo o es vídeo que se usará como referencia para el tipo - # -- de archivo - -def get_video_file(info): +def get_video_file( info ): + extensions_list = ['.aaf', '.3gp', '.asf', '.avi', '.flv', '.mpeg', + '.m1v', '.m2v', '.m4v', '.mkv', '.mov', '.mpg', + '.mpe', '.mp4', '.ogg', '.rar', '.wmv', '.zip'] size_file = 0 for i, f in enumerate(info.files()): if f.size > size_file: - video_file = f.path.replace("\\", "/") + video_file = f.path.replace("\\","/") size_file = f.size index_file = i + if os.path.splitext( video_file )[1] in extensions_list: + break return index_file, video_file, size_file # -- Listado de selección del vídeo a prioritarizar ------------- -def get_video_files_sizes(info): +def get_video_files_sizes( info ): + opciones = {} vfile_name = {} vfile_size = {} + rar_parts = 0 + rar_size = 0 + vid_parts = 0 + vid_size = 0 # -- Eliminar errores con tíldes ----------------------------- - for i, f in enumerate(info.files()): + for i, f in enumerate( info.files() ): _title = unicode(f.path, "iso-8859-1", errors="replace") _title = unicode(f.path, "'utf-8'", errors="replace") @@ -585,22 +755,29 @@ def get_video_files_sizes(info): '.m1v', '.m2v', '.m4v', '.mkv', '.mov', '.mpg', '.mpe', '.mp4', '.ogg', '.rar', '.wmv', '.zip'] - for i, f in enumerate(info.files()): + for i, f in enumerate( info.files() ): _index = int(i) - _title = f.path.replace("\\", "/") + _title = f.path.replace("\\","/") _size = f.size - _file_name = os.path.splitext(_title)[0] + _file_name = os.path.splitext( _title )[0] if "/" in _file_name: _file_name = _file_name.split('/')[1] - _file_ext = os.path.splitext(_title)[1] + _file_ext = os.path.splitext( _title )[1] + + if '.rar' in _file_ext or '.zip' in _file_ext: + rar_parts += 1 + rar_size += _size + else: + vid_parts += 1 + vid_size += _size if _file_ext in extensions_list: index = len(opciones) _caption = str(index) + \ - " - " + \ - _file_name + _file_ext + \ - " - %.2f MB" % (_size / 1048576.0) + " - " + \ + _file_name + _file_ext + \ + " - %.2f MB" % (_size / 1048576.0) vfile_name[index] = _title vfile_size[index] = _size @@ -608,56 +785,102 @@ def get_video_files_sizes(info): opciones[i] = _caption if len(opciones) > 1: - d = xbmcgui.Dialog() - seleccion = d.select("alfa-MCT: Lista de vídeos", opciones.values()) - else: - seleccion = 0 + if rar_parts > 1: + seleccion = -1 + index = -9 + return index, rar_parts, rar_size, len(opciones) + else: + d = xbmcgui.Dialog() + seleccion = d.select(msg_header + ": Selecciona el vídeo, o 'Cancelar' para todos", list(opciones.values())) + else: seleccion = 0 - index = opciones.keys()[seleccion] + index = list(opciones.keys())[seleccion] if seleccion == -1: - vfile_name[seleccion] = "" - vfile_size[seleccion] = 0 + vfile_name[seleccion] = vid_parts + vfile_size[seleccion] = vid_size index = seleccion return index, vfile_name[seleccion], vfile_size[seleccion], len(opciones) - # -- Preguntar si se desea borrar lo descargado ----------------- -def remove_files(download, torrent_file, video_file, ses, h): +def remove_files( download, torrent_file, video_file, ses, h, ren_video_file="" ): dialog_view = False torrent = False - if os.path.isfile(torrent_file): + if os.path.isfile( torrent_file ): dialog_view = True torrent = True if download > 0: dialog_view = True + if bkg_user and not extracted_rar: + dialog_view = False + + if erase_file_path and erase_file_path != \ + os.path.join( DOWNLOAD_PATH , "MCT-torrent-videos" ): + ren_video_file = erase_file_path + if filetools.isfile(ren_video_file) and filetools.split(ren_video_file)[0] != \ + os.path.join( DOWNLOAD_PATH , "MCT-torrent-videos" ): + ren_video_file = filetools.split(ren_video_file)[0] + elif filetools.isdir(ren_video_file) and ren_video_file == \ + os.path.join( DOWNLOAD_PATH , "MCT-torrent-videos" ): + ren_video_file = '' - if "/" in video_file: video_file = video_file.split("/")[0] - - if dialog_view: - d = xbmcgui.Dialog() - ok = d.yesno('alfa-MCT', 'Borrar las descargas del video', video_file) + if dialog_view and ren_video_file: + if h.status().num_pieces >= tot_piece_set: + d = xbmcgui.Dialog() + ok = d.yesno(msg_header, '¿Borrarmos los archivos descargados? (completos)', video_file) + else: + ok = True # -- SI ------------------------------------------------- if ok: # -- Borrar archivo - torrent ----------------------- if torrent: - os.remove(torrent_file) + try: + os.remove( torrent_file ) + except: + pass # -- Borrar carpeta/archivos y sesión - vídeo ------- - ses.remove_torrent(h, 1) - xbmc.log("### End session #########") + try: + ses.remove_torrent( h, 1 ) + ses_lt = False + except: + ses_lt = False + try: + if os.path.isdir(ren_video_file): + filetools.rmdirtree(ren_video_file, silent=True) + elif os.path.exists(ren_video_file) and os.path.isfile(ren_video_file): + os.remove(ren_video_file) + log("##### erase_file_path: %s" % ren_video_file) + except: + log("##### erase_file_path: %s" % ren_video_file) + + log("### End session #########") else: # -- Borrar sesión ---------------------------------- - ses.remove_torrent(h) - xbmc.log("### End session #########") + try: + ses.remove_torrent( h ) + ses_lt = False + except: + ses_lt = False + log("### End session #########") else: # -- Borrar sesión -------------------------------------- - ses.remove_torrent(h) - xbmc.log("### End session #########") + try: + ses.remove_torrent( h ) + ses_lt = False + except: + ses_lt = False + # -- Borrar archivo - torrent ----------------------- + if torrent: + try: + os.remove( torrent_file ) + except: + pass + log("### End session #########") - return + return # -- Descargar de la web los datos para crear el torrent -------- @@ -669,23 +892,22 @@ def url_get(url, params={}, headers={}): USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:20.0) Gecko/20100101 Firefox/20.0" if params: - import urllib - url = "%s?%s" % (url, urllib.urlencode(params)) + url = "%s?%s" % (url, urllib.parse.urlencode(params)) - req = urllib2.Request(url) + req = urllib.request.Request(url) req.add_header("User-Agent", USER_AGENT) - for k, v in headers.items(): + for k, v in list(headers.items()): req.add_header(k, v) try: - with closing(urllib2.urlopen(req)) as response: + with closing(urllib.request.urlopen(req)) as response: data = response.read() if response.headers.get("Content-Encoding", "") == "gzip": import zlib return zlib.decompressobj(16 + zlib.MAX_WBITS).decompress(data) return data - except urllib2.HTTPError: + except urllib.error.HTTPError: return None @@ -693,10 +915,8 @@ def url_get(url, params={}, headers={}): def count_completed_continuous_pieces(h, piece_set): not_zero = 0 for i, _set in enumerate(piece_set): - if not h.have_piece(_set): - break - else: - not_zero = 1 + if not h.have_piece(_set): break + else: not_zero = 1 return i + not_zero @@ -706,21 +926,31 @@ def count_completed_continuous_pieces(h, piece_set): # -- en una lista los índices de de las piezas del archivo - def set_priority_pieces(h, _index, video_file, video_size, porcent4first_pieces, porcent4last_pieces, allocate): + for i, _set in enumerate(h.file_priorities()): - if i != _index: - h.file_priority(i, 0) + if i != _index and _index >= 0: + #h.file_priority(i,0) + xbmc.sleep(1000) + h.file_priority(i,0) else: - h.file_priority(i, 1) + #h.file_priority(i,0) + xbmc.sleep(1000) + h.file_priority(i,1) piece_set = [] + x = 0 for i, _set in enumerate(h.piece_priorities()): - if _set == 1: piece_set.append(i) + #log("***** Nº Pieza: %s: %s" % (i, str(_set))) + if _set > 0: + piece_set.append(i) + x += 1 + log("***** Piezas %s : Activas: %s" % (str(i+1), str(x))) if not allocate: for i in range(0, porcent4first_pieces): h.set_piece_deadline(piece_set[i], 10000) - for i in range(len(piece_set) - porcent4last_pieces, len(piece_set)): + for i in range(len(piece_set)-porcent4last_pieces, len(piece_set)): h.set_piece_deadline(piece_set[i], 10000) return piece_set @@ -731,9 +961,23 @@ def decode_adfly(data): ysmm = scrapertools.find_single_match(data, "var ysmm = '([^']+)'") left = '' right = '' - for c in [ysmm[i:i + 2] for i in range(0, len(ysmm), 2)]: + for c in [ysmm[i:i+2] for i in range(0, len(ysmm), 2)]: left += c[0] right = c[1] + right decoded_url = base64.b64decode(left.encode() + right.encode())[2:].decode() return decoded_url + + +def encode(s): + import unicodedata + #log("### log ######") + #for c in s: + # log("%s : %s" % (c, str(unicodedata.category(c)))) + #log("##############") + #return s + return str(''.join((c for c in unicodedata.normalize('NFD', unicode(s, 'utf-8')) if unicodedata.category(c) != 'Mn'))) + + +def log(texto): + xbmc.log(texto, xbmc.LOGNOTICE) diff --git a/platformcode/platformtools.py b/platformcode/platformtools.py index 937573f0..7e6ae5f8 100644 --- a/platformcode/platformtools.py +++ b/platformcode/platformtools.py @@ -8,26 +8,36 @@ # version 2.0 # ------------------------------------------------------------ -import os +from __future__ import division +from __future__ import absolute_import +from past.utils import old_div +#from builtins import str import sys -import urllib +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + +if PY3: + #from future import standard_library + #standard_library.install_aliases() + import urllib.parse as urllib # Es muy lento en PY2. En PY3 es nativo +else: + import urllib # Usamos el nativo de PY2 que es más rápido + +import os -# import config import xbmc -import xbmcaddon import xbmcgui import xbmcplugin +import xbmcaddon from channelselector import get_thumb from core import channeltools from core import trakt_tools, scrapertools from core.item import Item -from platformcode import logger, keymaptools, config +from platformcode import logger +from platformcode import config from platformcode import unify -addon = xbmcaddon.Addon('plugin.video.kod') -downloadenabled = addon.getSetting('downloadenabled') - class XBMCPlayer(xbmc.Player): @@ -98,17 +108,16 @@ def dialog_numeric(_type, heading, default=""): return d -def dialog_textviewer(heading, text): # disponible a partir de kodi 16 +def dialog_textviewer(heading, text): # disponible a partir de kodi 16 return xbmcgui.Dialog().textviewer(heading, text) - def itemlist_refresh(): xbmc.executebuiltin("Container.Refresh") def itemlist_update(item, replace=False): - if replace: # reset the path history + if replace: # reset the path history xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ", replace)") else: xbmc.executebuiltin("Container.Update(" + sys.argv[0] + "?" + item.tourl() + ")") @@ -123,11 +132,11 @@ def render_items(itemlist, parent_item): @type parent_item: item @param parent_item: elemento padre """ - logger.info('START render_items') + logger.info('INICIO render_items') from core import httptools # Si el itemlist no es un list salimos - if not type(itemlist) == list: + if not isinstance(itemlist, list): return if parent_item.start: @@ -146,10 +155,18 @@ def render_items(itemlist, parent_item): anime = False if 'anime' in channeltools.get_channel_parameters(parent_item.channel)['categories']: anime = True - + try: + force_unify = channeltools.get_channel_parameters(parent_item.channel)['force_unify'] + except: + force_unify = False unify_enabled = config.get_setting('unify') - #logger.debug('unify_enabled: %s' % unify_enabled) + try: + if channeltools.get_channel_parameters(parent_item.channel)['adult']: + unify_enabled = False + except: + pass + # logger.debug('unify_enabled: %s' % unify_enabled) # Recorremos el itemlist for item in itemlist: @@ -157,10 +174,14 @@ def render_items(itemlist, parent_item): # Si el item no contiene categoria, le ponemos la del item padre if item.category == "": item.category = parent_item.category - + # Si title no existe, lo iniciamos como str, para evitar errones "NoType" if not item.title: item.title = '' + + # Si no hay action o es findvideos/play, folder=False porque no se va a devolver ningún listado + if item.action in ['play', '']: + item.folder = False # Si el item no contiene fanart, le ponemos el del item padre if item.fanart == "": @@ -180,14 +201,13 @@ def render_items(itemlist, parent_item): if 'pelicula' in item.action: item.thumbnail = get_thumb("videolibrary_movie.png") elif 'serie' in item.action: - item.thumbnail = get_thumb("videolibrary_tvshow.png") + item.thumbnail = get_thumb("videolibrary_tvshow.png") - - if unify_enabled and parent_item.channel != 'kodfavorites': + if (unify_enabled or force_unify) and parent_item.channel not in ['kodfavourites']: # Formatear titulo con unify item = unify.title_format(item) else: - #Formatear titulo metodo old school + # Formatear titulo metodo old school if item.text_color: item.title = '[COLOR %s]%s[/COLOR]' % (item.text_color, item.title) if item.text_bold: @@ -196,33 +216,26 @@ def render_items(itemlist, parent_item): item.title = '[I]%s[/I]' % item.title # Añade headers a las imagenes si estan en un servidor con cloudflare - if item.action == 'play': - #### Compatibilidad con Kodi 18: evita que se quede la ruedecedita dando vueltas en enlaces Directos - item.folder = False - item.thumbnail = unify.thumbnail_type(item) else: item.thumbnail = httptools.get_url_headers(item.thumbnail) item.fanart = httptools.get_url_headers(item.fanart) + # IconImage para folder y video if item.folder: icon_image = "DefaultFolder.png" else: icon_image = "DefaultVideo.png" - #if not genre or (genre and valid_genre): - # Creamos el listitem - #listitem = xbmcgui.ListItem(item.title, iconImage=icon_image, thumbnailImage=unify.thumbnail_type(item)) - listitem = xbmcgui.ListItem(item.title, iconImage=icon_image, thumbnailImage=item.thumbnail) # Ponemos el fanart if item.fanart: fanart = item.fanart else: - fanart = os.path.join(config.get_runtime_path(), "fanart1.jpg") + fanart = config.get_fanart() # Creamos el listitem - #listitem = xbmcgui.ListItem(item.title) + listitem = xbmcgui.ListItem(item.title) # values icon, thumb or poster are skin dependent.. so we set all to avoid problems # if not exists thumb it's used icon value @@ -240,19 +253,21 @@ def render_items(itemlist, parent_item): # Esta opcion es para poder utilizar el xbmcplugin.setResolvedUrl() # if item.isPlayable == True or (config.get_setting("player_mode") == 1 and item.action == "play"): if config.get_setting("player_mode") == 1 and item.action == "play": - if item.folder: - item.folder = False listitem.setProperty('IsPlayable', 'true') # Añadimos los infoLabels set_infolabels(listitem, item) + + # No arrastrar plot si no es una peli/serie/temporada/episodio + if item.plot and item.contentType not in ['movie', 'tvshow', 'season', 'episode']: + item.__dict__['infoLabels'].pop('plot') # Montamos el menu contextual if parent_item.channel != 'special': context_commands = set_context_commands(item, parent_item) else: context_commands = [] - # Añadimos el item + # Añadimos el menu contextual if config.get_platform(True)['num_version'] >= 17.0 and parent_item.list_type == '': listitem.addContextMenuItems(context_commands) elif parent_item.list_type == '': @@ -264,18 +279,15 @@ def render_items(itemlist, parent_item): listitem=listitem, isFolder=item.folder, totalItems=item.totalItems) - # Fijar los tipos de vistas... - if config.get_setting("forceview"): - # ...forzamos segun el viewcontent + if config.get_setting("forceview"): # ...forzamos segun el viewcontent xbmcplugin.setContent(int(sys.argv[1]), parent_item.viewcontent) - elif parent_item.channel not in ["channelselector", "", "kodfavorites"]: - # ... o segun el canal + elif parent_item.channel not in ["channelselector", "", "kodfavourites"]: # ... o segun el canal xbmcplugin.setContent(int(sys.argv[1]), "movies") - elif parent_item.channel == "kodfavorites" and parent_item.action == 'mostrar_perfil': - xbmcplugin.setContent(int(sys.argv[1]), "movies") + elif parent_item.channel == "kodfavourites" and parent_item.action == 'mostrar_perfil': + xbmcplugin.setContent(int(sys.argv[1]), "movies") # Fijamos el "breadcrumb" if parent_item.list_type == '': @@ -355,21 +367,58 @@ def set_infolabels(listitem, item, player=False): Metodo para pasar la informacion al listitem (ver tmdb.set_InfoLabels() ) item.infoLabels es un dicionario con los pares de clave/valor descritos en: http://mirrors.xbmc.org/docs/python-docs/14.x-helix/xbmcgui.html#ListItem-setInfo + https://kodi.wiki/view/InfoLabels @param listitem: objeto xbmcgui.ListItem @type listitem: xbmcgui.ListItem @param item: objeto Item que representa a una pelicula, serie o capitulo @type item: item """ + + infoLabels_dict = {'aired': 'aired', 'album': 'album', 'artist': 'artist', 'cast': 'cast', + 'castandrole': 'castandrole', 'tmdb_id': 'code', 'code': 'code', 'country': 'country', + 'credits': 'credits', 'release_date': 'dateadded', 'dateadded': 'dateadded', 'dbid': 'dbid', + 'director': 'director', 'duration': 'duration', 'episode': 'episode', + 'episodio_sinopsis': 'episodeguide', 'episodio_air_date': 'None', 'episodio_imagen': 'None', + 'episodio_titulo': 'title', 'episodio_vote_average': 'rating', 'episodio_vote_count': 'votes', + 'fanart': 'None', 'genre': 'genre', 'homepage': 'None', 'imdb_id': 'imdbnumber', + 'imdbnumber': 'imdbnumber', 'in_production': 'None', 'last_air_date': 'lastplayed', + 'mediatype': 'mediatype', 'mpaa': 'mpaa', 'number_of_episodes': 'None', + 'number_of_seasons': 'None', 'original_language': 'None', 'originaltitle': 'originaltitle', + 'overlay': 'overlay', 'poster_path': 'path', 'popularity': 'None', 'playcount': 'playcount', + 'plot': 'plot', 'plotoutline': 'plotoutline', 'premiered': 'premiered', 'quality': 'None', + 'rating': 'rating', 'season': 'season', 'set': 'set', 'setid': 'setid', + 'setoverview': 'setoverview', 'showlink': 'showlink', 'sortepisode': 'sortepisode', + 'sortseason': 'sortseason', 'sorttitle': 'sorttitle', 'status': 'status', 'studio': 'studio', + 'tag': 'tag', 'tagline': 'tagline', 'temporada_air_date': 'None', 'temporada_nombre': 'None', + 'temporada_num_episodios': 'None', 'temporada_poster': 'None', 'title': 'title', + 'top250': 'top250', 'tracknumber': 'tracknumber', 'trailer': 'trailer', 'thumbnail': 'None', + 'tvdb_id': 'None', 'tvshowtitle': 'tvshowtitle', 'type': 'None', 'userrating': 'userrating', + 'url_scraper': 'None', 'votes': 'votes', 'writer': 'writer', 'year': 'year'} + + infoLabels_kodi = {} + if item.infoLabels: if 'mediatype' not in item.infoLabels: item.infoLabels['mediatype'] = item.contentType - listitem.setInfo("video", item.infoLabels) + + try: + for label_tag, label_value in list(item.infoLabels.items()): + try: + # logger.debug(str(label_tag) + ': ' + str(infoLabels_dict[label_tag])) + if infoLabels_dict[label_tag] != 'None': + infoLabels_kodi.update({infoLabels_dict[label_tag]: item.infoLabels[label_tag]}) + except: + continue + + listitem.setInfo("video", infoLabels_kodi) + + except: + listitem.setInfo("video", item.infoLabels) + logger.error(item.infoLabels) + logger.error(infoLabels_kodi) if player and not item.contentTitle: - if item.fulltitle: - listitem.setInfo("video", {"Title": item.fulltitle}) - else: - listitem.setInfo("video", {"Title": item.title}) + listitem.setInfo("video", {"Title": item.title}) elif not player: listitem.setInfo("video", {"Title": item.title}) @@ -409,9 +458,9 @@ def set_context_commands(item, parent_item): num_version_xbmc = config.get_platform(True)['num_version'] # Creamos un list con las diferentes opciones incluidas en item.context - if type(item.context) == str: + if isinstance(item.context, str): context = item.context.split("|") - elif type(item.context) == list: + elif isinstance(item.context, list): context = item.context else: context = [] @@ -423,31 +472,30 @@ def set_context_commands(item, parent_item): item.action = itemBK.action item.channel = itemBK.channel infoLabels = {} - if itemBK.infoLabels["year"]: infoLabels["year"] = itemBK.infoLabels["year"] - if itemBK.infoLabels["imdb_id"]: infoLabels["imdb_id"] = itemBK.infoLabels["imdb_id"] - if itemBK.infoLabels["tmdb_id"]: infoLabels["tmdb_id"] = itemBK.infoLabels["tmdb_id"] - if itemBK.infoLabels["tvdb_id"]: infoLabels["tvdb_id"] = itemBK.infoLabels["tvdb_id"] - if itemBK.infoLabels["noscrap_id"]: infoLabels["noscrap_id"] = itemBK.infoLabels["noscrap_id"] - if len(infoLabels) > 0: item.infoLabels = infoLabels + if itemBK.infoLabels["year"]: infoLabels["year"] = itemBK.infoLabels["year"] + if itemBK.infoLabels["imdb_id"]: infoLabels["imdb_id"] = itemBK.infoLabels["imdb_id"] + if itemBK.infoLabels["tmdb_id"]: infoLabels["tmdb_id"] = itemBK.infoLabels["tmdb_id"] + if itemBK.infoLabels["tvdb_id"]: infoLabels["tvdb_id"] = itemBK.infoLabels["tvdb_id"] + if itemBK.infoLabels["noscrap_id"]: infoLabels["noscrap_id"] = itemBK.infoLabels["noscrap_id"] + if len(infoLabels) > 0: item.infoLabels = infoLabels - if itemBK.thumbnail: item.thumbnail = itemBK.thumbnail - if itemBK.extra: item.extra = itemBK.extra + if itemBK.thumbnail: item.thumbnail = itemBK.thumbnail + if itemBK.extra: item.extra = itemBK.extra if itemBK.contentEpisodeNumber: item.contentEpisodeNumber = itemBK.contentEpisodeNumber - if itemBK.contentEpisodeTitle: item.contentEpisodeTitle = itemBK.contentEpisodeTitle - if itemBK.contentPlot: item.contentPlot = itemBK.contentPlot - if itemBK.contentQuality: item.contentQuality = itemBK.contentQuality - if itemBK.contentSeason: item.contentSeason = itemBK.contentSeason - if itemBK.contentSerieName: item.contentSerieName = itemBK.contentSerieName - if itemBK.contentThumbnail: item.contentThumbnail = itemBK.contentThumbnail - if itemBK.contentTitle: item.contentTitle = itemBK.contentTitle - if itemBK.contentType: item.contentType = itemBK.contentType - if itemBK.duration: item.duration = itemBK.duration - if itemBK.fulltitle: item.fulltitle = itemBK.fulltitle - if itemBK.plot: item.plot = itemBK.plot - if itemBK.quality: item.quality = itemBK.quality - if itemBK.show: item.show = itemBK.show - if itemBK.title: item.title = itemBK.title - if itemBK.viewcontent: item.viewcontent = itemBK.viewcontent + if itemBK.contentEpisodeTitle: item.contentEpisodeTitle = itemBK.contentEpisodeTitle + if itemBK.contentPlot: item.contentPlot = itemBK.contentPlot + if itemBK.contentQuality: item.contentQuality = itemBK.contentQuality + if itemBK.contentSeason: item.contentSeason = itemBK.contentSeason + if itemBK.contentSerieName: item.contentSerieName = itemBK.contentSerieName + if itemBK.contentThumbnail: item.contentThumbnail = itemBK.contentThumbnail + if itemBK.contentTitle: item.contentTitle = itemBK.contentTitle + if itemBK.contentType: item.contentType = itemBK.contentType + if itemBK.duration: item.duration = itemBK.duration + if itemBK.plot: item.plot = itemBK.plot + if itemBK.quality: item.quality = itemBK.quality + if itemBK.show: item.show = itemBK.show + if itemBK.title: item.title = itemBK.title + if itemBK.viewcontent: item.viewcontent = itemBK.viewcontent # itemJson = item.tojson() # logger.info("Elemento: {0} bytes".format(len(itemJson))) @@ -457,12 +505,12 @@ def set_context_commands(item, parent_item): # Opciones segun item.context for command in context: # Predefinidos - if type(command) == str: + if isinstance(command, str): if command == "no_context": return [] # Formato dict - if type(command) == dict: + if isinstance(command, dict): # Los parametros del dict, se sobreescriben al nuevo context_item en caso de sobreescribir "action" y # "channel", los datos originales se guardan en "from_action" y "from_channel" if "action" in command: @@ -486,12 +534,12 @@ def set_context_commands(item, parent_item): return context_commands # Opciones segun criterios, solo si el item no es un tag (etiqueta), ni es "Añadir a la videoteca", etc... - if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer"]: + if item.action and item.action not in ["add_pelicula_to_library", "add_serie_to_library", "buscartrailer", "actualizar_titulos"]: # Mostrar informacion: si el item tiene plot suponemos q es una serie, temporada, capitulo o pelicula if item.infoLabels['plot'] and (num_version_xbmc < 17.0 or item.contentType == 'season'): context_commands.append((config.get_localized_string(60348), "XBMC.Action(Info)")) - # ExtendedInfo: Si esta instalado el addon y se cumplen una serie de condiciones + # ExtendedInfo: Si está instalado el addon y se cumplen una serie de condiciones if xbmc.getCondVisibility('System.HasAddon(script.extendedinfo)') \ and config.get_setting("extended_info") == True: if item.contentType == "episode" and item.contentEpisodeNumber and item.contentSeason \ @@ -520,15 +568,16 @@ def set_context_commands(item, parent_item): elif item.contentType == "movie" and (item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.contentTitle): param = "id =%s,imdb_id=%s,name=%s" \ - % (item.infoLabels['tmdb_id'], item.infoLabels['imdb_id'], item.contentTitle) + % (item.infoLabels['tmdb_id'], item.infoLabels['imdb_id'], item.contentTitle) context_commands.append(("ExtendedInfo", "XBMC.RunScript(script.extendedinfo,info=extendedinfo,%s)" % param)) # InfoPlus if config.get_setting("infoplus"): - if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \ - (item.contentTitle and item.infoLabels["year"]) or item.contentSerieName: + #if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id'] or \ + # (item.contentTitle and item.infoLabels["year"]) or item.contentSerieName: + if item.infoLabels['tmdb_id'] or item.infoLabels['imdb_id'] or item.infoLabels['tvdb_id']: context_commands.append(("InfoPlus", "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone( channel="infoplus", action="start", from_channel=item.channel).tourl()))) @@ -540,6 +589,7 @@ def set_context_commands(item, parent_item): context_commands.insert(2, (config.get_localized_string(70739), "XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(action="open_browser", url=item.url).tourl()))) + # Añadir a Favoritos if num_version_xbmc < 17.0 and \ ((item.channel not in ["favorites", "videolibrary", "help", ""] @@ -548,16 +598,17 @@ def set_context_commands(item, parent_item): (sys.argv[0], item.clone(channel="favorites", action="addFavourite", from_channel=item.channel, from_action=item.action).tourl()))) + # Añadir a Alfavoritos (Mis enlaces) if item.channel not in ["favorites", "videolibrary", "help", ""] and parent_item.channel != "favorites": - context_commands.append(("[B]%s[/B]" % config.get_localized_string(70557), "XBMC.RunPlugin(%s?%s)" % - (sys.argv[0], item.clone(channel="kodfavorites", action="addFavourite", - from_channel=item.channel, - from_action=item.action).tourl()))) + context_commands.append( + ('[COLOR blue]%s[/COLOR]' % config.get_localized_string(70557), "XBMC.RunPlugin(%s?%s)" % + (sys.argv[0], item.clone(channel="kodfavourites", action="addFavourite", + from_channel=item.channel, + from_action=item.action).tourl()))) # Buscar en otros canales - if item.contentType in ['movie', 'tvshow'] and item.channel != 'search': - + if item.contentType in ['movie', 'tvshow'] and item.channel != 'search' and item.action not in ['play']: # Buscar en otros canales if item.contentSerieName != '': @@ -569,6 +620,7 @@ def set_context_commands(item, parent_item): mediatype = 'tv' else: mediatype = item.contentType + context_commands.append((config.get_localized_string(60350), "XBMC.Container.Update (%s?%s)" % (sys.argv[0], item.clone(channel='search', @@ -576,13 +628,16 @@ def set_context_commands(item, parent_item): from_channel=item.channel, contextual=True, text=item.wanted).tourl()))) - context_commands.append(("[B]%s[/B]" % config.get_localized_string(70561), "XBMC.Container.Update (%s?%s)" % ( - sys.argv[0], item.clone(channel='search', action='from_context', search_type='list', page='1', - list_type='%s/%s/similar' % (mediatype,item.infoLabels['tmdb_id'])).tourl()))) + + context_commands.append( + ("[COLOR yellow]%s[/COLOR]" % config.get_localized_string(70561), "XBMC.Container.Update (%s?%s)" % ( + sys.argv[0], item.clone(channel='search', action='from_context', search_type='list', page='1', + list_type='%s/%s/similar' % ( + mediatype, item.infoLabels['tmdb_id'])).tourl()))) # Definir como Pagina de inicio if config.get_setting('start_page'): - if item.action not in ['findvideos', 'play']: + if item.action not in ['episodios', 'seasons', 'findvideos', 'play']: context_commands.insert(0, (config.get_localized_string(60351), "XBMC.RunPlugin(%s?%s)" % ( sys.argv[0], Item(channel='side_menu', @@ -602,55 +657,45 @@ def set_context_commands(item, parent_item): (sys.argv[0], item.clone(action="add_pelicula_to_library", from_action=item.action).tourl()))) - if (item.channel != "downloads" and item.channel != "videolibrary" and downloadenabled != "false" and not config.get_localized_string(70585) in str(item.context))\ - or (item.channel != "downloads" and item.channel != "videolibrary" and downloadenabled != "false" and config.get_localized_string(70585) in str(item.context) and config.get_localized_string(70714) in str(item.context)): + if item.channel != "downloads" and item.server != 'torrent': # Descargar pelicula - if item.contentType == "movie" and item.action in ['findvideos', "play"]: + if item.contentType == "movie" and item.contentTitle: context_commands.append((config.get_localized_string(60354), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone(channel="downloads", action="save_download", from_channel=item.channel, from_action=item.action) - .tourl()))) + .tourl()))) - # elif item.contentSerieName: - # Descargar serie - elif (item.contentType == "tvshow" and item.action in ["episodios"]) or \ - (item.contentType == "tvshow" and item.action in ['get_seasons'] and config.get_setting('show_seasons',item.channel) == False): - item.contentType == "tvshow" - context_commands.append((config.get_localized_string(60355), "XBMC.RunPlugin(%s?%s)" % - (sys.argv[0], item.clone(channel="downloads", action="save_download", - from_channel=item.channel, - from_action=item.action).tourl()))) - context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" % - (sys.argv[0], item.clone(channel="downloads", action="save_download", - from_channel=item.channel, - from_action=item.action, - download='season').tourl()))) - - # Descargar episodio - elif item.contentType == 'episode' and item.action in ["findvideos", "play"]: - item.contentType == "episode" - context_commands.append((config.get_localized_string(60356), "XBMC.RunPlugin(%s?%s)" % - (sys.argv[0], item.clone(channel="downloads", action="save_download", - from_channel=item.channel, - from_action=item.action).tourl()))) - - # Descargar temporada - elif item.contentType == "season": - context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" % - (sys.argv[0], item.clone(channel="downloads", action="save_download", - from_channel=item.channel, - from_action=item.action, - download='season').tourl()))) + elif item.contentSerieName: + # Descargar serie + if item.contentType == "tvshow": + context_commands.append((config.get_localized_string(60355), "XBMC.RunPlugin(%s?%s)" % + (sys.argv[0], item.clone(channel="downloads", action="save_download", + from_channel=item.channel, + from_action=item.action).tourl()))) + # Descargar episodio + elif item.contentType == "episode": + context_commands.append((config.get_localized_string(60356), "XBMC.RunPlugin(%s?%s)" % + (sys.argv[0], item.clone(channel="downloads", action="save_download", + from_channel=item.channel, + from_action=item.action).tourl()))) + # Descargar temporada + elif item.contentType == "season": + context_commands.append((config.get_localized_string(60357), "XBMC.RunPlugin(%s?%s)" % + (sys.argv[0], item.clone(channel="downloads", action="save_download", + from_channel=item.channel, + from_action=item.action).tourl()))) # Abrir configuración - if parent_item.channel not in ["setting", "news", "search"]: + if parent_item.channel not in ["setting", "news", "search"] and item.action == "play": context_commands.append((config.get_localized_string(60358), "XBMC.Container.Update(%s?%s)" % (sys.argv[0], Item(channel="setting", action="mainlist").tourl()))) # Buscar Trailer if item.action == "findvideos" or "buscar_trailer" in context: - context_commands.append((config.get_localized_string(60359), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone( - channel="trailertools", action="buscartrailer", contextual=True).tourl()))) + context_commands.append( + (config.get_localized_string(60359), "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], item.clone( + channel="trailertools", action="buscartrailer", contextual=True).tourl()))) + # Añadir SuperFavourites al menu contextual (1.0.53 o superior necesario) sf_file_path = xbmc.translatePath("special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py") check_sf = os.path.exists(sf_file_path) @@ -659,21 +704,16 @@ def set_context_commands(item, parent_item): "XBMC.RunScript(special://home/addons/plugin.program.super.favourites/LaunchSFMenu.py)")) context_commands = sorted(context_commands, key=lambda comand: comand[0]) + # Menu Rapido # context_commands.insert(0, (config.get_localized_string(60360), - # "XBMC.RunPlugin(%s?%s)" % (sys.argv[0], Item(channel='side_menu', - # action="open_shortcut_menu", - # parent=parent_item.tourl()).tourl( - # )))) - # context_commands.insert(1, (config.get_localized_string(70737), # "XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(channel='side_menu', # action="open_menu", # parent=parent_item.tourl()).tourl( # )))) if config.dev_mode(): context_commands.insert(2, ("item info", - "XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(action="itemInfo", - parent=item.tojson()).tourl()))) + "XBMC.Container.Update (%s?%s)" % (sys.argv[0], Item(action="itemInfo", parent=item.tojson()).tourl()))) return context_commands @@ -683,10 +723,8 @@ def is_playing(): def play_video(item, strm=False, force_direct=False, autoplay=False): logger.info() - # if item.play_from == 'window': - # force_direct=True # logger.debug(item.tostring('\n')) - logger.debug('item play: %s'%item) + logger.debug('item play: %s' % item) xbmc_player = XBMCPlayer() if item.channel == 'downloads': logger.info("Reproducir video local: %s [%s]" % (item.title, item.url)) @@ -759,7 +797,7 @@ def play_video(item, strm=False, force_direct=False, autoplay=False): # Reproduce xbmc_player.play(playlist, xlistitem) else: - set_player(item, xlistitem, mediaurl, view, strm) + set_player(item, xlistitem, mediaurl, view, strm, autoplay) def stop_video(): @@ -767,6 +805,14 @@ def stop_video(): def get_seleccion(default_action, opciones, seleccion, video_urls): + fixpri = False + # para conocer en que prioridad se trabaja + priority = int(config.get_setting("resolve_priority")) + # se usara para comprobar si hay links premium o de debriders + check = [] + # Comprueba si resolve stop esta desactivado + if config.get_setting("resolve_stop") == False: + fixpri = True # preguntar if default_action == 0: # "Elige una opción" @@ -775,24 +821,42 @@ def get_seleccion(default_action, opciones, seleccion, video_urls): elif default_action == 1: resolutions = [] for url in video_urls: + if "debrid]" in url[0] or "Premium)" in url[0]: + check.append(True) res = calcResolution(url[0]) if res: resolutions.append(res) if resolutions: - seleccion = resolutions.index(min(resolutions)) + if (fixpri == True and + check and + priority == 2): + seleccion = 0 + else: + seleccion = resolutions.index(min(resolutions)) else: seleccion = 0 # Ver en alta calidad elif default_action == 2: resolutions = [] for url in video_urls: + if "debrid]" in url[0] or "Premium)" in url[0]: + check.append(True) res = calcResolution(url[0]) if res: resolutions.append(res) + if resolutions: - seleccion = resolutions.index(max(resolutions)) + if (fixpri == True and + check and + priority == 2): + seleccion = 0 + else: + seleccion = resolutions.index(max(resolutions)) else: - seleccion = len(video_urls) - 1 + if fixpri == True and check: + seleccion = 0 + else: + seleccion = len(video_urls) - 1 else: seleccion = 0 return seleccion @@ -802,7 +866,7 @@ def calcResolution(option): match = scrapertools.find_single_match(option, '([0-9]{2,4})x([0-9]{2,4})') resolution = False if match: - resolution = int(match[0])*int(match[1]) + resolution = int(match[0]) * int(match[1]) else: if '240p' in option: resolution = 320 * 240 @@ -829,7 +893,7 @@ def show_channel_settings(**kwargs): @return: devuelve la ventana con los elementos @rtype: SettingsWindow """ - from xbmc_config_menu import SettingsWindow + from platformcode.xbmc_config_menu import SettingsWindow return SettingsWindow("ChannelSettings.xml", config.get_runtime_path()).start(**kwargs) @@ -843,12 +907,12 @@ def show_video_info(*args, **kwargs): @rtype: InfoWindow """ - from xbmc_info_window import InfoWindow + from platformcode.xbmc_info_window import InfoWindow return InfoWindow("InfoWindow.xml", config.get_runtime_path()).start(*args, **kwargs) def show_recaptcha(key, referer): - from recaptcha import Recaptcha + from platformcode.recaptcha import Recaptcha return Recaptcha("Recaptcha.xml", config.get_runtime_path()).Start(key, referer) @@ -868,7 +932,7 @@ def handle_wait(time_to_wait, title, text): espera = dialog_progress(' ' + title, "") secs = 0 - increment = int(100 / time_to_wait) + increment = int(old_div(100, time_to_wait)) cancelled = False while secs < time_to_wait: @@ -930,10 +994,10 @@ def get_dialogo_opciones(item, default_action, strm, autoplay): # "Descargar" import xbmcaddon addon = xbmcaddon.Addon('plugin.video.kod') - # downloadenabled = addon.getSetting('downloadenabled') - # if downloadenabled != "false": - # opcion = config.get_localized_string(30153) - # opciones.append(opcion) + downloadenabled = addon.getSetting('downloadenabled') + if downloadenabled != "false": + opcion = config.get_localized_string(30153) + opciones.append(opcion) if item.isFavourite: # "Quitar de favoritos" @@ -1051,11 +1115,13 @@ def get_video_seleccionado(item, seleccion, video_urls): mediaurl = video_urls[seleccion][1] if len(video_urls[seleccion]) > 4: wait_time = video_urls[seleccion][2] - item.subtitle = video_urls[seleccion][3] + if not item.subtitle: + item.subtitle = video_urls[seleccion][3] mpd = True elif len(video_urls[seleccion]) > 3: wait_time = video_urls[seleccion][2] - item.subtitle = video_urls[seleccion][3] + if not item.subtitle: + item.subtitle = video_urls[seleccion][3] elif len(video_urls[seleccion]) > 2: wait_time = video_urls[seleccion][2] view = True @@ -1077,10 +1143,9 @@ def get_video_seleccionado(item, seleccion, video_urls): return mediaurl, view, mpd -def set_player(item, xlistitem, mediaurl, view, strm): +def set_player(item, xlistitem, mediaurl, view, strm, autoplay): logger.info() - # logger.debug("item:\n" + item.tostring('\n')) - + logger.debug("item:\n" + item.tostring('\n')) # Movido del conector "torrent" aqui if item.server == "torrent": play_torrent(item, xlistitem, mediaurl) @@ -1097,11 +1162,11 @@ def set_player(item, xlistitem, mediaurl, view, strm): logger.info("player_mode=%s" % config.get_setting("player_mode")) logger.info("mediaurl=" + mediaurl) if config.get_setting("player_mode") == 3 or "megacrypter.com" in mediaurl: - import download_and_play - download_and_play.download_and_play(mediaurl, "download_and_play.mp4", config.get_setting("downloadpath")) + from . import download_and_play + download_and_play.download_and_play(mediaurl, "download_and_play.tmp", config.get_setting("downloadpath")) return - elif config.get_setting("player_mode") == 0 or item.play_from == 'window' or\ + elif config.get_setting("player_mode") == 0 or item.play_from == 'window' or \ (config.get_setting("player_mode") == 3 and mediaurl.startswith("rtmp")): # Añadimos el listitem a una lista de reproducción (playlist) playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) @@ -1116,15 +1181,16 @@ def set_player(item, xlistitem, mediaurl, view, strm): # elif config.get_setting("player_mode") == 1 or item.isPlayable: elif config.get_setting("player_mode") == 1: - logger.info("mediaurl :" + mediaurl) logger.info("Tras setResolvedUrl") # si es un archivo de la videoteca enviar a marcar como visto + if strm or item.strm_path: from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_auto_as_watched(item) logger.debug(item) xlistitem.setPath(mediaurl) xbmcplugin.setResolvedUrl(int(sys.argv[1]), True, xlistitem) + xbmc.sleep(2500) elif config.get_setting("player_mode") == 2: xbmc.executebuiltin("PlayMedia(" + mediaurl + ")") @@ -1140,6 +1206,12 @@ def set_player(item, xlistitem, mediaurl, view, strm): from platformcode import xbmc_videolibrary xbmc_videolibrary.mark_auto_as_watched(item) + if is_playing(): + xbmc.sleep(2000) + if is_playing(): + if not PY3: from lib import alfaresolver + else: from lib import alfaresolver_py3 as alfaresolver + alfaresolver.frequency_count(item) def torrent_client_installed(show_tuple=False): # Plugins externos se encuentra en servers/torrent.json nodo clients @@ -1160,9 +1232,13 @@ def torrent_client_installed(show_tuple=False): def play_torrent(item, xlistitem, mediaurl): logger.info() import time + import traceback + from core import filetools - from core import videolibrarytools - + from core import httptools + from lib import generictools + from servers import torrent + # Opciones disponibles para Reproducir torrents torrent_options = list() torrent_options.append(["Cliente interno (necesario libtorrent)"]) @@ -1183,205 +1259,237 @@ def play_torrent(item, xlistitem, mediaurl): else: seleccion = 0 - # Plugins externos - if seleccion > 1: - - #### Compatibilidad con Kodi 18: evita cuelgues/cancelaciones cuando el .torrent se lanza desde pantalla convencional - #if xbmc.getCondVisibility('Window.IsMedia'): - xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xlistitem) #Preparamos el entorno para evitar error Kod1 18 - time.sleep(0.5) #Dejamos tiempo para que se ejecute + # Si Libtorrent ha dado error de inicialización, no se pueden usar los clientes internos + UNRAR = config.get_setting("unrar_path", server="torrent", default="") + LIBTORRENT = config.get_setting("libtorrent_path", server="torrent", default='') + size_rar = 2 + rar_files = [] + if item.password: + size_rar = 3 - #Nuevo método de descarga previa del .torrent. Si da error, miramos si hay alternatica local. Si ya es local, lo usamos + # Si es Libtorrent y no está soportado, se ofrecen alternativas, si las hay... + if seleccion < 2 and not LIBTORRENT: + dialog_ok('Cliente Interno (LibTorrent):', 'Este cliente no está soportado en su dispositivo.', \ + 'Error: [COLOR yellow]%s[/COLOR]' % config.get_setting("libtorrent_error", server="torrent", + default=''), \ + 'Use otro cliente Torrent soportado') + if len(torrent_options) > 2: + seleccion = dialog_select(config.get_localized_string(70193), [opcion[0] for opcion in torrent_options]) + if seleccion < 2: + return + else: + return + # Si es Torrenter o Elementum con opción de Memoria, se ofrece la posibilidad ee usar Libtorrent temporalemente + elif seleccion > 1 and LIBTORRENT and UNRAR and 'RAR-' in item.torrent_info and ( + "torrenter" in torrent_options[seleccion][0] \ + or ("elementum" in torrent_options[seleccion][0] and xbmcaddon.Addon(id="plugin.video.%s" \ + % torrent_options[seleccion][ + 0].replace('Plugin externo: ', + '')).getSetting( + 'download_storage') == '1')): + if dialog_yesno(torrent_options[seleccion][0], 'Este plugin externo no soporta extraer on-line archivos RAR', \ + '[COLOR yellow]¿Quiere que usemos esta vez el Cliente interno MCT?[/COLOR]', \ + 'Esta operación ocupará en disco [COLOR yellow][B]%s+[/B][/COLOR] veces el tamaño del vídeo' % size_rar): + seleccion = 1 + else: + return + # Si es Elementum pero con opción de Memoria, se muestras los Ajustes de Elementum y se pide al usuario que cambie a "Usar Archivos" + elif seleccion > 1 and not LIBTORRENT and UNRAR and 'RAR-' in item.torrent_info and "elementum" in \ + torrent_options[seleccion][0] \ + and xbmcaddon.Addon(id="plugin.video.%s" % torrent_options[seleccion][0].replace('Plugin externo: ', '')) \ + .getSetting('download_storage') == '1': + if dialog_yesno(torrent_options[seleccion][0], + 'Elementum con descarga en [COLOR yellow]Memoria[/COLOR] no soporta ' + \ + 'extraer on-line archivos RAR (ocupación en disco [COLOR yellow][B]%s+[/B][/COLOR] veces)' % size_rar, \ + '[COLOR yellow]¿Quiere llamar a los Ajustes de Elementum para cambiar [B]temporalmente[/B] ' + \ + 'a [COLOR hotpink]"Usar Archivos"[/COLOR] y [B]reintentarlo[/B]?[/COLOR]'): + __settings__ = xbmcaddon.Addon( + id="plugin.video.%s" % torrent_options[seleccion][0].replace('Plugin externo: ', '')) + __settings__.openSettings() # Se visulizan los Ajustes de Elementum + elementum_dl = xbmcaddon.Addon( + id="plugin.video.%s" % torrent_options[seleccion][0].replace('Plugin externo: ', '')) \ + .getSetting('download_storage') + if elementum_dl != '1': + config.set_setting("elementum_dl", "1", server="torrent") # Salvamos el cambio para restaurarlo luego + return # Se sale, porque habrá refresco y cancelaría Kodi si no + + # Descarga de torrents a local + if seleccion >= 0: + + #### Compatibilidad con Kodi 18: evita cuelgues/cancelaciones cuando el .torrent se lanza desde pantalla convencional + # if xbmc.getCondVisibility('Window.IsMedia'): + xbmcplugin.setResolvedUrl(int(sys.argv[1]), False, xlistitem) # Preparamos el entorno para evitar error Kod1 18 + time.sleep(0.5) # Dejamos tiempo para que se ejecute + + # Nuevo método de descarga previa del .torrent. Si da error, miramos si hay alternatica local. + # Si ya es local, lo usamos url = '' url_stat = False torrents_path = '' referer = None post = None - videolibrary_path = config.get_videolibrary_path() #Calculamos el path absoluto a partir de la Videoteca - if videolibrary_path.lower().startswith("smb://"): #Si es una conexión SMB, usamos userdata local - videolibrary_path = config.get_data_path() #Calculamos el path absoluto a partir de Userdata - if not filetools.exists(videolibrary_path): #Si no existe el path, pasamos al modo clásico + rar = False + size = '' + password = '' + if item.password: + password = item.password + + videolibrary_path = config.get_videolibrary_path() # Calculamos el path absoluto a partir de la Videoteca + if scrapertools.find_single_match(videolibrary_path, + '(^\w+:\/\/)'): # Si es una conexión REMOTA, usamos userdata local + videolibrary_path = config.get_data_path() # Calculamos el path absoluto a partir de Userdata + if not filetools.exists(videolibrary_path): # Si no existe el path, pasamos al modo clásico videolibrary_path = False else: - torrents_path = filetools.join(videolibrary_path, 'temp_torrents_Alfa', 'cliente_torrent_Alfa.torrent') #path descarga temporal - if videolibrary_path and not filetools.exists(filetools.join(videolibrary_path, 'temp_torrents_Alfa')): #Si no existe la carpeta temporal, la creamos + torrents_path = filetools.join(videolibrary_path, 'temp_torrents_Alfa', \ + 'cliente_torrent_Alfa.torrent') # path descarga temporal + if not videolibrary_path or not filetools.exists(filetools.join(videolibrary_path, \ + 'temp_torrents_Alfa')): # Si no existe la carpeta temporal, la creamos filetools.mkdir(filetools.join(videolibrary_path, 'temp_torrents_Alfa')) - #identificamos si es una url o un path de archivo. Los Magnets los tratamos de la forma clásica - if not item.url.startswith("\\") and not item.url.startswith("/") and not item.url.startswith("magnet:") and not url_stat: + # Si hay headers, se pasar a la petición de descarga del .torrent + headers = {} + if item.headers: + headers = item.headers + + # identificamos si es una url o un path de archivo + if not item.url.startswith("\\") and not item.url.startswith("/") and not url_stat: timeout = 10 if item.torrent_alt: timeout = 5 - #Si es una llamada con POST, lo preparamos + # Si es una llamada con POST, lo preparamos if item.referer: referer = item.referer if item.post: post = item.post - #Descargamos el .torrent - url = videolibrarytools.caching_torrents(item.url, referer, post, torrents_path=torrents_path, timeout=timeout) + # Descargamos el .torrent + size, url, torrent_f, rar_files = generictools.get_torrent_size(item.url, referer, post, \ + torrents_path=torrents_path, + timeout=timeout, lookup=False, + headers=headers, short_pad=True) if url: url_stat = True item.url = url - if "torrentin" in torrent_options[seleccion][1]: + if "torrentin" in torrent_options[seleccion][0]: item.url = 'file://' + item.url - if not url and item.torrent_alt: #Si hay error, se busca un .torrent alternativo + if not url and item.torrent_alt: # Si hay error, se busca un .torrent alternativo if (item.torrent_alt.startswith("\\") or item.torrent_alt.startswith("/")) and videolibrary_path: - item.url = item.torrent_alt #El .torrent alternativo puede estar en una url o en local - elif not item.url.startswith("\\") and not item.url.startswith("/") and not item.url.startswith("magnet:"): + item.url = item.torrent_alt # El .torrent alternativo puede estar en una url o en local + elif not item.url.startswith("\\") and not item.url.startswith("/"): item.url = item.torrent_alt - - #Si es un archivo .torrent local, actualizamos el path relativo a path absoluto - if (item.url.startswith("\\") or item.url.startswith("/")) and not url_stat and videolibrary_path: #.torrent alternativo local + + # Si es un archivo .torrent local, actualizamos el path relativo a path absoluto + if (item.url.startswith("\\") or item.url.startswith("/")) and not \ + url_stat and videolibrary_path: # .torrent alternativo local movies = config.get_setting("folder_movies") series = config.get_setting("folder_tvshows") - if item.contentType == 'movie': - folder = movies #películas + if item.contentType == 'movie': + folder = movies # películas else: - folder = series #o series - item.url = filetools.join(config.get_videolibrary_path(), folder, item.url) #dirección del .torrent local en la Videoteca - if filetools.copy(item.url, torrents_path, silent=True): #se copia a la carpeta generíca para evitar problemas de encode + folder = series # o series + item.url = filetools.join(config.get_videolibrary_path(), folder, + item.url) # dirección del .torrent local en la Videoteca + if filetools.copy(item.url, torrents_path, + silent=True): # se copia a la carpeta generíca para evitar problemas de encode item.url = torrents_path - if "torrentin" in torrent_options[seleccion][1]: #Si es Torrentin, hay que añadir un prefijo + if "torrentin" in torrent_options[seleccion][0]: # Si es Torrentin, hay que añadir un prefijo item.url = 'file://' + item.url + size, rar_files = generictools.get_torrent_size('', file_list=True, local_torr=torrents_path, + short_pad=True) - mediaurl = urllib.quote_plus(item.url) - #Llamada con más parámetros para completar el título - if ("quasar" in torrent_options[seleccion][1] or "elementum" in torrent_options[seleccion][1]) and item.infoLabels['tmdb_id']: - if item.contentType == 'episode' and "elementum" not in torrent_options[seleccion][1]: - mediaurl += "&episode=%s&library=&season=%s&show=%s&tmdb=%s&type=episode" % (item.infoLabels['episode'], item.infoLabels['season'], item.infoLabels['tmdb_id'], item.infoLabels['tmdb_id']) - elif item.contentType == 'movie': - mediaurl += "&library=&tmdb=%s&type=movie" % (item.infoLabels['tmdb_id']) + mediaurl = item.url - xbmc.executebuiltin("PlayMedia(" + torrent_options[seleccion][1] % mediaurl + ")") + if seleccion >= 0: - #Seleccionamos que clientes torrent soportamos para el marcado de vídeos vistos: asumimos que todos funcionan - #if "quasar" in torrent_options[seleccion][1] or "elementum" in torrent_options[seleccion][1]: - - time_limit = time.time() + 150 #Marcamos el timepo máx. de buffering - while not is_playing() and time.time() < time_limit: #Esperamos mientra buffera - time.sleep(5) #Repetimos cada intervalo - #logger.debug(str(time_limit)) - if item.subtitle != '': - time.sleep(5) - xbmc_player.setSubtitles(item.subtitle) - #subt = xbmcgui.ListItem(path=item.url, thumbnailImage=item.thumbnail) - #subt.setSubtitles([item.subtitle]) - - if item.strm_path and is_playing(): #Sólo si es de Videoteca - from platformcode import xbmc_videolibrary - xbmc_videolibrary.mark_auto_as_watched(item) #Marcamos como visto al terminar - #logger.debug("Llamado el marcado") - - if seleccion == 1: - from platformcode import mct - mct.play(mediaurl, xlistitem, subtitle=item.subtitle, item=item) - - # Reproductor propio (libtorrent) - if seleccion == 0: - import time - played = False - debug = (config.get_setting("debug") == True) - - # Importamos el cliente - from btserver import Client - - client_tmp_path = config.get_setting("downloadpath") - if not client_tmp_path: - client_tmp_path = config.get_data_path() - - # Iniciamos el cliente: - c = Client(url=mediaurl, is_playing_fnc=xbmc_player.isPlaying, wait_time=None, timeout=10, - temp_path=os.path.join(client_tmp_path, config.get_localized_string(70194)), print_status=debug) - - # Mostramos el progreso - progreso = dialog_progress(config.get_localized_string(70195), config.get_localized_string(70196)) - - # Mientras el progreso no sea cancelado ni el cliente cerrado - while not c.closed: + # Si tiene .torrent válido o magnet, lo registramos + if size or item.url.startswith('magnet'): try: - # Obtenemos el estado del torrent - s = c.status - if debug: - # Montamos las tres lineas con la info del torrent - txt = '%.2f%% de %.1fMB %s | %.1f kB/s' % \ - (s.progress_file, s.file_size, s.str_state, s._download_rate) - txt2 = 'S: %d(%d) P: %d(%d) | DHT:%s (%d) | Trakers: %d' % \ - (s.num_seeds, s.num_complete, s.num_peers, s.num_incomplete, s.dht_state, s.dht_nodes, - s.trackers) - txt3 = 'Origen Peers TRK: %d DHT: %d PEX: %d LSD %d ' % \ - (s.trk_peers, s.dht_peers, s.pex_peers, s.lsd_peers) - else: - txt = '%.2f%% de %.1fMB %s | %.1f kB/s' % \ - (s.progress_file, s.file_size, s.str_state, s._download_rate) - txt2 = 'S: %d(%d) P: %d(%d)' % (s.num_seeds, s.num_complete, s.num_peers, s.num_incomplete) - try: - txt3 = config.get_localized_string(70197) % (int(s.timeout)) - except: - txt3 = '' - - progreso.update(s.buffer, txt, txt2, txt3) - time.sleep(0.5) - - if progreso.iscanceled(): - progreso.close() - if s.buffer == 100: - if dialog_yesno(config.get_localized_string(70195), config.get_localized_string(70198)): - played = False - progreso = dialog_progress(config.get_localized_string(70195), "") - progreso.update(s.buffer, txt, txt2, txt3) - else: - progreso = dialog_progress(config.get_localized_string(70195), "") - break - - else: - if dialog_yesno(config.get_localized_string(70195), config.get_localized_string(70199)): - progreso = dialog_progress(config.get_localized_string(70195), "") - break - - else: - progreso = dialog_progress(config.get_localized_string(70195), "") - progreso.update(s.buffer, txt, txt2, txt3) - - # Si el buffer se ha llenado y la reproduccion no ha sido iniciada, se inicia - if s.buffer == 100 and not played: - # Cerramos el progreso - progreso.close() - - # Obtenemos el playlist del torrent - videourl = c.get_play_list() - - # Iniciamos el reproductor - playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) - playlist.clear() - playlist.add(videourl, xlistitem) - # xbmc_player = xbmc_player - xbmc_player.play(playlist) - - # Marcamos como reproducido para que no se vuelva a iniciar - played = True - - # si es un archivo de la videoteca enviar a marcar como visto - if item.strm_path: - from platformcode import xbmc_videolibrary - xbmc_videolibrary.mark_auto_as_watched(item) - - # Y esperamos a que el reproductor se cierre - while xbmc_player.isPlaying(): - time.sleep(1) - - # Cuando este cerrado, Volvemos a mostrar el dialogo - progreso = dialog_progress(config.get_localized_string(70195), "") - progreso.update(s.buffer, txt, txt2, txt3) - + import threading + if not PY3: from lib import alfaresolver + else: from lib import alfaresolver_py3 as alfaresolver + threading.Thread(target=alfaresolver.frequency_count, args=(item, )).start() except: - import traceback - logger.error(traceback.format_exc()) - break + logger.error(traceback.format_exc(1)) + + # Reproductor propio BT (libtorrent) + if seleccion == 0: + torrent.bt_client(mediaurl, xlistitem, rar_files, subtitle=item.subtitle, password=password, item=item) - progreso.update(100, config.get_localized_string(70200), " ", " ") + # Reproductor propio MCT (libtorrent) + elif seleccion == 1: + from platformcode import mct + mct.play(mediaurl, xlistitem, subtitle=item.subtitle, password=password, item=item) - # Detenemos el cliente - if not c.closed: - c.stop() + # Plugins externos + else: + mediaurl = urllib.quote_plus(item.url) + # Llamada con más parámetros para completar el título + if ("quasar" in torrent_options[seleccion][1] or "elementum" in torrent_options[seleccion][1]) \ + and item.infoLabels['tmdb_id']: + if item.contentType == 'episode' and "elementum" not in torrent_options[seleccion][1]: + mediaurl += "&episode=%s&library=&season=%s&show=%s&tmdb=%s&type=episode" % ( + item.infoLabels['episode'], item.infoLabels['season'], item.infoLabels['tmdb_id'], + item.infoLabels['tmdb_id']) + elif item.contentType == 'movie': + mediaurl += "&library=&tmdb=%s&type=movie" % (item.infoLabels['tmdb_id']) + + xbmc.executebuiltin("PlayMedia(" + torrent_options[seleccion][1] % mediaurl + ")") + + # Si es un archivo RAR, monitorizamos el cliente Torrent hasta que haya descargado el archivo, + # y después lo extraemos, incluso con RAR's anidados y con contraseña + torr_client = torrent_options[seleccion][0].replace('Plugin externo: ', '') + if 'RAR-' in size and torr_client in ['quasar', 'elementum'] and UNRAR: + rar_file, save_path_videos, folder_torr = torrent.wait_for_download(rar_files, + torr_client) # Esperamos mientras se descarga el RAR + if rar_file and save_path_videos: # Si se ha descargado el RAR... + dp = dialog_progress_bg('Alfa %s' % torr_client) + video_file, rar, video_path, erase_file_path = torrent.extract_files(rar_file, \ + save_path_videos, password, dp, + item, + torr_client) # ... extraemos el vídeo del RAR + dp.close() + + # Reproducimos el vídeo extraido, si no hay nada en reproducción + while is_playing() and rar and not xbmc.abortRequested: + time.sleep(3) # Repetimos cada intervalo + if rar and not xbmc.abortRequested: + time.sleep(1) + video_play = filetools.join(video_path, video_file) + log("##### video_play: %s" % video_play) + playlist = xbmc.PlayList(xbmc.PLAYLIST_VIDEO) + playlist.clear() + playlist.add(video_play, xlistitem) + xbmc_player.play(playlist) + + if seleccion > 1: + # Seleccionamos que clientes torrent soportamos para el marcado de vídeos vistos: asumimos que todos funcionan + torrent.mark_auto_as_watched(item) + + # Si se ha extraido un RAR, se pregunta para borrar los archivos después de reproducir el vídeo (plugins externos) + while is_playing() and rar and not xbmc.abortRequested: + time.sleep(3) # Repetimos cada intervalo + if rar and not xbmc.abortRequested: + if dialog_yesno('Alfa %s' % torr_client, '¿Borrar las descargas del RAR y Vídeo?'): + log("##### erase_file_path: %s" % erase_file_path) + try: + torr_data, deamon_url, index = torrent.get_tclient_data(folder_torr, torr_client) + if torr_data and deamon_url: + data = httptools.downloadpage('%sdelete/%s' % (deamon_url, index), timeout=5, + alfa_s=True).data + time.sleep(1) + if filetools.isdir(erase_file_path): + filetools.rmdirtree(erase_file_path) + elif filetools.exists(erase_file_path) and filetools.isfile(erase_file_path): + filetools.remove(erase_file_path) + except: + logger.error(traceback.format_exc(1)) + elementum_dl = config.get_setting("elementum_dl", server="torrent", + default='') # Si salvamos el cambio de Elementum + if elementum_dl: + config.set_setting("elementum_dl", "", server="torrent") # lo reseteamos en Alfa + xbmcaddon.Addon(id="plugin.video.%s" % torrent_options[seleccion][0].replace('Plugin externo: ', '')) \ + .setSetting('download_storage', elementum_dl) # y lo reseteamos en Elementum + + +def log(texto): + xbmc.log(texto, xbmc.LOGNOTICE) - # Y cerramos el progreso - progreso.close() diff --git a/platformcode/recaptcha.py b/platformcode/recaptcha.py index 57f4a68b..3d34b640 100644 --- a/platformcode/recaptcha.py +++ b/platformcode/recaptcha.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- +from builtins import range import xbmcgui - from core import httptools from core import scrapertools from platformcode import config diff --git a/platformcode/subtitletools.py b/platformcode/subtitletools.py index bd30ff93..b4294efc 100644 --- a/platformcode/subtitletools.py +++ b/platformcode/subtitletools.py @@ -1,17 +1,34 @@ # -*- coding: utf-8 -*- +from __future__ import print_function +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + +if PY3: + #from future import standard_library + #standard_library.install_aliases() + import urllib.parse as urllib # Es muy lento en PY2. En PY3 es nativo +else: + import urllib # Usamos el nativo de PY2 que es más rápido + import os import re import string -import urllib + from unicodedata import normalize +from core import filetools +from core import httptools +from core import jsontools +from core import scrapertools import xbmc import xbmcgui - from platformcode import config, logger -allchars = string.maketrans('', '') +if PY3: allchars = str.maketrans('', '') +if not PY3: allchars = string.maketrans('', '') deletechars = ',\\/:*"<>|?' @@ -38,14 +55,14 @@ def regex_tvshow(compare, file, sub=""): for regex in regex_expressions: response_file = re.findall(regex, file) if len(response_file) > 0: - print "Regex File Se: %s, Ep: %s," % (str(response_file[0][0]), str(response_file[0][1]),) + print("Regex File Se: %s, Ep: %s," % (str(response_file[0][0]), str(response_file[0][1]),)) tvshow = 1 if not compare: title = re.split(regex, file)[0] for char in ['[', ']', '_', '(', ')', '.', '-']: title = title.replace(char, ' ') if title.endswith(" "): title = title.strip() - print "title: %s" % title + print("title: %s" % title) return title, response_file[0][0], response_file[0][1] else: break @@ -74,7 +91,7 @@ def set_Subtitle(): logger.info() exts = [".srt", ".sub", ".txt", ".smi", ".ssa", ".ass"] - subtitle_folder_path = os.path.join(config.get_data_path(), "subtitles") + subtitle_folder_path = filetools.join(config.get_data_path(), "subtitles") subtitle_type = config.get_setting("subtitle_type") @@ -90,9 +107,9 @@ def set_Subtitle(): config.set_setting("subtitlepath_folder", subtitle_path) else: subtitle_path = config.get_setting("subtitlepath_keyboard") - long = len(subtitle_path) - if long > 0: - if subtitle_path.startswith("http") or subtitle_path[long - 4, long] in exts: + long_v = len(subtitle_path) + if long_v > 0: + if subtitle_path.startswith("http") or subtitle_path[long_v - 4, long] in exts: logger.info("Con subtitulo : " + subtitle_path) xbmc.Player().setSubtitles(subtitle_path) return @@ -106,13 +123,13 @@ def set_Subtitle(): tvshow_title, season, episode = regex_tvshow(False, subtitle_name) try: if episode != "": - Subnames = glob.glob(os.path.join(subtitle_path, "Tvshows", tvshow_title, + Subnames = glob.glob(filetools.join(subtitle_path, "Tvshows", tvshow_title, "%s %sx%s" % (tvshow_title, season, episode) + "*.??.???")) else: - Subnames = glob.glob(os.path.join(subtitle_path, "Movies", subtitle_name + "*.??.???")) + Subnames = glob.glob(filetools.join(subtitle_path, "Movies", subtitle_name + "*.??.???")) for Subname in Subnames: if os.path.splitext(Subname)[1] in exts: - logger.info("Con subtitulo : " + os.path.split(Subname)[1]) + logger.info("Con subtitulo : " + filetools.split(Subname)[1]) xbmc.Player().setSubtitles((Subname)) except: logger.error("error al cargar subtitulos") @@ -147,13 +164,13 @@ def searchSubtitle(item): if config.get_setting("subtitle_type") == 0: subtitlepath = config.get_setting("subtitlepath_folder") if subtitlepath == "": - subtitlepath = os.path.join(config.get_data_path(), "subtitles") + subtitlepath = filetools.join(config.get_data_path(), "subtitles") config.set_setting("subtitlepath_folder", subtitlepath) elif config.get_setting("subtitle_type") == 1: subtitlepath = config.get_setting("subtitlepath_keyboard") if subtitlepath == "": - subtitlepath = os.path.join(config.get_data_path(), "subtitles") + subtitlepath = filetools.join(config.get_data_path(), "subtitles") config.set_setting("subtitlepathkeyboard", subtitlepath) elif subtitlepath.startswith("http"): subtitlepath = config.get_setting("subtitlepath_folder") @@ -161,27 +178,27 @@ def searchSubtitle(item): else: subtitlepath = config.get_setting("subtitlepath_folder") if subtitlepath == "": - subtitlepath = os.path.join(config.get_data_path(), "subtitles") + subtitlepath = filetools.join(config.get_data_path(), "subtitles") config.set_setting("subtitlepath_folder", subtitlepath) - if not os.path.exists(subtitlepath): + if not filetools.exists(subtitlepath): try: - os.mkdir(subtitlepath) + filetools.mkdir(subtitlepath) except: logger.error("error no se pudo crear path subtitulos") return - path_movie_subt = xbmc.translatePath(os.path.join(subtitlepath, "Movies")) - if not os.path.exists(path_movie_subt): + path_movie_subt = xbmc.translatePath(filetools.join(subtitlepath, "Movies")) + if not filetools.exists(path_movie_subt): try: - os.mkdir(path_movie_subt) + filetools.mkdir(path_movie_subt) except: logger.error("error no se pudo crear el path Movies") return full_path_tvshow = "" - path_tvshow_subt = xbmc.translatePath(os.path.join(subtitlepath, "Tvshows")) - if not os.path.exists(path_tvshow_subt): + path_tvshow_subt = xbmc.translatePath(filetools.join(subtitlepath, "Tvshows")) + if not filetools.exists(path_tvshow_subt): try: - os.mkdir(path_tvshow_subt) + filetools.mkdir(path_tvshow_subt) except: logger.error("error no pudo crear el path Tvshows") return @@ -189,20 +206,20 @@ def searchSubtitle(item): title_new = title = urllib.unquote_plus(item.title) else: title_new = title = urllib.unquote_plus(item.show + " - " + item.title) - path_video_temp = xbmc.translatePath(os.path.join(config.get_runtime_path(), "resources", "subtitle.mp4")) - if not os.path.exists(path_video_temp): + path_video_temp = xbmc.translatePath(filetools.join(config.get_runtime_path(), "resources", "subtitle.mp4")) + if not filetools.exists(path_video_temp): logger.error("error : no existe el video temporal de subtitulos") return - # path_video_temp = xbmc.translatePath(os.path.join( ,video_temp + ".mp4" )) + # path_video_temp = xbmc.translatePath(filetools.join( ,video_temp + ".mp4" )) title_new = _normalize(title_new) tvshow_title, season, episode = regex_tvshow(False, title_new) if episode != "": - full_path_tvshow = xbmc.translatePath(os.path.join(path_tvshow_subt, tvshow_title)) - if not os.path.exists(full_path_tvshow): - os.mkdir(full_path_tvshow) # title_new + ".mp4" + full_path_tvshow = xbmc.translatePath(filetools.join(path_tvshow_subt, tvshow_title)) + if not filetools.exists(full_path_tvshow): + filetools.mkdir(full_path_tvshow) # title_new + ".mp4" full_path_video_new = xbmc.translatePath( - os.path.join(full_path_tvshow, "%s %sx%s.mp4" % (tvshow_title, season, episode))) + filetools.join(full_path_tvshow, "%s %sx%s.mp4" % (tvshow_title, season, episode))) logger.info(full_path_video_new) listitem = xbmcgui.ListItem(title_new, iconImage="DefaultVideo.png", thumbnailImage="") listitem.setInfo("video", @@ -210,14 +227,14 @@ def searchSubtitle(item): "tvshowtitle": tvshow_title}) else: - full_path_video_new = xbmc.translatePath(os.path.join(path_movie_subt, title_new + ".mp4")) + full_path_video_new = xbmc.translatePath(filetools.join(path_movie_subt, title_new + ".mp4")) listitem = xbmcgui.ListItem(title, iconImage="DefaultVideo.png", thumbnailImage="") listitem.setInfo("video", {"Title": title_new, "Genre": "Movies"}) - import shutil, time + import time try: - shutil.copy(path_video_temp, full_path_video_new) + filetools.copy(path_video_temp, full_path_video_new) copy = True logger.info("nuevo path =" + full_path_video_new) time.sleep(2) @@ -242,10 +259,10 @@ def searchSubtitle(item): continue time.sleep(1) - os.remove(full_path_video_new) + filetools.remove(full_path_video_new) try: if full_path_tvshow != "": - os.rmdir(full_path_tvshow) + filetools.rmdir(full_path_tvshow) except OSError: pass @@ -267,3 +284,70 @@ def saveSubtitleName(item): else: config.set_setting("subtitle_name", title) return + + +def get_from_subdivx(sub_url): + + """ + :param sub_url: Url de descarga del subtitulo alojado en suvdivx.com + Por Ejemplo: http://www.subdivx.com/bajar.php?id=573942&u=8 + + :return: La ruta al subtitulo descomprimido + """ + + logger.info() + + sub = '' + sub_dir = os.path.join(config.get_data_path(), 'temp_subs') + + if os.path.exists(sub_dir): + for sub_file in os.listdir(sub_dir): + old_sub = os.path.join(sub_dir, sub_file) + os.remove(old_sub) + else: + os.mkdir(sub_dir) + + sub_url = sub_url.replace("&", "&") + sub_data = httptools.downloadpage(sub_url, follow_redirects=False) + if 'x-frame-options' not in sub_data.headers: + sub_url = '%s' % sub_data.headers['location'] + ext = sub_url[-4::] + file_id = "subtitle%s" % ext + filename = os.path.join(sub_dir, file_id) + try: + data_dl = httptools.downloadpage(sub_url).data + filetools.write(filename, data_dl) + sub = extract_file_online(sub_dir, filename) + except: + logger.info('sub no valido') + else: + logger.info('sub no valido') + return sub + + +def extract_file_online(path, filename): + + """ + :param path: Ruta donde se encuentra el archivo comprimido + + :param filename: Nombre del archivo comprimido + + :return: Devuelve la ruta al subtitulo descomprimido + """ + + logger.info() + + url = "http://online.b1.org/rest/online/upload" + + data = httptools.downloadpage(url, file=filename).data + + result = jsontools.load(scrapertools.find_single_match(data, "result.listing = ([^;]+);")) + compressed = result["name"] + extracted = result["children"][0]["name"] + + dl_url = "http://online.b1.org/rest/online/download/%s/%s" % (compressed, extracted) + extracted_path = os.path.join(path, extracted) + data_dl = httptools.downloadpage(dl_url).data + filetools.write(extracted_path, data_dl) + + return extracted_path diff --git a/platformcode/unify.py b/platformcode/unify.py index 0c8c41af..92ceda10 100644 --- a/platformcode/unify.py +++ b/platformcode/unify.py @@ -6,189 +6,167 @@ # datos obtenidos de las paginas # ---------------------------------------------------------- -import re +# from builtins import str +import sys + +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + +import os import unicodedata +import re -import config - +from platformcode import config +from core.item import Item from core import scrapertools from platformcode import logger -thumb_dict = { - "numbers": "http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-10/256/Numbers-icon.png", - "a": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-A-black-icon.png", - "accion": "https://s14.postimg.cc/sqy3q2aht/action.png", - "actors": "https://i.postimg.cc/tC2HMhVV/actors.png", - "adolescente" : "https://s10.postimg.cc/inq7u4p61/teens.png", - "adultos": "https://s10.postimg.cc/s8raxc51l/adultos.png", - "adults": "https://s10.postimg.cc/s8raxc51l/adultos.png", - "alcinema": "http://icons.iconarchive.com/icons/chromatix/aerial/256/movie-icon.png", #"http://icons.iconarchive.com/icons/itzikgur/my-seven/256/Movies-Films-icon.png", - "all": "https://s10.postimg.cc/h1igpgw0p/todas.png", - "alphabet": "https://s10.postimg.cc/4dy3ytmgp/a-z.png", - "animacion": "https://s14.postimg.cc/vl193mupd/animation.png", - "anime" : "https://s10.postimg.cc/n9mc2ikzt/anime.png", - "artes marciales" : "https://s10.postimg.cc/4u1v51tzt/martial_arts.png", - "asiaticas" : "https://i.postimg.cc/Xq0HXD5d/asiaticas.png", - "audio": "https://s10.postimg.cc/b34nern7d/audio.png", - "aventura": "http://icons.iconarchive.com/icons/sirubico/movie-genre/256/Adventure-2-icon.png",#"https://s14.postimg.cc/ky7fy5he9/adventure.png", - "b": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-B-black-icon.png", - "belico": "https://s14.postimg.cc/5e027lru9/war.png", - "biografia" : "https://s10.postimg.cc/jq0ecjxnt/biographic.png", - "c": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-C-black-icon.png", - "carreras": "https://s14.postimg.cc/yt5qgdr69/races.png", - "cast": "https://i.postimg.cc/qvfP5Xvt/cast.png", - "categories": "https://s10.postimg.cc/v0ako5lmh/categorias.png", - "ciencia ficcion": "https://s14.postimg.cc/8kulr2jy9/scifi.png", - "cine negro" : "https://s10.postimg.cc/6ym862qgp/noir.png", - "colections": "https://s10.postimg.cc/ywnwjvytl/colecciones.png", - "comedia": "https://s14.postimg.cc/9ym8moog1/comedy.png", - "cortometraje" : "https://s10.postimg.cc/qggvlxndl/shortfilm.png", - "country": "https://s10.postimg.cc/yz0h81j15/pais.png", - "crimen": "https://s14.postimg.cc/duzkipjq9/crime.png", - "d": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-D-black-icon.png", - "de la tv": "https://s10.postimg.cc/94gj0iwh5/image.png", - "deporte": "https://s14.postimg.cc/x1crlnnap/sports.png", - "destacadas": "https://s10.postimg.cc/yu40x8q2x/destacadas.png", - "documental": "https://s10.postimg.cc/68aygmmcp/documentales.png", - "documentaries": "https://s10.postimg.cc/68aygmmcp/documentales.png", - "doramas":"https://s10.postimg.cc/h4dyr4nfd/doramas.png", - "drama": "https://s14.postimg.cc/fzjxjtnxt/drama.png", - "e": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-E-black-icon.png", - "erotica" : "https://s10.postimg.cc/dcbb9bfx5/erotic.png", - "espanolas" : "https://s10.postimg.cc/x1y6zikx5/spanish.png", - "estrenos" : "https://s10.postimg.cc/sk8r9xdq1/estrenos.png", - "extranjera": "https://s10.postimg.cc/f44a4eerd/foreign.png", - "f": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-F-black-icon.png", - "familiar": "https://s14.postimg.cc/jj5v9ndsx/family.png", - "fantasia": "https://s14.postimg.cc/p7c60ksg1/fantasy.png", - "fantastico" : "https://s10.postimg.cc/tedufx5eh/fantastic.png", - "favorites": "https://s10.postimg.cc/rtg147gih/favoritas.png", - "g": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-G-black-icon.png", - "genres": "https://s10.postimg.cc/6c4rx3x1l/generos.png", - "h": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-H-black-icon.png", - "historica": "https://s10.postimg.cc/p1faxj6yh/historic.png", - "horror" : "https://s10.postimg.cc/8exqo6yih/horror2.png", - "hot": "https://s10.postimg.cc/yu40x8q2x/destacadas.png", - "i": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-I-black-icon.png", - "infantil": "https://s14.postimg.cc/4zyq842mp/childish.png", - "intriga": "https://s14.postimg.cc/5qrgdimw1/intrigue.png", - "j": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-J-black-icon.png", - "k": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-K-black-icon.png", - "l": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-L-black-icon.png", - "language": "https://s10.postimg.cc/6wci189ft/idioma.png", - "last": "https://s10.postimg.cc/i6ciuk0eh/ultimas.png", - "lat": "https://i.postimg.cc/Gt8fMH0J/lat.png", - "latino" : "https://s10.postimg.cc/swip0b86h/latin.png", - "m": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-M-black-icon.png", - "mexicanas" : "https://s10.postimg.cc/swip0b86h/latin.png", - "misterio": "https://s14.postimg.cc/3m73cg8ep/mistery.png", - "more voted": "https://s10.postimg.cc/lwns2d015/masvotadas.png", - "more watched": "https://s10.postimg.cc/c6orr5neh/masvistas.png", - "movies": "https://s10.postimg.cc/fxtqzdog9/peliculas.png", - "musical": "https://s10.postimg.cc/hy7fhtecp/musical.png", - "n": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-N-black-icon.png", - "new episodes": "https://s10.postimg.cc/fu4iwpnqh/nuevoscapitulos.png", - "newest": "http://icons.iconarchive.com/icons/laurent-baumann/creme/128/Location-News-icon.png", #"http://icons.iconarchive.com/icons/uiconstock/ios8-setting/128/news-icon.png", - "nextpage": "http://icons.iconarchive.com/icons/custom-icon-design/pretty-office-5/256/navigate-right-icon.png", #"http://icons.iconarchive.com/icons/custom-icon-design/office/256/forward-icon.png", #"http://icons.iconarchive.com/icons/ahmadhania/spherical/128/forward-icon.png", - "o": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-O-black-icon.png", - "others": "http://icons.iconarchive.com/icons/limav/movie-genres-folder/128/Others-icon.png", - "p": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-P-black-icon.png", - "peleas" : "https://s10.postimg.cc/7a3ojbjwp/Fight.png", - "policial" : "https://s10.postimg.cc/wsw0wbgbd/cops.png", - "premieres": "https://s10.postimg.cc/sk8r9xdq1/estrenos.png", - "q": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-Q-black-icon.png", - "quality": "https://s10.postimg.cc/9bbojsbjd/calidad.png", - "r": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-R-black-icon.png", - "recents": "https://s10.postimg.cc/649u24kp5/recents.png", - "recomendadas": "https://s10.postimg.cc/7xk1oqccp/recomendadas.png", - "recomended": "https://s10.postimg.cc/7xk1oqccp/recomendadas.png", - "religion" : "https://s10.postimg.cc/44j2skquh/religion.png", - "romance" : "https://s10.postimg.cc/yn8vdll6x/romance.png", - "romantica": "https://s14.postimg.cc/8xlzx7cht/romantic.png", - "s": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-S-black-icon.png", - "search": "http://icons.iconarchive.com/icons/jamespeng/movie/256/database-icon.png", - "suspenso": "https://s10.postimg.cc/7peybxdfd/suspense.png", - "t": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-T-black-icon.png", - "telenovelas": "https://i.postimg.cc/QCXZkyDM/telenovelas.png", - "terror": "https://s14.postimg.cc/thqtvl52p/horror.png", - "thriller": "https://s14.postimg.cc/uwsekl8td/thriller.png", - "tvshows": "https://s10.postimg.cc/kxvslawe1/series.png", - "u": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-U-black-icon.png", - "ultimiarrivi" : "http://icons.iconarchive.com/icons/saki/snowish/128/Extras-internet-download-icon.png", - "updated" : "https://s10.postimg.cc/46m3h6h9l/updated.png", - "v": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-V-black-icon.png", - "vose": "https://i.postimg.cc/kgmnbd8h/vose.png", - "w": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-W-black-icon.png", - "western": "https://s10.postimg.cc/5wc1nokjt/western.png", - "x": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-X-black-icon.png", - "y": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-Y-black-icon.png", - "year": "https://s10.postimg.cc/atzrqg921/a_o.png", - "z": "http://icons.iconarchive.com/icons/hydrattz/multipurpose-alphabet/256/Letter-Z-black-icon.png" - } +thumb_dict = {"movies": "https://s10.postimg.cc/fxtqzdog9/peliculas.png", + "tvshows": "https://s10.postimg.cc/kxvslawe1/series.png", + "on air": "https://i.postimg.cc/HLLJWMcr/en-emision.png", + "all": "https://s10.postimg.cc/h1igpgw0p/todas.png", + "genres": "https://s10.postimg.cc/6c4rx3x1l/generos.png", + "search": "https://s10.postimg.cc/v985e2izd/buscar.png", + "quality": "https://s10.postimg.cc/9bbojsbjd/calidad.png", + "audio": "https://s10.postimg.cc/b34nern7d/audio.png", + "newest": "https://s10.postimg.cc/g1s5tf1bt/novedades.png", + "last": "https://s10.postimg.cc/i6ciuk0eh/ultimas.png", + "hot": "https://s10.postimg.cc/yu40x8q2x/destacadas.png", + "year": "https://s10.postimg.cc/atzrqg921/a_o.png", + "alphabet": "https://s10.postimg.cc/4dy3ytmgp/a-z.png", + "recomended": "https://s10.postimg.cc/7xk1oqccp/recomendadas.png", + "more watched": "https://s10.postimg.cc/c6orr5neh/masvistas.png", + "more voted": "https://s10.postimg.cc/lwns2d015/masvotadas.png", + "favorites": "https://s10.postimg.cc/rtg147gih/favoritas.png", + "colections": "https://s10.postimg.cc/ywnwjvytl/colecciones.png", + "categories": "https://s10.postimg.cc/v0ako5lmh/categorias.png", + "premieres": "https://s10.postimg.cc/sk8r9xdq1/estrenos.png", + "documentaries": "https://s10.postimg.cc/68aygmmcp/documentales.png", + "language": "https://s10.postimg.cc/6wci189ft/idioma.png", + "new episodes": "https://s10.postimg.cc/fu4iwpnqh/nuevoscapitulos.png", + "country": "https://s10.postimg.cc/yz0h81j15/pais.png", + "adults": "https://s10.postimg.cc/s8raxc51l/adultos.png", + "recents": "https://s10.postimg.cc/649u24kp5/recents.png", + "updated": "https://s10.postimg.cc/46m3h6h9l/updated.png", + "actors": "https://i.postimg.cc/tC2HMhVV/actors.png", + "cast": "https://i.postimg.cc/qvfP5Xvt/cast.png", + "lat": "https://i.postimg.cc/Gt8fMH0J/lat.png", + "vose": "https://i.postimg.cc/kgmnbd8h/vose.png", + "accion": "https://s14.postimg.cc/sqy3q2aht/action.png", + "adolescente": "https://s10.postimg.cc/inq7u4p61/teens.png", + "adultos": "https://s10.postimg.cc/s8raxc51l/adultos.png", + "animacion": "https://s14.postimg.cc/vl193mupd/animation.png", + "anime": "https://s10.postimg.cc/n9mc2ikzt/anime.png", + "artes marciales": "https://s10.postimg.cc/4u1v51tzt/martial_arts.png", + "asiaticas": "https://i.postimg.cc/Xq0HXD5d/asiaticas.png", + "aventura": "https://s14.postimg.cc/ky7fy5he9/adventure.png", + "belico": "https://s14.postimg.cc/5e027lru9/war.png", + "biografia": "https://s10.postimg.cc/jq0ecjxnt/biographic.png", + "carreras": "https://s14.postimg.cc/yt5qgdr69/races.png", + "ciencia ficcion": "https://s14.postimg.cc/8kulr2jy9/scifi.png", + "cine negro": "https://s10.postimg.cc/6ym862qgp/noir.png", + "comedia": "https://s14.postimg.cc/9ym8moog1/comedy.png", + "cortometraje": "https://s10.postimg.cc/qggvlxndl/shortfilm.png", + "crimen": "https://s14.postimg.cc/duzkipjq9/crime.png", + "de la tv": "https://s10.postimg.cc/94gj0iwh5/image.png", + "deporte": "https://s14.postimg.cc/x1crlnnap/sports.png", + "destacadas": "https://s10.postimg.cc/yu40x8q2x/destacadas.png", + "documental": "https://s10.postimg.cc/68aygmmcp/documentales.png", + "doramas": "https://s10.postimg.cc/h4dyr4nfd/doramas.png", + "drama": "https://s14.postimg.cc/fzjxjtnxt/drama.png", + "erotica": "https://s10.postimg.cc/dcbb9bfx5/erotic.png", + "espanolas": "https://s10.postimg.cc/x1y6zikx5/spanish.png", + "estrenos": "https://s10.postimg.cc/sk8r9xdq1/estrenos.png", + "extranjera": "https://s10.postimg.cc/f44a4eerd/foreign.png", + "familiar": "https://s14.postimg.cc/jj5v9ndsx/family.png", + "fantasia": "https://s14.postimg.cc/p7c60ksg1/fantasy.png", + "fantastico": "https://s10.postimg.cc/tedufx5eh/fantastic.png", + "historica": "https://s10.postimg.cc/p1faxj6yh/historic.png", + "horror": "https://s10.postimg.cc/8exqo6yih/horror2.png", + "infantil": "https://s14.postimg.cc/4zyq842mp/childish.png", + "intriga": "https://s14.postimg.cc/5qrgdimw1/intrigue.png", + "latino": "https://s10.postimg.cc/swip0b86h/latin.png", + "mexicanas": "https://s10.postimg.cc/swip0b86h/latin.png", + "misterio": "https://s14.postimg.cc/3m73cg8ep/mistery.png", + "musical": "https://s10.postimg.cc/hy7fhtecp/musical.png", + "peleas": "https://s10.postimg.cc/7a3ojbjwp/Fight.png", + "policial": "https://s10.postimg.cc/wsw0wbgbd/cops.png", + "recomendadas": "https://s10.postimg.cc/7xk1oqccp/recomendadas.png", + "religion": "https://s10.postimg.cc/44j2skquh/religion.png", + "romance": "https://s10.postimg.cc/yn8vdll6x/romance.png", + "romantica": "https://s14.postimg.cc/8xlzx7cht/romantic.png", + "suspenso": "https://s10.postimg.cc/7peybxdfd/suspense.png", + "telenovelas": "https://i.postimg.cc/QCXZkyDM/telenovelas.png", + "terror": "https://s14.postimg.cc/thqtvl52p/horror.png", + "thriller": "https://s14.postimg.cc/uwsekl8td/thriller.png", + "western": "https://s10.postimg.cc/5wc1nokjt/western.png" + } + def set_genre(string): - #logger.info() + # logger.info() - genres_dict = {'accion':['azione'], - 'adultos':['adulto','adulti'], - 'animacion':['animazione'], - 'adolescente':['adolescente', 'adolescenti'], - 'aventura':['avventura'], - 'belico':['guerra','guerriglia'], - 'biografia':['biografia', 'biografie', 'biografico'], - 'ciencia ficcion':['ciencia ficcion', 'cienciaficcion', 'sci fi', 'c ficcion'], - 'cine negro':['film noir'], - 'comedia':['commedia', 'commedie'], - 'cortometraje':['cortometraggio', 'corto', 'corti'], - 'de la tv':['della tv', 'televisione', 'tv'], - 'deporte':['deporte', 'deportes'], - 'destacadas':['destacada', 'destacadas'], - 'documental':['documentario', 'documentari'], - 'erotica':['erotica', 'erotica +', 'eroticas', 'eroticas +', 'erotico', 'erotico +'], - 'estrenos':['estrenos', 'estrenos'], - 'extranjera':['extrajera', 'extrajeras', 'foreign'], - 'familiar':['familiare', 'famiglia'], - 'fantastico':['fantastico', 'fantastica', 'fantastici'], - 'historica':['storico', 'storia'], - 'infantil':['bambini', 'infanzia'], - 'musical':['musicale', 'musical', 'musica'], - 'numbers': ['0','1','2','3','4','5','6','7','8','9'], - 'policial':['politico', 'politici', 'politica'], - 'recomendadas':['raccomandato', 'raccomandati'], - 'religion':['religione', 'religioso', 'religiosa','religiosi'], - 'romantica':['romantica', 'romantico', 'romantici'], - 'suspenso':['suspenso', 'suspense'], - 'thriller':['thriller', 'thrillers'], - 'western':['western', 'westerns'] + genres_dict = {'accion': ['accion', 'action', 'accion y aventura', 'action & adventure'], + 'adultos': ['adultos', 'adultos +', 'adulto'], + 'animacion': ['animacion', 'animacion e infantil', 'dibujos animados'], + 'adolescente': ['adolescente', 'adolescentes', 'adolescencia', 'adolecentes'], + 'aventura': ['aventura', 'aventuras'], + 'belico': ['belico', 'belica', 'belicas', 'guerra', 'belico guerra'], + 'biografia': ['biografia', 'biografias', 'biografica', 'biograficas', 'biografico'], + 'ciencia ficcion': ['ciencia ficcion', 'cienciaficcion', 'sci fi', 'c ficcion'], + 'cine negro': ['film noir', 'negro'], + 'comedia': ['comedia', 'comedias'], + 'cortometraje': ['cortometraje', 'corto', 'cortos'], + 'de la tv': ['de la tv', 'television', 'tv'], + 'deporte': ['deporte', 'deportes'], + 'destacadas': ['destacada', 'destacadas'], + 'documental': ['documental', 'documentales'], + 'erotica': ['erotica', 'erotica +', 'eroticas', 'eroticas +', 'erotico', 'erotico +'], + 'estrenos': ['estrenos', 'estrenos'], + 'extranjera': ['extrajera', 'extrajeras', 'foreign'], + 'familiar': ['familiar', 'familia'], + 'fantastico': ['fantastico', 'fantastica', 'fantasticas'], + 'historica': ['historica', 'historicas', 'historico', 'historia'], + 'infantil': ['infantil', 'kids'], + 'musical': ['musical', 'musicales', 'musica'], + 'policial': ['policial', 'policiaco', 'policiaca'], + 'recomendadas': ['recomedada', 'recomendadas'], + 'religion': ['religion', 'religiosa', 'religiosas'], + 'romantica': ['romantica', 'romanticas', 'romantico'], + 'suspenso': ['suspenso', 'suspense'], + 'thriller': ['thriller', 'thrillers'], + 'western': ['western', 'westerns', 'oeste western'] } - string = re.sub(r'peliculas de |pelicula de la |peli |cine ','', string) - for genre, variants in genres_dict.items(): + string = re.sub(r'peliculas de |pelicula de la |peli |cine ', '', string) + for genre, variants in list(genres_dict.items()): if string in variants: string = genre return string + def remove_format(string): - #logger.info() - #logger.debug('entra en remove: %s' % string) + # logger.info() + # logger.debug('entra en remove: %s' % string) string = string.rstrip() string = re.sub(r'(\[|\[\/)(?:color|COLOR|b|B|i|I).*?\]|\[|\]|\(|\)|\:|\.', '', string) - #logger.debug('sale de remove: %s' % string) + # logger.debug('sale de remove: %s' % string) return string + def normalize(string): - string = string.decode('utf-8') + if not PY3 and isinstance(string, str): + string = string.decode('utf-8') normal = ''.join((c for c in unicodedata.normalize('NFD', unicode(string)) if unicodedata.category(c) != 'Mn')) return normal def simplify(string): - - #logger.info() - #logger.debug('entra en simplify: %s'%string) + # logger.info() + # logger.debug('entra en simplify: %s'%string) string = remove_format(string) - string = string.replace('-',' ').replace('_',' ') - string = re.sub(r'\d+','', string) + string = string.replace('-', ' ').replace('_', ' ') + string = re.sub(r'\d+', '', string) string = string.strip() notilde = normalize(string) @@ -197,12 +175,13 @@ def simplify(string): except: pass string = string.lower() - #logger.debug('sale de simplify: %s' % string) + # logger.debug('sale de simplify: %s' % string) return string + def add_languages(title, languages): - #logger.info() + # logger.info() if isinstance(languages, list): for language in languages: @@ -211,14 +190,55 @@ def add_languages(title, languages): title = '%s %s' % (title, set_color(languages, languages)) return title + +def add_info_plot(plot, languages, quality): + # logger.info() + last = '[/I][/B]\n' + + if languages: + l_part = '[COLOR yellowgreen][B][I]Idiomas:[/COLOR] ' + mid = '' + + if isinstance(languages, list): + for language in languages: + mid += '%s ' % (set_color(language, language)) + else: + mid = '%s ' % (set_color(languages, languages)) + + p_lang = '%s%s%s' % (l_part, mid, last) + + if quality: + q_part = '[COLOR yellowgreen][B][I]Calidad:[/COLOR] ' + p_quality = '%s%s%s' % (q_part, quality, last) + + if languages and quality: + plot_ = '%s%s\n%s' % (p_lang, p_quality, plot) + + elif languages: + plot_ = '%s\n%s' % (p_lang, plot) + + elif quality: + plot_ = '%s\n%s' % (p_quality, plot) + + else: + plot_ = plot + + return plot_ + + def set_color(title, category): - #logger.info() + # logger.info() + from core import jsontools + + styles_path = os.path.join(config.get_runtime_path(), 'resources', 'color_styles.json') + preset = config.get_setting("preset_style", default="Estilo 1") + color_setting = jsontools.load((open(styles_path, "r").read()))[preset] color_scheme = {'otro': 'white', 'dual': 'white'} - #logger.debug('category antes de remove: %s' % category) + # logger.debug('category antes de remove: %s' % category) category = remove_format(category).lower() - #logger.debug('category despues de remove: %s' % category) + # logger.debug('category despues de remove: %s' % category) # Lista de elementos posibles en el titulo color_list = ['movie', 'tvshow', 'year', 'rating_1', 'rating_2', 'rating_3', 'quality', 'cast', 'lat', 'vose', 'vos', 'vo', 'server', 'library', 'update', 'no_update'] @@ -234,46 +254,45 @@ def set_color(title, category): if custom_colors: color_scheme[element] = remove_format(config.get_setting('%s_color' % element)) else: - color_scheme[element] = 'white' + color_scheme[element] = remove_format(color_setting.get(element, 'white')) + # color_scheme[element] = 'white' + if category in ['update', 'no_update']: - #logger.debug('title antes de updates: %s' % title) - title= re.sub(r'\[COLOR .*?\]','[COLOR %s]' % color_scheme[category],title) + # logger.debug('title antes de updates: %s' % title) + title = re.sub(r'\[COLOR .*?\]', '[COLOR %s]' % color_scheme[category], title) else: if category not in ['movie', 'tvshow', 'library', 'otro']: - title = "[COLOR %s][%s][/COLOR]"%(color_scheme[category], title) + title = "[COLOR %s][%s][/COLOR]" % (color_scheme[category], title) else: title = "[COLOR %s]%s[/COLOR]" % (color_scheme[category], title) return title -def set_lang(language): - #logger.info() - cast =['castellano','espanol','cast','esp','espaol', 'es','zc', 'spa', 'spanish', 'vc'] - ita =['italiano','italian','ita','it'] - lat=['latino','lat','la', 'espanol latino', 'espaol latino', 'zl', 'mx', 'co', 'vl'] - vose=['subtitulado','subtitulada','sub','sub espanol','vose','espsub','su','subs castellano', - 'sub: español', 'vs', 'zs', 'vs', 'english-spanish subs', 'ingles sub espanol'] - sub_ita=['sottotitolato','sottotitolata','sub','sub ita','subs italiano', - 'sub: italiano', 'inglese sottotitolato'] - vos=['vos', 'sub ingles', 'engsub','ingles subtitulado', 'sub: ingles'] - vo=['ingles', 'en','vo', 'ovos', 'eng','v.o', 'english'] - dual=['dual'] +def set_lang(language): + # logger.info() + + cast = ['castellano', 'español', 'espanol', 'cast', 'esp', 'espaol', 'es', 'zc', 'spa', 'spanish', 'vc'] + ita = ['italiano', 'italian', 'ita', 'it'] + lat = ['latino', 'lat', 'la', 'español latino', 'espanol latino', 'espaol latino', 'zl', 'mx', 'co', 'vl'] + vose = ['subtitulado', 'subtitulada', 'sub', 'sub espanol', 'vose', 'espsub', 'su', 'subs castellano', + 'sub: español', 'vs', 'zs', 'vs', 'english-spanish subs', 'ingles sub espanol', 'ingles sub español'] + vos = ['vos', 'sub ingles', 'engsub', 'vosi', 'ingles subtitulado', 'sub: ingles'] + vo = ['ingles', 'en', 'vo', 'ovos', 'eng', 'v.o', 'english'] + dual = ['dual'] language = scrapertools.decodeHtmlentities(language) old_lang = language language = simplify(language) - #logger.debug('language before simplify: %s' % language) - #logger.debug('old language: %s' % old_lang) + # logger.debug('language before simplify: %s' % language) + # logger.debug('old language: %s' % old_lang) if language in cast: language = 'cast' elif language in lat: language = 'lat' elif language in ita: language = 'ita' - elif language in sub_ita: - language = 'sub-ita' elif language in vose: language = 'vose' elif language in vos: @@ -285,67 +304,67 @@ def set_lang(language): else: language = 'otro' - #logger.debug('language after simplify: %s' % language) + # logger.debug('language after simplify: %s' % language) return language - - - def title_format(item): - #logger.info() + # logger.info() lang = False valid = True language_color = 'otro' + simple_language = '' - #logger.debug('item.title antes de formatear: %s' % item.title.lower()) + # logger.debug('item.title antes de formatear: %s' % item.title.lower()) # TODO se deberia quitar cualquier elemento que no sea un enlace de la lista de findvideos para quitar esto - #Palabras "prohibidas" en los titulos (cualquier titulo que contengas estas no se procesara en unify) + # Palabras "prohibidas" en los titulos (cualquier titulo que contengas estas no se procesara en unify) excluded_words = ['online', 'descarga', 'downloads', 'trailer', 'videoteca', 'gb', 'autoplay'] # Actions excluidos, (se define canal y action) los titulos que contengan ambos valores no se procesaran en unify - excluded_actions = [('videolibrary','get_episodes')] + excluded_actions = [('videolibrary', 'get_episodes')] - # Verifica si hay marca de visto de trakt - - visto = False - #logger.debug('titlo con visto? %s' % item.title) - - if '[[I]v[/I]]' in item.title or '[COLOR limegreen][v][/COLOR]' in item.title: - visto = True - - # Se elimina cualquier formato previo en el titulo - if item.action != '' and item.action !='mainlist': - item.title = remove_format(item.title) - - #logger.debug('visto? %s' % visto) - - # Evita que aparezcan los idiomas en los mainlist de cada canal - if item.action == 'mainlist': - item.language ='' - - info = item.infoLabels - #logger.debug('item antes de formatear: %s'%item) - - if hasattr(item,'text_color'): - item.text_color='' - - #Verifica el item sea valido para ser formateado por unify + # Verifica el item sea valido para ser formateado por unify if item.channel == 'trailertools' or (item.channel.lower(), item.action.lower()) in excluded_actions or \ - item.action=='': + item.action == '': valid = False else: for word in excluded_words: if word in item.title.lower(): valid = False break + if not valid: + return item - if valid and item.unify!=False: + # Verifica si hay marca de visto de trakt + + visto = False + # logger.debug('titlo con visto? %s' % item.title) + + if '[[I]v[/I]]' in item.title or '[COLOR limegreen][v][/COLOR]' in item.title: + visto = True + + # Se elimina cualquier formato previo en el titulo + if item.action != '' and item.action != 'mainlist' and item.unify: + item.title = remove_format(item.title) + + # logger.debug('visto? %s' % visto) + + # Evita que aparezcan los idiomas en los mainlist de cada canal + if item.action == 'mainlist': + item.language = '' + + info = item.infoLabels + # logger.debug('item antes de formatear: %s'%item) + + if hasattr(item, 'text_color'): + item.text_color = '' + + if valid and item.unify != False: # Formamos el titulo para serie, se debe definir contentSerieName # o show en el item para que esto funcione. @@ -354,25 +373,26 @@ def title_format(item): # Si se tiene la informacion en infolabels se utiliza if item.contentType == 'episode' and info['episode'] != '': if info['title'] == '': - info['title'] = '%s - Episodio %s'% (info['tvshowtitle'], info['episode']) + info['title'] = '%s - Episodio %s' % (info['tvshowtitle'], info['episode']) elif 'Episode' in info['title']: episode = info['title'].lower().replace('episode', 'episodio') info['title'] = '%s - %s' % (info['tvshowtitle'], episode.capitalize()) - elif info['episodio_titulo']!='': - #logger.debug('info[episode_titulo]: %s' % info['episodio_titulo']) + elif info['episodio_titulo'] != '': + # logger.debug('info[episode_titulo]: %s' % info['episodio_titulo']) if 'episode' in info['episodio_titulo'].lower(): episode = info['episodio_titulo'].lower().replace('episode', 'episodio') - item.title = '%sx%s - %s' % (info['season'],info['episode'], episode.capitalize()) + item.title = '%sx%s - %s' % (info['season'], info['episode'], episode.capitalize()) else: - item.title = '%sx%s - %s' % (info['season'], info['episode'], info['episodio_titulo'].capitalize()) + item.title = '%sx%s - %s' % ( + info['season'], info['episode'], info['episodio_titulo'].capitalize()) else: - item.title = '%sx%s - %s' % (info['season'],info['episode'], info['title']) + item.title = '%sx%s - %s' % (info['season'], info['episode'], info['title']) item.title = set_color(item.title, 'tvshow') else: # En caso contrario se utiliza el titulo proporcionado por el canal - #logger.debug ('color_scheme[tvshow]: %s' % color_scheme['tvshow']) + # logger.debug ('color_scheme[tvshow]: %s' % color_scheme['tvshow']) item.title = '%s' % set_color(item.title, 'tvshow') elif item.contentTitle: @@ -386,27 +406,27 @@ def title_format(item): item.title = '%s [V.Extend.]' % set_color(item.contentTitle, 'movie') else: item.title = '%s' % set_color(item.contentTitle, 'movie') - if item.contentType=='movie': + if item.contentType == 'movie': if item.context: if isinstance(item.context, list): item.context.append('Buscar esta pelicula en otros canales') - if 'Novedades' in item.category and item.from_channel=='news': - #logger.debug('novedades') - item.title = '%s [%s]'%(item.title, item.channel) + if ('Novedades' in item.category and item.from_channel == 'news'): + # logger.debug('novedades') + item.title = '%s [%s]' % (item.title, item.channel) # Verificamos si item.language es una lista, si lo es se toma # cada valor y se normaliza formado una nueva lista - if hasattr(item,'language') and item.language !='': - #logger.debug('tiene language: %s'%item.language) + if hasattr(item, 'language') and item.language != '': + # logger.debug('tiene language: %s'%item.language) if isinstance(item.language, list): - language_list =[] + language_list = [] for language in item.language: if language != '': lang = True language_list.append(set_lang(remove_format(language)).upper()) - #logger.debug('language_list: %s' % language_list) + # logger.debug('language_list: %s' % language_list) simple_language = language_list else: # Si item.language es un string se normaliza @@ -416,19 +436,19 @@ def title_format(item): else: simple_language = '' - #item.language = simple_language + # item.language = simple_language # Damos formato al año si existiera y lo agregamos # al titulo excepto que sea un episodio - if info and info.get("year", "") not in [""," "] and item.contentType != 'episode' and not info['season']: + if info and info.get("year", "") not in ["", " "] and item.contentType != 'episode' and not info['season']: try: year = '%s' % set_color(info['year'], 'year') item.title = item.title = '%s %s' % (item.title, year) except: - logger.debug('infoLabels: %s'%info) + logger.debug('infoLabels: %s' % info) # Damos formato al puntaje si existiera y lo agregamos al titulo - if info and info['rating'] and info['rating']!='0.0' and not info['season']: + if info and info['rating'] and info['rating'] != '0.0' and not info['season']: # Se normaliza el puntaje del rating @@ -454,13 +474,29 @@ def title_format(item): # Damos formato a la calidad si existiera y lo agregamos al titulo if item.quality and isinstance(item.quality, str): quality = item.quality.strip() - item.title = '%s %s' % (item.title, set_color(quality, 'quality')) else: quality = '' - # Damos formato al idioma si existiera y lo agregamos al titulo - if lang: - item.title = add_languages(item.title, simple_language) + # Damos formato al idioma-calidad si existieran y los agregamos al plot + quality_ = set_color(quality, 'quality') + + if (lang or quality) and item.action == "play": + if hasattr(item, "clean_plot"): + item.contentPlot = item.clear_plot + + if lang: item.title = add_languages(item.title, simple_language) + if quality: item.title = '%s %s' % (item.title, quality_) + + elif (lang or quality) and item.action != "play": + + if item.contentPlot: + item.clean_plot = item.contentPlot + plot_ = add_info_plot(item.contentPlot, simple_language, quality_) + item.contentPlot = plot_ + else: + item.clean_plot = None + plot_ = add_info_plot('', simple_language, quality_) + item.contentPlot = plot_ # Para las busquedas por canal if item.from_channel != '': @@ -469,17 +505,16 @@ def title_format(item): logger.debug(channel_parameters) item.title = '%s [%s]' % (item.title, channel_parameters['title']) - # Formato para actualizaciones de series en la videoteca sobreescribe los colores anteriores - if item.channel=='videolibrary' and item.context!='': - if item.action=='get_seasons': + if item.channel == 'videolibrary' and item.context != '': + if item.action == 'get_seasons': if 'Desactivar' in item.context[1]['title']: - item.title= '%s' % (set_color(item.title, 'update')) + item.title = '%s' % (set_color(item.title, 'update')) if 'Activar' in item.context[1]['title']: - item.title= '%s' % (set_color(item.title, 'no_update')) + item.title = '%s' % (set_color(item.title, 'no_update')) - #logger.debug('Despues del formato: %s' % item) + # logger.debug('Despues del formato: %s' % item) # Damos formato al servidor si existiera if item.server: server = '%s' % set_color(item.server.strip().capitalize(), 'server') @@ -487,18 +522,28 @@ def title_format(item): # Compureba si estamos en findvideos, y si hay server, si es asi no se muestra el # titulo sino el server, en caso contrario se muestra el titulo normalmente. - #logger.debug('item.title antes de server: %s'%item.title) + # logger.debug('item.title antes de server: %s'%item.title) if item.action != 'play' and item.server: - item.title ='%s %s'%(item.title, server.strip()) + item.title = '%s %s' % (item.title, server.strip()) + elif item.action == 'play' and item.server: + if hasattr(item, "clean_plot"): + item.contentPlot = item.clean_plot if item.quality == 'default': quality = '' - #logger.debug('language_color: %s'%language_color) - item.title = '%s %s' % (server, set_color(quality,'quality')) + # logger.debug('language_color: %s'%language_color) + item.title = '%s %s' % (server, set_color(quality, 'quality')) if lang: item.title = add_languages(item.title, simple_language) - #logger.debug('item.title: %s' % item.title) + # logger.debug('item.title: %s' % item.title) + # Torrent_info + if item.server == 'torrent' and item.torrent_info != '': + item.title = '%s [%s]' % (item.title, item.torrent_info) + + if item.channel == 'videolibrary': + item.title += ' [%s]' % item.contentChannel + # si hay verificacion de enlaces if item.alive != '': if item.alive.lower() == 'no': @@ -507,14 +552,15 @@ def title_format(item): item.title = '[[COLOR yellow][B]?[/B][/COLOR]] %s' % item.title else: item.title = '%s' % item.title - #logger.debug('item.title despues de server: %s' % item.title) + + # logger.debug('item.title despues de server: %s' % item.title) elif 'library' in item.action: item.title = '%s' % set_color(item.title, 'library') - elif item.action == '' and item.title !='': - item.title='**- %s -**'%item.title - else: + elif item.action == '' and item.title != '': + item.title = '**- %s -**' % item.title + elif item.unify: item.title = '%s' % set_color(item.title, 'otro') - #logger.debug('antes de salir %s' % item.title) + # logger.debug('antes de salir %s' % item.title) if visto: try: check = u'\u221a' @@ -528,8 +574,9 @@ def title_format(item): return item + def thumbnail_type(item): - #logger.info() + # logger.info() # Se comprueba que tipo de thumbnail se utilizara en findvideos, # Poster o Logo del servidor @@ -539,7 +586,7 @@ def thumbnail_type(item): item.contentThumbnail = item.thumbnail if info: - if info['thumbnail'] !='': + if info['thumbnail'] != '': item.contentThumbnail = info['thumbnail'] if item.action == 'play': @@ -548,7 +595,7 @@ def thumbnail_type(item): item.thumbnail = info['thumbnail'] elif thumb_type == 1: from core.servertools import get_server_parameters - #logger.debug('item.server: %s'%item.server) + # logger.debug('item.server: %s'%item.server) server_parameters = get_server_parameters(item.server.lower()) item.thumbnail = server_parameters.get("thumbnail", item.contentThumbnail) @@ -574,7 +621,7 @@ def check_rating(rating): try: # convertimos los deciamles p.e. 7.1 return "%.1f" % round(_rating, 1) - except Exception, ex_dl: + except Exception as ex_dl: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex_dl).__name__, ex_dl.args) logger.error(message) @@ -601,18 +648,18 @@ def check_rating(rating): def convert_float(_rating): try: return float(_rating) - except ValueError, ex_ve: + except ValueError as ex_ve: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex_ve).__name__, ex_ve.args) logger.error(message) return None - if type(rating) != float: + if not isinstance(rating, float): # logger.debug("no soy float") - if type(rating) == int: + if isinstance(rating, int): # logger.debug("soy int") rating = convert_float(rating) - elif type(rating) == str: + elif isinstance(rating, str): # logger.debug("soy str") rating = rating.replace("<", "") @@ -634,4 +681,4 @@ def check_rating(rating): rating = check_decimal_length(rating) rating = check_range(rating) - return rating + return rating \ No newline at end of file diff --git a/platformcode/xbmc_config_menu.py b/platformcode/xbmc_config_menu.py index b3e87a25..752f63fc 100644 --- a/platformcode/xbmc_config_menu.py +++ b/platformcode/xbmc_config_menu.py @@ -3,6 +3,14 @@ # XBMC Config Menu # ------------------------------------------------------------ +from __future__ import division +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int +from builtins import range +from past.utils import old_div + import inspect import os @@ -161,7 +169,7 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): self.callback = callback self.item = item - if type(custom_button) == dict: + if isinstance(custom_button, dict): self.custom_button = {} self.custom_button["label"] = custom_button.get("label", "") self.custom_button["function"] = custom_button.get("function", "") @@ -245,8 +253,10 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): def evaluate(self, index, cond): import re + ok = False + # Si la condicion es True o False, no hay mas que evaluar, ese es el valor - if type(cond) == bool: + if isinstance(cond, bool): return cond # Obtenemos las condiciones @@ -294,9 +304,9 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): pass # valor bool - if value.lower() == "true": + if not isinstance(value, int) and value.lower() == "true": value = True - elif value.lower() == "false": + elif not isinstance(value, int) and value.lower() == "false": value = False # operacion "eq" "igual a" @@ -515,7 +525,7 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): continue if c["type"] == "list" and "lvalues" not in c: continue - if c["type"] == "list" and not type(c["lvalues"]) == list: + if c["type"] == "list" and not isinstance(c["lvalues"], list): continue if c["type"] == "list" and not len(c["lvalues"]) > 0: continue @@ -590,7 +600,7 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): self.check_ok(self.values) def dispose_controls(self, index, focus=False, force=False): - show_controls = self.controls_height / self.height_control - 1 + show_controls = old_div(self.controls_height, self.height_control) - 1 visible_count = 0 @@ -609,7 +619,7 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): if index < 0: index = 0 new_index = index - if self.index <> new_index or force: + if self.index != new_index or force: for x, c in enumerate(self.visible_controls): if x < new_index or visible_count > show_controls or not c["show"]: self.set_visible(c, False) @@ -693,7 +703,7 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): else: self.return_value = getattr(cb_channel, self.custom_button['function'])(self.item, self.values) if not self.custom_button["close"]: - if isinstance(self.return_value, dict) and self.return_value.has_key("label"): + if isinstance(self.return_value, dict) and "label" in self.return_value: self.getControl(10006).setLabel(self.return_value['label']) for c in self.list_controls: @@ -936,11 +946,11 @@ class SettingsWindow(xbmcgui.WindowXMLDialog): elif action == 504: if self.xx > raw_action.getAmount2(): - if (self.xx - int(raw_action.getAmount2())) / self.height_control: + if old_div((self.xx - int(raw_action.getAmount2())), self.height_control): self.xx -= self.height_control self.dispose_controls(self.index + 1) else: - if (int(raw_action.getAmount2()) - self.xx) / self.height_control: + if old_div((int(raw_action.getAmount2()) - self.xx), self.height_control): self.xx += self.height_control self.dispose_controls(self.index - 1) return @@ -981,7 +991,7 @@ class ControlEdit(xbmcgui.ControlButton): def setWidth(self, w): xbmcgui.ControlButton.setWidth(self, w) - self.textControl.setWidth(w / 2) + self.textControl.setWidth(old_div(w, 2)) def setHeight(self, w): xbmcgui.ControlButton.setHeight(self, w) @@ -992,7 +1002,7 @@ class ControlEdit(xbmcgui.ControlButton): if xbmcgui.__version__ == "1.2": self.textControl.setPosition(x + self.getWidth(), y) else: - self.textControl.setPosition(x + self.getWidth() / 2, y) + self.textControl.setPosition(x + old_div(self.getWidth(), 2), y) def setText(self, text): self.text = text diff --git a/platformcode/xbmc_info_window.py b/platformcode/xbmc_info_window.py index fea52fa2..07c689fc 100644 --- a/platformcode/xbmc_info_window.py +++ b/platformcode/xbmc_info_window.py @@ -91,8 +91,7 @@ class InfoWindow(xbmcgui.WindowXMLDialog): En caso de peliculas: Coge el titulo de los siguientes campos (en este orden) 1. contentTitle (este tiene prioridad 1) - 2. fulltitle (este tiene prioridad 2) - 3. title (este tiene prioridad 3) + 2. title (este tiene prioridad 2) El primero que contenga "algo" lo interpreta como el titulo (es importante asegurarse que el titulo este en su sitio) diff --git a/platformcode/xbmc_videolibrary.py b/platformcode/xbmc_videolibrary.py index 3f0c1972..892c1eb6 100644 --- a/platformcode/xbmc_videolibrary.py +++ b/platformcode/xbmc_videolibrary.py @@ -3,17 +3,24 @@ # XBMC Library Tools # ------------------------------------------------------------ +from future import standard_library +standard_library.install_aliases() +#from builtins import str +import sys +PY3 = False +if sys.version_info[0] >= 3: PY3 = True; unicode = str; unichr = chr; long = int + import os import threading import time +import re -import urllib2 import xbmc - from core import filetools from core import jsontools from platformcode import config, logger from platformcode import platformtools +from core import scrapertools def mark_auto_as_watched(item): @@ -83,7 +90,6 @@ def sync_trakt_addon(path_folder): "special://home/addons/script.trakt/"] for path in paths: - import sys sys.path.append(xbmc.translatePath(path)) # se obtiene las series vistas @@ -94,10 +100,9 @@ def sync_trakt_addon(path_folder): return shows = traktapi.getShowsWatched({}) - shows = shows.items() + shows = list(shows.items()) # obtenemos el id de la serie para comparar - import re _id = re.findall("\[(.*?)\]", path_folder, flags=re.DOTALL)[0] logger.debug("el id es %s" % _id) @@ -329,9 +334,7 @@ def mark_season_as_watched_on_kodi(item, value=1): def mark_content_as_watched_on_alfa(path): from specials import videolibrary from core import videolibrarytools - from core import scrapertools - from core import filetools - import re + """ marca toda la serie o película como vista o no vista en la Videoteca de Alfa basado en su estado en la Videoteca de Kodi @type str: path @@ -361,6 +364,9 @@ def mark_content_as_watched_on_alfa(path): if "\\" in path: path = path.replace("/", "\\") head_nfo, item = videolibrarytools.read_nfo(path) #Leo el .nfo del contenido + if not item: + logger.error('.NFO no encontrado: ' + path) + return if FOLDER_TVSHOWS in path: #Compruebo si es CINE o SERIE contentType = "episode_view" #Marco la tabla de BBDD de Kodi Video @@ -379,7 +385,7 @@ def mark_content_as_watched_on_alfa(path): nfo_name = scrapertools.find_single_match(path2, '\]\/(.*?)$') #Construyo el nombre del .nfo path1 = path1.replace(nfo_name, '') #para la SQL solo necesito la carpeta path2 = path2.replace(nfo_name, '') #para la SQL solo necesito la carpeta - path2 = filetools.remove_smb_credential(path2) #Si el archivo está en un servidor SMB, quiamos las credenciales + path2 = filetools.remove_smb_credential(path2) #Si el archivo está en un servidor SMB, quitamos las credenciales #Ejecutmos la sentencia SQL sql = 'select strFileName, playCount from %s where (strPath like "%s" or strPath like "%s")' % (contentType, path1, path2) @@ -399,7 +405,11 @@ def mark_content_as_watched_on_alfa(path): playCount_final = 0 elif playCount >= 1: playCount_final = 1 - title_plain = title_plain.decode("utf-8").encode("utf-8") #Hacemos esto porque si no genera esto: u'title_plain' + + elif not PY3 and isinstance(title_plain, (str, unicode)): + title_plain = title_plain.decode("utf-8").encode("utf-8") #Hacemos esto porque si no genera esto: u'title_plain' + elif PY3 and isinstance(var, bytes): + title_plain = title_plain.decode('utf-8') item.library_playcounts.update({title_plain: playCount_final}) #actualizamos el playCount del .nfo if item.infoLabels['mediatype'] == "tvshow": #Actualizamos los playCounts de temporadas y Serie @@ -420,6 +430,7 @@ def get_data(payload): @param payload: data :return: """ + import urllib.request, urllib.error logger.info("payload: %s" % payload) # Required header for XBMC JSON-RPC calls, otherwise you'll get a 415 HTTP response code - Unsupported media type headers = {'content-type': 'application/json'} @@ -433,14 +444,14 @@ def get_data(payload): xbmc_json_rpc_url = "http://" + config.get_setting("xbmc_host", "videolibrary") + ":" + str( xbmc_port) + "/jsonrpc" - req = urllib2.Request(xbmc_json_rpc_url, data=jsontools.dump(payload), headers=headers) - f = urllib2.urlopen(req) + req = urllib.request.Request(xbmc_json_rpc_url, data=jsontools.dump(payload), headers=headers) + f = urllib.request.urlopen(req) response = f.read() f.close() logger.info("get_data: response %s" % response) data = jsontools.load(response) - except Exception, ex: + except Exception as ex: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error("error en xbmc_json_rpc_url: %s" % message) @@ -448,7 +459,7 @@ def get_data(payload): else: try: data = jsontools.load(xbmc.executeJSONRPC(jsontools.dump(payload))) - except Exception, ex: + except Exception as ex: template = "An exception of type %s occured. Arguments:\n%r" message = template % (type(ex).__name__, ex.args) logger.error("error en xbmc.executeJSONRPC: %s" % message) @@ -477,6 +488,7 @@ def update(folder_content=config.get_setting("folder_tvshows"), folder=""): } if folder: + folder = str(folder) videolibrarypath = config.get_videolibrary_config_path() if folder.endswith('/') or folder.endswith('\\'): @@ -489,9 +501,10 @@ def update(folder_content=config.get_setting("folder_tvshows"), folder=""): videolibrarypath = videolibrarypath[:-1] update_path = videolibrarypath + "/" + folder_content + "/" + folder + "/" else: - update_path = filetools.join(videolibrarypath, folder_content, folder) + "/" + #update_path = filetools.join(videolibrarypath, folder_content, folder) + "/" # Problemas de encode en "folder" + update_path = filetools.join(videolibrarypath, folder_content, ' ').rstrip() - if not update_path.startswith("smb://"): + if not scrapertools.find_single_match(update_path, '(^\w+:\/\/)'): payload["params"] = {"directory": update_path} while xbmc.getCondVisibility('Library.IsScanningVideo()'): @@ -663,7 +676,7 @@ def set_content(content_type, silent=False): if sql_videolibrarypath.startswith("special://"): sql_videolibrarypath = sql_videolibrarypath.replace('/profile/', '/%/').replace('/home/userdata/', '/%/') sep = '/' - elif sql_videolibrarypath.startswith("smb://"): + elif scrapertools.find_single_match(sql_videolibrarypath, '(^\w+:\/\/)'): sep = '/' else: sep = os.sep @@ -881,7 +894,7 @@ def add_sources(path): # Nodo nodo_name = xmldoc.createElement("name") sep = os.sep - if path.startswith("special://") or path.startswith("smb://"): + if path.startswith("special://") or scrapertools.find_single_match(path, '(^\w+:\/\/)'): sep = "/" name = path if path.endswith(sep):